svn commit: r321537 - stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
Alexander Motin
mav at FreeBSD.org
Wed Jul 26 16:24:12 UTC 2017
Author: mav
Date: Wed Jul 26 16:24:11 2017
New Revision: 321537
URL: https://svnweb.freebsd.org/changeset/base/321537
Log:
MFC r317511: MFV 316896
7580 ztest failure in dbuf_read_impl
illumos/illumos-gate at 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.zakharov at delphix.com>
Reviewed by: Steve Gonczi <steve.gonczi at delphix.com>
Reviewed by: Matthew Ahrens <mahrens at delphix.com>
Approved by: Dan McDonald <danmcd at omniti.com>
Author: George Wilson <george.wilson at delphix.com>
Modified:
stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.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 Wed Jul 26 16:23:30 2017 (r321536)
+++ stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c Wed Jul 26 16:24:11 2017 (r321537)
@@ -3317,13 +3317,13 @@ dbuf_write_children_ready(zio_t *zio, arc_buf_t *buf,
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, arc_buf_t *buf,
* 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: stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c
==============================================================================
--- stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c Wed Jul 26 16:23:30 2017 (r321536)
+++ stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c Wed Jul 26 16:24:11 2017 (r321537)
@@ -236,8 +236,8 @@ free_children(dmu_buf_impl_t *db, uint64_t blkid, uint
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_t blkid, uint
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_t blkid, uint
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_t blkid, uint
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 {
/*
More information about the svn-src-all
mailing list