6468748 assertion failure in dnode_sync
6490104 'zfs recv' can be very slow when processing large DRR_FREEOBJECTS record
6490105 assertion failure in dbuf_verify when doing zfs recv
6490829 panic in zfs_hash() while 'zfs recv' a zvol
--- a/usr/src/uts/common/fs/zfs/dmu_send.c Fri Nov 10 10:18:00 2006 -0800
+++ b/usr/src/uts/common/fs/zfs/dmu_send.c Fri Nov 10 11:24:28 2006 -0800
@@ -622,7 +622,8 @@
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;
--- a/usr/src/uts/common/fs/zfs/dnode.c Fri Nov 10 10:18:00 2006 -0800
+++ b/usr/src/uts/common/fs/zfs/dnode.c Fri Nov 10 11:24:28 2006 -0800
@@ -395,6 +395,7 @@
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 @@
/* 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 @@
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 @@
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);
}
--- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c Fri Nov 10 10:18:00 2006 -0800
+++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c Fri Nov 10 11:24:28 2006 -0800
@@ -677,7 +677,14 @@
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);