Print this page
3956 ::vdev -r should work with pipelines
3957 ztest should update the cachefile before killing itself
3958 multiple scans can lead to partial resilvering
3959 ddt entries are not always resilvered
3960 dsl_scan can skip over dedup-ed blocks if physical birth != logical birth
3961 freed gang blocks are not resilvered and can cause pool to suspend
3962 ztest should print out zfs debug buffer before exiting
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Adam Leventhal <ahl@delphix.com>

@@ -192,10 +192,11 @@
         scn->scn_phys.scn_ddt_class_max = DDT_CLASSES - 1; /* the entire DDT */
         scn->scn_phys.scn_start_time = gethrestime_sec();
         scn->scn_phys.scn_errors = 0;
         scn->scn_phys.scn_to_examine = spa->spa_root_vdev->vdev_stat.vs_alloc;
         scn->scn_restart_txg = 0;
+        scn->scn_done_txg = 0;
         spa_scan_stat_init(spa);
 
         if (DSL_SCAN_IS_SCRUB_RESILVER(scn)) {
                 scn->scn_phys.scn_ddt_class_max = zfs_scrub_ddt_class_max;
 

@@ -767,11 +768,11 @@
          * are doing this on behalf of a deleted snapshot, and we will
          * revisit the future block on the next pass of this dataset.
          * Don't scan it now unless we need to because something
          * under it was modified.
          */
-        if (bp->blk_birth <= scn->scn_phys.scn_cur_max_txg) {
+        if (BP_PHYSICAL_BIRTH(bp) <= scn->scn_phys.scn_cur_max_txg) {
                 scan_funcs[scn->scn_phys.scn_func](dp, bp, zb);
         }
         if (buf)
                 (void) arc_buf_remove_ref(buf, &buf);
 }

@@ -1212,11 +1213,11 @@
         if (scn->scn_phys.scn_state != DSS_SCANNING)
                 return;
 
         for (int p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
                 if (ddp->ddp_phys_birth == 0 ||
-                    ddp->ddp_phys_birth > scn->scn_phys.scn_cur_max_txg)
+                    ddp->ddp_phys_birth > scn->scn_phys.scn_max_txg)
                         continue;
                 ddt_bp_create(checksum, ddk, ddp, &bp);
 
                 scn->scn_visited_this_txg++;
                 scan_funcs[scn->scn_phys.scn_func](scn->scn_dp, &bp, &zb);

@@ -1455,10 +1456,20 @@
         }
 
         if (scn->scn_phys.scn_state != DSS_SCANNING)
                 return;
 
+        if (scn->scn_done_txg == tx->tx_txg) {
+                ASSERT(!scn->scn_pausing);
+                /* finished with scan. */
+                zfs_dbgmsg("txg %llu scan complete", tx->tx_txg);
+                dsl_scan_done(scn, B_TRUE, tx);
+                ASSERT3U(spa->spa_scrub_inflight, ==, 0);
+                dsl_scan_sync_state(scn, tx);
+                return;
+        }
+
         if (scn->scn_phys.scn_ddt_bookmark.ddb_class <=
             scn->scn_phys.scn_ddt_class_max) {
                 zfs_dbgmsg("doing scan sync txg %llu; "
                     "ddt bm=%llu/%llu/%llu/%llx",
                     (longlong_t)tx->tx_txg,

@@ -1490,13 +1501,13 @@
         zfs_dbgmsg("visited %llu blocks in %llums",
             (longlong_t)scn->scn_visited_this_txg,
             (longlong_t)NSEC2MSEC(gethrtime() - scn->scn_sync_start_time));
 
         if (!scn->scn_pausing) {
-                /* finished with scan. */
-                zfs_dbgmsg("finished scan txg %llu", (longlong_t)tx->tx_txg);
-                dsl_scan_done(scn, B_TRUE, tx);
+                scn->scn_done_txg = tx->tx_txg + 1;
+                zfs_dbgmsg("txg %llu traversal complete, waiting till txg %llu",
+                    tx->tx_txg, scn->scn_done_txg);
         }
 
         if (DSL_SCAN_IS_SCRUB_RESILVER(scn)) {
                 mutex_enter(&spa->spa_scrub_lock);
                 while (spa->spa_scrub_inflight > 0) {