Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 26 Jul 2017 16:24:11 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r321537 - stable/11/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
Message-ID:  <201707261624.v6QGOBu4067944@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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@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@delphix.com>
  Reviewed by: Steve Gonczi <steve.gonczi@delphix.com>
  Reviewed by: Matthew Ahrens <mahrens@delphix.com>
  Approved by: Dan McDonald <danmcd@omniti.com>
  Author: George Wilson <george.wilson@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 {
 		/*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201707261624.v6QGOBu4067944>