Author: mav
Date: Fri Oct 14 07:18:27 2016
New Revision: 307269
URL: https://svnweb.freebsd.org/changeset/base/307269

Log:
  MFC r305325: MFV r303078:
  7086 ztest attempts dva_get_dsize_sync on an embedded blockpointer
  
  illumos/illumos-gate@926549256b71acd595f69b236779ff6b78fa08ef
  
https://github.com/illumos/illumos-gate/commit/926549256b71acd595f69b236779ff6b7
  8fa08ef
  
  https://www.illumos.org/issues/7086
    In dbuf_dirty(), we need to grab the dn_struct_rwlock before looking at the
    db_blkptr, to prevent it from being changed by syncing context.
    Otherwise we may see that ztest got a segfault from this stack:
    libzpool.so.1`dva_get_dsize_sync+0x98(872f000, b32b240, fed7811b, 0, 
b4cda20,
  0)
    libzpool.so.1`bp_get_dsize+0x60(872f000, b32b240, 0, 97cb780, 9d4c1a8, 0)
    libzpool.so.1`dbuf_dirty+0x9b3(ce0a100, 97cb780, 9, fecd2530)
    libzpool.so.1`dmu_buf_will_dirty+0xc3(ce0a100, 97cb780, ea293d6c, 1)
    libzpool.so.1`zap_lockdir+0x1a0(8aaa3c0, 1, 0, 97cb780, 1, 1)
    libzpool.so.1`zap_remove_norm+0x30(8aaa3c0, 1, 0, 8728b10, 0, 97cb780)
    libzpool.so.1`zap_remove+0x29(8aaa3c0, 1, 0, 8728b10, 97cb780, a)
    ztest_replay_remove+0x225(ea294588, 8728ae8, 0, 38010000, 0, 0)
    ztest_remove+0x9f(ea294588, ea293f50, 4, 3)
    ztest_object_init+0x78(ea294588, ea293f50, 4e0, 1)
    ztest_dmu_object_alloc_free+0x71(ea294588, 13)
    ztest_dmu_objset_create_destroy+0x224(80cef08, 13, 0, 805d36c, 9017ad44, 0)
    ztest_execute+0x89(a, 807c720, 13, 0)
    ztest_thread+0xea(13, 0, 0, 0)
    libc.so.1`_thrp_setup+0x88(f0983240)
    libc.so.1`_lwp_start(f0983240, 0, 0, 0, 0, 0)
    Looking into it a bit, we see that this is an embedded blockpointer, so
    BP_GET_NDVAS should have returned 0:
         b32b240::blkptr
    EMBEDDED [L0 ZAP_OTHER] et=0 LZ4 size=200L/4aP birth=80L
    Instead, it looks like another thread is modifying this blockpointer:
         b32b240::ugrep | ::whatis
    f47a0e0c is in [ stack tid=0x19f ]
    ebd6ec40 is in [ stack tid=0x226 ]
    ea293bd0 is in [ stack tid=0x244 ]
    ea293be4 is in [ stack tid=0x244 ]
  
  Reviewed by: Prakash Surya <prakash.su...@delphix.com>
  Reviewed by: George Wilson <george.wil...@delphix.com>
  Approved by: Robert Mustacchi <r...@joyent.com>
  Author: Matthew Ahrens <mahr...@delphix.com>

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

Modified: stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
==============================================================================
--- stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c     Fri Oct 
14 07:16:51 2016        (r307268)
+++ stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c     Fri Oct 
14 07:18:27 2016        (r307269)
@@ -1662,7 +1662,20 @@ dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t 
                dnode_setdirty(dn, tx);
                DB_DNODE_EXIT(db);
                return (dr);
-       } else if (do_free_accounting) {
+       }
+
+       /*
+        * The dn_struct_rwlock prevents db_blkptr from changing
+        * due to a write from syncing context completing
+        * while we are running, so we want to acquire it before
+        * looking at db_blkptr.
+        */
+       if (!RW_WRITE_HELD(&dn->dn_struct_rwlock)) {
+               rw_enter(&dn->dn_struct_rwlock, RW_READER);
+               drop_struct_lock = TRUE;
+       }
+
+       if (do_free_accounting) {
                blkptr_t *bp = db->db_blkptr;
                int64_t willfree = (bp && !BP_IS_HOLE(bp)) ?
                    bp_get_dsize(os->os_spa, bp) : db->db.db_size;
@@ -1678,11 +1691,6 @@ dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t 
                dnode_willuse_space(dn, -willfree, tx);
        }
 
-       if (!RW_WRITE_HELD(&dn->dn_struct_rwlock)) {
-               rw_enter(&dn->dn_struct_rwlock, RW_READER);
-               drop_struct_lock = TRUE;
-       }
-
        if (db->db_level == 0) {
                dnode_new_blkid(dn, db->db_blkid, tx, drop_struct_lock);
                ASSERT(dn->dn_maxblkid >= db->db_blkid);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to