Author: jpaetzel
Date: Thu Apr 27 16:38:28 2017
New Revision: 317511
URL: https://svnweb.freebsd.org/changeset/base/317511

Log:
  MFV 316896
  
  7580 ztest failure in dbuf_read_impl
  
  illumos/illumos-gate@1a01181fdc809f40c64d5c6881ae3e4521a9d9c7
  
https://github.com/illumos/illumos-gate/commit/1a01181fdc809f40c64d5c6881ae3e4521a9d9c7
  
  https://www.illumos.org/issues/7580
    We need to prevent any reader whenever we're about the zero out all the
    blkptrs. To do this we need to grab the dn_struct_rwlock as writer in
    dbuf_write_children_ready and free_children just prior to calling bzero.
  
  Reviewed by: Pavel Zakharov <pavel.zakha...@delphix.com>
  Reviewed by: Steve Gonczi <steve.gon...@delphix.com>
  Reviewed by: Matthew Ahrens <mahr...@delphix.com>
  Approved by: Dan McDonald <dan...@omniti.com>
  Author: George Wilson <george.wil...@delphix.com>

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c
Directory Properties:
  head/sys/cddl/contrib/opensolaris/   (props changed)

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c  Thu Apr 27 
16:32:42 2017        (r317510)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c  Thu Apr 27 
16:38:28 2017        (r317511)
@@ -3317,13 +3317,13 @@ dbuf_write_children_ready(zio_t *zio, ar
        dmu_buf_impl_t *db = vdb;
        dnode_t *dn;
        blkptr_t *bp;
-       uint64_t i;
-       int epbs;
+       unsigned int epbs, i;
 
        ASSERT3U(db->db_level, >, 0);
        DB_DNODE_ENTER(db);
        dn = DB_DNODE(db);
        epbs = dn->dn_phys->dn_indblkshift - SPA_BLKPTRSHIFT;
+       ASSERT3U(epbs, <, 31);
 
        /* Determine if all our children are holes */
        for (i = 0, bp = db->db.db_data; i < 1 << epbs; i++, bp++) {
@@ -3336,8 +3336,14 @@ dbuf_write_children_ready(zio_t *zio, ar
         * we may get compressed away.
         */
        if (i == 1 << epbs) {
-               /* didn't find any non-holes */
+               /*
+                * We only found holes. Grab the rwlock to prevent
+                * anybody from reading the blocks we're about to
+                * zero out.
+                */
+               rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
                bzero(db->db.db_data, db->db.db_size);
+               rw_exit(&dn->dn_struct_rwlock);
        }
        DB_DNODE_EXIT(db);
 }

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    Thu Apr 
27 16:32:42 2017        (r317510)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c    Thu Apr 
27 16:38:28 2017        (r317511)
@@ -236,8 +236,8 @@ free_children(dmu_buf_impl_t *db, uint64
        dnode_t *dn;
        blkptr_t *bp;
        dmu_buf_impl_t *subdb;
-       uint64_t start, end, dbstart, dbend, i;
-       int epbs, shift;
+       uint64_t start, end, dbstart, dbend;
+       unsigned int epbs, shift, i;
 
        /*
         * There is a small possibility that this block will not be cached:
@@ -254,6 +254,7 @@ free_children(dmu_buf_impl_t *db, uint64
        DB_DNODE_ENTER(db);
        dn = DB_DNODE(db);
        epbs = dn->dn_phys->dn_indblkshift - SPA_BLKPTRSHIFT;
+       ASSERT3U(epbs, <, 31);
        shift = (db->db_level - 1) * epbs;
        dbstart = db->db_blkid << epbs;
        start = blkid >> shift;
@@ -273,12 +274,12 @@ free_children(dmu_buf_impl_t *db, uint64
                FREE_VERIFY(db, start, end, tx);
                free_blocks(dn, bp, end-start+1, tx);
        } else {
-               for (i = start; i <= end; i++, bp++) {
+               for (uint64_t id = start; id <= end; id++, bp++) {
                        if (BP_IS_HOLE(bp))
                                continue;
                        rw_enter(&dn->dn_struct_rwlock, RW_READER);
                        VERIFY0(dbuf_hold_impl(dn, db->db_level - 1,
-                           i, TRUE, FALSE, FTAG, &subdb));
+                           id, TRUE, FALSE, FTAG, &subdb));
                        rw_exit(&dn->dn_struct_rwlock);
                        ASSERT3P(bp, ==, subdb->db_blkptr);
 
@@ -293,8 +294,14 @@ free_children(dmu_buf_impl_t *db, uint64
                        break;
        }
        if (i == 1 << epbs) {
-               /* didn't find any non-holes */
+               /*
+                * We only found holes. Grab the rwlock to prevent
+                * anybody from reading the blocks we're about to
+                * zero out.
+                */
+               rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
                bzero(db->db.db_data, db->db.db_size);
+               rw_exit(&dn->dn_struct_rwlock);
                free_blocks(dn, db->db_blkptr, 1, tx);
        } else {
                /*
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to