svn commit: r296513 - vendor-sys/illumos/dist/uts/common/fs/zfs

Alexander Motin mav at FreeBSD.org
Tue Mar 8 17:34:09 UTC 2016


Author: mav
Date: Tue Mar  8 17:34:07 2016
New Revision: 296513
URL: https://svnweb.freebsd.org/changeset/base/296513

Log:
  6450 scrub/resilver unnecessarily traverses snapshots created
  after the scrub started
  
  Reviewed by: George Wilson <george.wilson at delphix.com>
  Reviewed by: Prakash Surya <prakash.surya at delphix.com>
  Reviewed by: Richard Elling <Richard.Elling at RichardElling.com>
  Approved by: Richard Lowe <richlowe at richlowe.net>
  Author: Matthew Ahrens <mahrens at delphix.com>
  
  illumos/illumos-gate at 38d61036746e2273cc18f6698392e1e29f87d1bf

Modified:
  vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_scan.c

Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_scan.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_scan.c	Tue Mar  8 17:32:24 2016	(r296512)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_scan.c	Tue Mar  8 17:34:07 2016	(r296513)
@@ -819,7 +819,16 @@ dsl_scan_ds_destroyed(dsl_dataset_t *ds,
 
 	if (scn->scn_phys.scn_bookmark.zb_objset == ds->ds_object) {
 		if (ds->ds_is_snapshot) {
-			/* Note, scn_cur_{min,max}_txg stays the same. */
+			/*
+			 * Note:
+			 *  - scn_cur_{min,max}_txg stays the same.
+			 *  - Setting the flag is not really necessary if
+			 *    scn_cur_max_txg == scn_max_txg, because there
+			 *    is nothing after this snapshot that we care
+			 *    about.  However, we set it anyway and then
+			 *    ignore it when we retraverse it in
+			 *    dsl_scan_visitds().
+			 */
 			scn->scn_phys.scn_bookmark.zb_objset =
 			    dsl_dataset_phys(ds)->ds_next_snap_obj;
 			zfs_dbgmsg("destroying ds %llu; currently traversing; "
@@ -859,9 +868,6 @@ dsl_scan_ds_destroyed(dsl_dataset_t *ds,
 			zfs_dbgmsg("destroying ds %llu; in queue; removing",
 			    (u_longlong_t)ds->ds_object);
 		}
-	} else {
-		zfs_dbgmsg("destroying ds %llu; ignoring",
-		    (u_longlong_t)ds->ds_object);
 	}
 
 	/*
@@ -1014,6 +1020,46 @@ dsl_scan_visitds(dsl_scan_t *scn, uint64
 
 	VERIFY3U(0, ==, dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds));
 
+	if (scn->scn_phys.scn_cur_min_txg >=
+	    scn->scn_phys.scn_max_txg) {
+		/*
+		 * This can happen if this snapshot was created after the
+		 * scan started, and we already completed a previous snapshot
+		 * that was created after the scan started.  This snapshot
+		 * only references blocks with:
+		 *
+		 *	birth < our ds_creation_txg
+		 *	cur_min_txg is no less than ds_creation_txg.
+		 *	We have already visited these blocks.
+		 * or
+		 *	birth > scn_max_txg
+		 *	The scan requested not to visit these blocks.
+		 *
+		 * Subsequent snapshots (and clones) can reference our
+		 * blocks, or blocks with even higher birth times.
+		 * Therefore we do not need to visit them either,
+		 * so we do not add them to the work queue.
+		 *
+		 * Note that checking for cur_min_txg >= cur_max_txg
+		 * is not sufficient, because in that case we may need to
+		 * visit subsequent snapshots.  This happens when min_txg > 0,
+		 * which raises cur_min_txg.  In this case we will visit
+		 * this dataset but skip all of its blocks, because the
+		 * rootbp's birth time is < cur_min_txg.  Then we will
+		 * add the next snapshots/clones to the work queue.
+		 */
+		char *dsname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
+		dsl_dataset_name(ds, dsname);
+		zfs_dbgmsg("scanning dataset %llu (%s) is unnecessary because "
+		    "cur_min_txg (%llu) >= max_txg (%llu)",
+		    dsobj, dsname,
+		    scn->scn_phys.scn_cur_min_txg,
+		    scn->scn_phys.scn_max_txg);
+		kmem_free(dsname, MAXNAMELEN);
+
+		goto out;
+	}
+
 	if (dmu_objset_from_ds(ds, &os))
 		goto out;
 


More information about the svn-src-all mailing list