diff options
Diffstat (limited to 'usr/src')
| -rw-r--r-- | usr/src/uts/common/fs/zfs/dmu_send.c | 3 | ||||
| -rw-r--r-- | usr/src/uts/common/fs/zfs/dnode.c | 21 | ||||
| -rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_ioctl.c | 9 |
3 files changed, 28 insertions, 5 deletions
diff --git a/usr/src/uts/common/fs/zfs/dmu_send.c b/usr/src/uts/common/fs/zfs/dmu_send.c index ddf73d609b..d78d47e4da 100644 --- a/usr/src/uts/common/fs/zfs/dmu_send.c +++ b/usr/src/uts/common/fs/zfs/dmu_send.c @@ -622,7 +622,8 @@ restore_freeobjects(struct restorearg *ra, objset_t *os, return (EINVAL); for (obj = drrfo->drr_firstobj; - obj < drrfo->drr_firstobj + drrfo->drr_numobjs; obj++) { + obj < drrfo->drr_firstobj + drrfo->drr_numobjs; + (void) dmu_object_next(os, &obj, FALSE, 0)) { dmu_tx_t *tx; int err; diff --git a/usr/src/uts/common/fs/zfs/dnode.c b/usr/src/uts/common/fs/zfs/dnode.c index a2a985eb26..8fd083167b 100644 --- a/usr/src/uts/common/fs/zfs/dnode.c +++ b/usr/src/uts/common/fs/zfs/dnode.c @@ -395,6 +395,7 @@ dnode_reallocate(dnode_t *dn, dmu_object_type_t ot, int blocksize, dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx) { int i; + dmu_buf_impl_t *db = NULL; ASSERT3U(blocksize, >=, SPA_MINBLOCKSIZE); ASSERT3U(blocksize, <=, SPA_MAXBLOCKSIZE); @@ -425,17 +426,25 @@ dnode_reallocate(dnode_t *dn, dmu_object_type_t ot, int blocksize, /* change blocksize */ rw_enter(&dn->dn_struct_rwlock, RW_WRITER); + if (blocksize != dn->dn_datablksz && + (!BP_IS_HOLE(&dn->dn_phys->dn_blkptr[0]) || + list_head(&dn->dn_dbufs) != NULL)) { + db = dbuf_hold(dn, 0, FTAG); + dbuf_new_size(db, blocksize, tx); + } dnode_setdblksz(dn, blocksize); dnode_setdirty(dn, tx); dn->dn_next_blksz[tx->tx_txg&TXG_MASK] = blocksize; rw_exit(&dn->dn_struct_rwlock); + if (db) { + dbuf_rele(db, FTAG); + db = NULL; + } /* change type */ dn->dn_type = ot; if (dn->dn_bonuslen != bonuslen) { - dmu_buf_impl_t *db = NULL; - /* change bonus size */ if (bonuslen == 0) bonuslen = 1; /* XXX */ @@ -453,7 +462,6 @@ dnode_reallocate(dnode_t *dn, dmu_object_type_t ot, int blocksize, db->db.db_size = bonuslen; mutex_exit(&db->db_mtx); dbuf_dirty(db, tx); - dbuf_rele(db, FTAG); } /* change bonus size and type */ @@ -465,6 +473,13 @@ dnode_reallocate(dnode_t *dn, dmu_object_type_t ot, int blocksize, dn->dn_compress = ZIO_COMPRESS_INHERIT; ASSERT3U(dn->dn_nblkptr, <=, DN_MAX_NBLKPTR); + /* + * NB: we have to do the dbuf_rele after we've changed the + * dn_bonuslen, for the sake of dbuf_verify(). + */ + if (db) + dbuf_rele(db, FTAG); + dn->dn_allocated_txg = tx->tx_txg; mutex_exit(&dn->dn_mtx); } diff --git a/usr/src/uts/common/fs/zfs/zfs_ioctl.c b/usr/src/uts/common/fs/zfs/zfs_ioctl.c index 8926563a4c..e8f9645dc0 100644 --- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c +++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c @@ -677,7 +677,14 @@ retry: if (zc->zc_nvlist_dst != 0 && (error = dsl_prop_get_all(os, &nv)) == 0) { dmu_objset_stats(os, nv); - if (dmu_objset_type(os) == DMU_OST_ZVOL) + /* + * NB: zvol_get_stats() will read the objset contents, + * which we aren't supposed to do with a + * DS_MODE_STANDARD open, because it could be + * inconsistent. So this is a bit of a workaround... + */ + if (!zc->zc_objset_stats.dds_inconsistent && + dmu_objset_type(os) == DMU_OST_ZVOL) VERIFY(zvol_get_stats(os, nv) == 0); error = put_nvlist(zc, nv); nvlist_free(nv); |
