changeset 8746:e1d96ca6808c

6796377 panic on rollback in space_map_add()
author Matthew Ahrens <Matthew.Ahrens@Sun.COM>
date Tue, 10 Feb 2009 13:01:10 -0800
parents 6864f0b4a0e6
children 73be8d78d904
files usr/src/uts/common/fs/zfs/dbuf.c usr/src/uts/common/fs/zfs/dmu_traverse.c usr/src/uts/common/fs/zfs/dsl_dataset.c usr/src/uts/common/fs/zfs/dsl_scrub.c usr/src/uts/common/fs/zfs/zil.c
diffstat 5 files changed, 48 insertions(+), 73 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/dbuf.c	Wed Feb 11 05:52:00 2009 +1100
+++ b/usr/src/uts/common/fs/zfs/dbuf.c	Tue Feb 10 13:01:10 2009 -0800
@@ -1943,7 +1943,6 @@
 	dnode_t *dn = db->db_dnode;
 	objset_impl_t *os = dn->dn_objset;
 	uint64_t txg = tx->tx_txg;
-	int blksz;
 
 	ASSERT(dmu_tx_is_syncing(tx));
 
@@ -2049,32 +2048,25 @@
 		return;
 	}
 
-	if (db->db_state != DB_NOFILL) {
-		blksz = arc_buf_size(*datap);
-
-		if (dn->dn_object != DMU_META_DNODE_OBJECT) {
-			/*
-			 * If this buffer is currently "in use" (i.e., there
-			 * are active holds and db_data still references it),
-			 * then make a copy before we start the write so that
-			 * any modifications from the open txg will not leak
-			 * into this write.
-			 *
-			 * NOTE: this copy does not need to be made for
-			 * objects only modified in the syncing context (e.g.
-			 * DNONE_DNODE blocks).
-			 */
-			if (refcount_count(&db->db_holds) > 1 &&
-			    *datap == db->db_buf) {
-				arc_buf_contents_t type =
-				    DBUF_GET_BUFC_TYPE(db);
-				*datap =
-				    arc_buf_alloc(os->os_spa, blksz, db, type);
-				bcopy(db->db.db_data, (*datap)->b_data, blksz);
-			}
-		}
-
-		ASSERT(*datap != NULL);
+	if (db->db_state != DB_NOFILL &&
+	    dn->dn_object != DMU_META_DNODE_OBJECT &&
+	    refcount_count(&db->db_holds) > 1 &&
+	    *datap == db->db_buf) {
+		/*
+		 * If this buffer is currently "in use" (i.e., there
+		 * are active holds and db_data still references it),
+		 * then make a copy before we start the write so that
+		 * any modifications from the open txg will not leak
+		 * into this write.
+		 *
+		 * NOTE: this copy does not need to be made for
+		 * objects only modified in the syncing context (e.g.
+		 * DNONE_DNODE blocks).
+		 */
+		int blksz = arc_buf_size(*datap);
+		arc_buf_contents_t type = DBUF_GET_BUFC_TYPE(db);
+		*datap = arc_buf_alloc(os->os_spa, blksz, db, type);
+		bcopy(db->db.db_data, (*datap)->b_data, blksz);
 	}
 	db->db_data_pending = dr;
 
--- a/usr/src/uts/common/fs/zfs/dmu_traverse.c	Wed Feb 11 05:52:00 2009 +1100
+++ b/usr/src/uts/common/fs/zfs/dmu_traverse.c	Tue Feb 10 13:01:10 2009 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -223,10 +223,6 @@
 			return (err);
 
 		osp = buf->b_data;
-		/*
-		 * traverse_zil is just here for zdb's leak checking.
-		 * For other consumers, there will be no ZIL blocks.
-		 */
 		traverse_zil(td, &osp->os_zil_header);
 
 		for (j = 0; j < osp->os_meta_dnode.dn_nblkptr; j++) {
--- a/usr/src/uts/common/fs/zfs/dsl_dataset.c	Wed Feb 11 05:52:00 2009 +1100
+++ b/usr/src/uts/common/fs/zfs/dsl_dataset.c	Tue Feb 10 13:01:10 2009 -0800
@@ -1164,8 +1164,18 @@
 	if (bp == NULL)
 		return (0);
 
-	ASSERT3U(bp->blk_birth, >, ka->ds->ds_phys->ds_prev_snap_txg);
-	(void) dsl_dataset_block_kill(ka->ds, bp, ka->zio, ka->tx);
+	if ((zb->zb_level == -1ULL && zb->zb_blkid != 0) ||
+	    (zb->zb_object != 0 && dnp == NULL)) {
+		/*
+		 * It's a block in the intent log.  It has no
+		 * accounting, so just free it.
+		 */
+		VERIFY3U(0, ==, dsl_free(ka->zio, ka->tx->tx_pool,
+		    ka->tx->tx_txg, bp, NULL, NULL, ARC_NOWAIT));
+	} else {
+		ASSERT3U(bp->blk_birth, >, ka->ds->ds_phys->ds_prev_snap_txg);
+		(void) dsl_dataset_block_kill(ka->ds, bp, ka->zio, ka->tx);
+	}
 
 	return (0);
 }
@@ -1209,13 +1219,7 @@
 
 	dmu_buf_will_dirty(ds->ds_dbuf, tx);
 
-	/*
-	 * Before the roll back destroy the zil.
-	 */
 	if (ds->ds_user_ptr != NULL) {
-		zil_rollback_destroy(
-		    ((objset_impl_t *)ds->ds_user_ptr)->os_zil, tx);
-
 		/*
 		 * We need to make sure that the objset_impl_t is reopened after
 		 * we do the rollback, otherwise it will have the wrong
@@ -1248,7 +1252,10 @@
 	    ds->ds_phys->ds_deadlist_obj));
 
 	{
-		/* Free blkptrs that we gave birth to */
+		/*
+		 * Free blkptrs that we gave birth to - this covers
+		 * claimed but not played log blocks too.
+		 */
 		zio_t *zio;
 		struct killarg ka;
 
--- a/usr/src/uts/common/fs/zfs/dsl_scrub.c	Wed Feb 11 05:52:00 2009 +1100
+++ b/usr/src/uts/common/fs/zfs/dsl_scrub.c	Tue Feb 10 13:01:10 2009 -0800
@@ -348,6 +348,12 @@
 	if (bp->blk_birth <= dp->dp_scrub_min_txg)
 		return;
 
+	/*
+	 * One block ("stumpy") can be allocated a long time ago; we
+	 * want to visit that one because it has been allocated
+	 * (on-disk) even if it hasn't been claimed (even though for
+	 * plain scrub there's nothing to do to it).
+	 */
 	if (claim_txg == 0 && bp->blk_birth >= spa_first_txg(dp->dp_spa))
 		return;
 
@@ -373,6 +379,11 @@
 		if (bp->blk_birth <= dp->dp_scrub_min_txg)
 			return;
 
+		/*
+		 * birth can be < claim_txg if this record's txg is
+		 * already txg sync'ed (but this log block contains
+		 * other records that are not synced)
+		 */
 		if (claim_txg == 0 || bp->blk_birth < claim_txg)
 			return;
 
--- a/usr/src/uts/common/fs/zfs/zil.c	Wed Feb 11 05:52:00 2009 +1100
+++ b/usr/src/uts/common/fs/zfs/zil.c	Tue Feb 10 13:01:10 2009 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -470,37 +470,6 @@
 	dmu_tx_commit(tx);
 }
 
-/*
- * zil_rollback_destroy() is only called by the rollback code.
- * We already have a syncing tx. Rollback has exclusive access to the
- * dataset, so we don't have to worry about concurrent zil access.
- * The actual freeing of any log blocks occurs in zil_sync() later in
- * this txg syncing phase.
- */
-void
-zil_rollback_destroy(zilog_t *zilog, dmu_tx_t *tx)
-{
-	const zil_header_t *zh = zilog->zl_header;
-	uint64_t txg;
-
-	if (BP_IS_HOLE(&zh->zh_log))
-		return;
-
-	txg = dmu_tx_get_txg(tx);
-	ASSERT3U(zilog->zl_destroy_txg, <, txg);
-	zilog->zl_destroy_txg = txg;
-	zilog->zl_keep_first = B_FALSE;
-
-	/*
-	 * Ensure there's no outstanding ZIL IO.  No lwbs or just the
-	 * unused one that allocated in advance is ok.
-	 */
-	ASSERT(zilog->zl_lwb_list.list_head.list_next ==
-	    zilog->zl_lwb_list.list_head.list_prev);
-	(void) zil_parse(zilog, zil_free_log_block, zil_free_log_record,
-	    tx, zh->zh_claim_txg);
-}
-
 int
 zil_claim(char *osname, void *txarg)
 {