6468748 assertion failure in dnode_sync
authorahrens
Fri, 10 Nov 2006 11:24:28 -0800
changeset 3087 62df4acfd5cb
parent 3086 822e7a20b543
child 3088 0f31cbe575ba
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
usr/src/uts/common/fs/zfs/dmu_send.c
usr/src/uts/common/fs/zfs/dnode.c
usr/src/uts/common/fs/zfs/zfs_ioctl.c
--- 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);