Author: mm
Date: Thu May 13 20:55:58 2010
New Revision: 208050
URL: http://svn.freebsd.org/changeset/base/208050

Log:
  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

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scrub.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c  Thu May 13 
20:51:20 2010        (r208049)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c  Thu May 13 
20:55:58 2010        (r208050)
@@ -1915,7 +1915,6 @@ dbuf_sync_leaf(dbuf_dirty_record_t *dr, 
        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, 
                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);

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c  Thu May 
13 20:51:20 2010        (r208049)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c  Thu May 
13 20:55:58 2010        (r208050)
@@ -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 *t
                        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++) {

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c   Thu May 
13 20:51:20 2010        (r208049)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c   Thu May 
13 20:55:58 2010        (r208050)
@@ -1171,8 +1171,18 @@ kill_blkptr(spa_t *spa, blkptr_t *bp, co
        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, vo
 
        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, vo
            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;
 

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scrub.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scrub.c     Thu May 
13 20:51:20 2010        (r208049)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scrub.c     Thu May 
13 20:55:58 2010        (r208050)
@@ -344,6 +344,12 @@ traverse_zil_block(zilog_t *zilog, blkpt
        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
                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;
 

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c   Thu May 13 
20:51:20 2010        (r208049)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c   Thu May 13 
20:55:58 2010        (r208050)
@@ -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 ke
 }
 
 /*
- * 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
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to