Author: pjd
Date: Mon Aug 31 16:27:00 2009
New Revision: 196703
URL: http://svn.freebsd.org/changeset/base/196703

Log:
  Backport the 'dirtying dbuf' panic fix from newer ZFS version.
  
  Reported by:  Thomas Backman <[email protected]>
  MFC after:    1 week

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c      Mon Aug 
31 16:25:55 2009        (r196702)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c      Mon Aug 
31 16:27:00 2009        (r196703)
@@ -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.
  */
 
@@ -864,10 +864,11 @@ restore_object(struct restorearg *ra, ob
                /* currently allocated, want to be allocated */
                dmu_tx_hold_bonus(tx, drro->drr_object);
                /*
-                * We may change blocksize, so need to
-                * hold_write
+                * We may change blocksize and delete old content,
+                * so need to hold_write and hold_free.
                 */
                dmu_tx_hold_write(tx, drro->drr_object, 0, 1);
+               dmu_tx_hold_free(tx, drro->drr_object, 0, DMU_OBJECT_END);
                err = dmu_tx_assign(tx, TXG_WAIT);
                if (err) {
                        dmu_tx_abort(tx);

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c Mon Aug 31 
16:25:55 2009        (r196702)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c Mon Aug 31 
16:27:00 2009        (r196703)
@@ -415,7 +415,7 @@ void
 dnode_reallocate(dnode_t *dn, dmu_object_type_t ot, int blocksize,
     dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
 {
-       int i, old_nblkptr;
+       int i, nblkptr;
        dmu_buf_impl_t *db = NULL;
 
        ASSERT3U(blocksize, >=, SPA_MINBLOCKSIZE);
@@ -445,6 +445,8 @@ dnode_reallocate(dnode_t *dn, dmu_object
                dnode_free_range(dn, 0, -1ULL, tx);
        }
 
+       nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT);
+
        /* change blocksize */
        rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
        if (blocksize != dn->dn_datablksz &&
@@ -457,6 +459,8 @@ dnode_reallocate(dnode_t *dn, dmu_object
        dnode_setdirty(dn, tx);
        dn->dn_next_bonuslen[tx->tx_txg&TXG_MASK] = bonuslen;
        dn->dn_next_blksz[tx->tx_txg&TXG_MASK] = blocksize;
+       if (dn->dn_nblkptr != nblkptr)
+               dn->dn_next_nblkptr[tx->tx_txg&TXG_MASK] = nblkptr;
        rw_exit(&dn->dn_struct_rwlock);
        if (db)
                dbuf_rele(db, FTAG);
@@ -466,19 +470,15 @@ dnode_reallocate(dnode_t *dn, dmu_object
 
        /* change bonus size and type */
        mutex_enter(&dn->dn_mtx);
-       old_nblkptr = dn->dn_nblkptr;
        dn->dn_bonustype = bonustype;
        dn->dn_bonuslen = bonuslen;
-       dn->dn_nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT);
+       dn->dn_nblkptr = nblkptr;
        dn->dn_checksum = ZIO_CHECKSUM_INHERIT;
        dn->dn_compress = ZIO_COMPRESS_INHERIT;
        ASSERT3U(dn->dn_nblkptr, <=, DN_MAX_NBLKPTR);
 
-       /* XXX - for now, we can't make nblkptr smaller */
-       ASSERT3U(dn->dn_nblkptr, >=, old_nblkptr);
-
-       /* fix up the bonus db_size if dn_nblkptr has changed */
-       if (dn->dn_bonus && dn->dn_bonuslen != old_nblkptr) {
+       /* fix up the bonus db_size */
+       if (dn->dn_bonus) {
                dn->dn_bonus->db.db_size =
                    DN_MAX_BONUSLEN - (dn->dn_nblkptr-1) * sizeof (blkptr_t);
                ASSERT(dn->dn_bonuslen <= dn->dn_bonus->db.db_size);

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c    Mon Aug 
31 16:25:55 2009        (r196702)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c    Mon Aug 
31 16:27:00 2009        (r196703)
@@ -19,12 +19,10 @@
  * 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.
  */
 
-#pragma ident  "%Z%%M% %I%     %E% SMI"
-
 #include <sys/zfs_context.h>
 #include <sys/dbuf.h>
 #include <sys/dnode.h>
@@ -534,18 +532,12 @@ dnode_sync(dnode_t *dn, dmu_tx_t *tx)
                        /* XXX shouldn't the phys already be zeroed? */
                        bzero(dnp, DNODE_CORE_SIZE);
                        dnp->dn_nlevels = 1;
+                       dnp->dn_nblkptr = dn->dn_nblkptr;
                }
 
-               if (dn->dn_nblkptr > dnp->dn_nblkptr) {
-                       /* zero the new blkptrs we are gaining */
-                       bzero(dnp->dn_blkptr + dnp->dn_nblkptr,
-                           sizeof (blkptr_t) *
-                           (dn->dn_nblkptr - dnp->dn_nblkptr));
-               }
                dnp->dn_type = dn->dn_type;
                dnp->dn_bonustype = dn->dn_bonustype;
                dnp->dn_bonuslen = dn->dn_bonuslen;
-               dnp->dn_nblkptr = dn->dn_nblkptr;
        }
 
        ASSERT(dnp->dn_nlevels > 1 ||
@@ -605,6 +597,30 @@ dnode_sync(dnode_t *dn, dmu_tx_t *tx)
                return;
        }
 
+       if (dn->dn_next_nblkptr[txgoff]) {
+               /* this should only happen on a realloc */
+               ASSERT(dn->dn_allocated_txg == tx->tx_txg);
+               if (dn->dn_next_nblkptr[txgoff] > dnp->dn_nblkptr) {
+                       /* zero the new blkptrs we are gaining */
+                       bzero(dnp->dn_blkptr + dnp->dn_nblkptr,
+                           sizeof (blkptr_t) *
+                           (dn->dn_next_nblkptr[txgoff] - dnp->dn_nblkptr));
+#ifdef ZFS_DEBUG
+               } else {
+                       int i;
+                       ASSERT(dn->dn_next_nblkptr[txgoff] < dnp->dn_nblkptr);
+                       /* the blkptrs we are losing better be unallocated */
+                       for (i = dn->dn_next_nblkptr[txgoff];
+                           i < dnp->dn_nblkptr; i++)
+                               ASSERT(BP_IS_HOLE(&dnp->dn_blkptr[i]));
+#endif
+               }
+               mutex_enter(&dn->dn_mtx);
+               dnp->dn_nblkptr = dn->dn_next_nblkptr[txgoff];
+               dn->dn_next_nblkptr[txgoff] = 0;
+               mutex_exit(&dn->dn_mtx);
+       }
+
        if (dn->dn_next_nlevels[txgoff]) {
                dnode_increase_indirection(dn, tx);
                dn->dn_next_nlevels[txgoff] = 0;

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h     Mon Aug 
31 16:25:55 2009        (r196702)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h     Mon Aug 
31 16:27:00 2009        (r196703)
@@ -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.
  */
 
@@ -160,6 +160,7 @@ typedef struct dnode {
        uint16_t dn_datablkszsec;       /* in 512b sectors */
        uint32_t dn_datablksz;          /* in bytes */
        uint64_t dn_maxblkid;
+       uint8_t dn_next_nblkptr[TXG_SIZE];
        uint8_t dn_next_nlevels[TXG_SIZE];
        uint8_t dn_next_indblkshift[TXG_SIZE];
        uint16_t dn_next_bonuslen[TXG_SIZE];
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to