summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormm <mm@FreeBSD.org>2010-05-13 20:55:58 +0000
committermm <mm@FreeBSD.org>2010-05-13 20:55:58 +0000
commitcc11636cc42ff8dfd0229ccfea4c2c240e96f360 (patch)
treeb2e5826e17eda5f7f98901d8cb711f89c39a016a
parent3fb4e24eaea20e22c860c0de63f3f98c094cdf92 (diff)
downloadFreeBSD-src-cc11636cc42ff8dfd0229ccfea4c2c240e96f360.zip
FreeBSD-src-cc11636cc42ff8dfd0229ccfea4c2c240e96f360.tar.gz
Fix ZIL-related panic on zfs rollback.
OpenSolaris onnv-revision: 8746:e1d96ca6808c Approved by: pjd, delphij (mentor) Obtained from: OpenSolaris (Bug ID 6796377) MCF after: 1 week
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c30
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c6
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c25
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scrub.c11
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c33
5 files changed, 44 insertions, 61 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
index 69ad489..fe03304 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
@@ -1915,7 +1915,6 @@ dbuf_sync_leaf(dbuf_dirty_record_t *dr, dmu_tx_t *tx)
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));
@@ -2025,23 +2024,24 @@ dbuf_sync_leaf(dbuf_dirty_record_t *dr, dmu_tx_t *tx)
return;
}
- blksz = arc_buf_size(*datap);
-
- if (dn->dn_object != DMU_META_DNODE_OBJECT) {
+ if (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.
+ * 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).
+ * 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);
- }
+ 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);
}
ASSERT(*datap != NULL);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c
index 5e177c5d..15e789f 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c
@@ -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.
*/
@@ -226,10 +226,6 @@ traverse_visitbp(struct traverse_data *td, const dnode_phys_t *dnp,
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++) {
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
index 30e0836..622fa5d 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
@@ -1171,8 +1171,18 @@ kill_blkptr(spa_t *spa, blkptr_t *bp, const zbookmark_t *zb,
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);
}
@@ -1216,13 +1226,7 @@ dsl_dataset_rollback_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx)
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
@@ -1255,7 +1259,10 @@ dsl_dataset_rollback_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx)
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;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scrub.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scrub.c
index 950a91f..dededdf 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scrub.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scrub.c
@@ -344,6 +344,12 @@ traverse_zil_block(zilog_t *zilog, blkptr_t *bp, void *arg, uint64_t claim_txg)
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;
@@ -369,6 +375,11 @@ traverse_zil_record(zilog_t *zilog, lr_t *lrc, void *arg, uint64_t claim_txg)
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;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c
index 1e79091..4a0e8d5 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c
@@ -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.
*/
@@ -478,37 +478,6 @@ zil_destroy(zilog_t *zilog, boolean_t keep_first)
}
/*
- * 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);
-}
-
-/*
* return true if the initial log block is not valid
*/
static boolean_t
OpenPOWER on IntegriCloud