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>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/zfs/dsl_scan.c
          +++ new/usr/src/uts/common/fs/zfs/dsl_scan.c
↓ open down ↓ 186 lines elided ↑ open up ↑
 187  187          bzero(&scn->scn_phys, sizeof (scn->scn_phys));
 188  188          scn->scn_phys.scn_func = *funcp;
 189  189          scn->scn_phys.scn_state = DSS_SCANNING;
 190  190          scn->scn_phys.scn_min_txg = 0;
 191  191          scn->scn_phys.scn_max_txg = tx->tx_txg;
 192  192          scn->scn_phys.scn_ddt_class_max = DDT_CLASSES - 1; /* the entire DDT */
 193  193          scn->scn_phys.scn_start_time = gethrestime_sec();
 194  194          scn->scn_phys.scn_errors = 0;
 195  195          scn->scn_phys.scn_to_examine = spa->spa_root_vdev->vdev_stat.vs_alloc;
 196  196          scn->scn_restart_txg = 0;
      197 +        scn->scn_done_txg = 0;
 197  198          spa_scan_stat_init(spa);
 198  199  
 199  200          if (DSL_SCAN_IS_SCRUB_RESILVER(scn)) {
 200  201                  scn->scn_phys.scn_ddt_class_max = zfs_scrub_ddt_class_max;
 201  202  
 202  203                  /* rewrite all disk labels */
 203  204                  vdev_config_dirty(spa->spa_root_vdev);
 204  205  
 205  206                  if (vdev_resilver_needed(spa->spa_root_vdev,
 206  207                      &scn->scn_phys.scn_min_txg, &scn->scn_phys.scn_max_txg)) {
↓ open down ↓ 555 lines elided ↑ open up ↑
 762  763                  return;
 763  764          }
 764  765  
 765  766          /*
 766  767           * If this block is from the future (after cur_max_txg), then we
 767  768           * are doing this on behalf of a deleted snapshot, and we will
 768  769           * revisit the future block on the next pass of this dataset.
 769  770           * Don't scan it now unless we need to because something
 770  771           * under it was modified.
 771  772           */
 772      -        if (bp->blk_birth <= scn->scn_phys.scn_cur_max_txg) {
      773 +        if (BP_PHYSICAL_BIRTH(bp) <= scn->scn_phys.scn_cur_max_txg) {
 773  774                  scan_funcs[scn->scn_phys.scn_func](dp, bp, zb);
 774  775          }
 775  776          if (buf)
 776  777                  (void) arc_buf_remove_ref(buf, &buf);
 777  778  }
 778  779  
 779  780  static void
 780  781  dsl_scan_visit_rootbp(dsl_scan_t *scn, dsl_dataset_t *ds, blkptr_t *bp,
 781  782      dmu_tx_t *tx)
 782  783  {
↓ open down ↓ 424 lines elided ↑ open up ↑
1207 1208          const ddt_key_t *ddk = &dde->dde_key;
1208 1209          ddt_phys_t *ddp = dde->dde_phys;
1209 1210          blkptr_t bp;
1210 1211          zbookmark_t zb = { 0 };
1211 1212  
1212 1213          if (scn->scn_phys.scn_state != DSS_SCANNING)
1213 1214                  return;
1214 1215  
1215 1216          for (int p = 0; p < DDT_PHYS_TYPES; p++, ddp++) {
1216 1217                  if (ddp->ddp_phys_birth == 0 ||
1217      -                    ddp->ddp_phys_birth > scn->scn_phys.scn_cur_max_txg)
     1218 +                    ddp->ddp_phys_birth > scn->scn_phys.scn_max_txg)
1218 1219                          continue;
1219 1220                  ddt_bp_create(checksum, ddk, ddp, &bp);
1220 1221  
1221 1222                  scn->scn_visited_this_txg++;
1222 1223                  scan_funcs[scn->scn_phys.scn_func](scn->scn_dp, &bp, &zb);
1223 1224          }
1224 1225  }
1225 1226  
1226 1227  static void
1227 1228  dsl_scan_visit(dsl_scan_t *scn, dmu_tx_t *tx)
↓ open down ↓ 222 lines elided ↑ open up ↑
1450 1451                           */
1451 1452                          ddt_sync(spa, tx->tx_txg);
1452 1453                  }
1453 1454                  if (err == ERESTART)
1454 1455                          return;
1455 1456          }
1456 1457  
1457 1458          if (scn->scn_phys.scn_state != DSS_SCANNING)
1458 1459                  return;
1459 1460  
     1461 +        if (scn->scn_done_txg == tx->tx_txg) {
     1462 +                ASSERT(!scn->scn_pausing);
     1463 +                /* finished with scan. */
     1464 +                zfs_dbgmsg("txg %llu scan complete", tx->tx_txg);
     1465 +                dsl_scan_done(scn, B_TRUE, tx);
     1466 +                ASSERT3U(spa->spa_scrub_inflight, ==, 0);
     1467 +                dsl_scan_sync_state(scn, tx);
     1468 +                return;
     1469 +        }
     1470 +
1460 1471          if (scn->scn_phys.scn_ddt_bookmark.ddb_class <=
1461 1472              scn->scn_phys.scn_ddt_class_max) {
1462 1473                  zfs_dbgmsg("doing scan sync txg %llu; "
1463 1474                      "ddt bm=%llu/%llu/%llu/%llx",
1464 1475                      (longlong_t)tx->tx_txg,
1465 1476                      (longlong_t)scn->scn_phys.scn_ddt_bookmark.ddb_class,
1466 1477                      (longlong_t)scn->scn_phys.scn_ddt_bookmark.ddb_type,
1467 1478                      (longlong_t)scn->scn_phys.scn_ddt_bookmark.ddb_checksum,
1468 1479                      (longlong_t)scn->scn_phys.scn_ddt_bookmark.ddb_cursor);
1469 1480                  ASSERT(scn->scn_phys.scn_bookmark.zb_objset == 0);
↓ open down ↓ 15 lines elided ↑ open up ↑
1485 1496          dsl_scan_visit(scn, tx);
1486 1497          dsl_pool_config_exit(dp, FTAG);
1487 1498          (void) zio_wait(scn->scn_zio_root);
1488 1499          scn->scn_zio_root = NULL;
1489 1500  
1490 1501          zfs_dbgmsg("visited %llu blocks in %llums",
1491 1502              (longlong_t)scn->scn_visited_this_txg,
1492 1503              (longlong_t)NSEC2MSEC(gethrtime() - scn->scn_sync_start_time));
1493 1504  
1494 1505          if (!scn->scn_pausing) {
1495      -                /* finished with scan. */
1496      -                zfs_dbgmsg("finished scan txg %llu", (longlong_t)tx->tx_txg);
1497      -                dsl_scan_done(scn, B_TRUE, tx);
     1506 +                scn->scn_done_txg = tx->tx_txg + 1;
     1507 +                zfs_dbgmsg("txg %llu traversal complete, waiting till txg %llu",
     1508 +                    tx->tx_txg, scn->scn_done_txg);
1498 1509          }
1499 1510  
1500 1511          if (DSL_SCAN_IS_SCRUB_RESILVER(scn)) {
1501 1512                  mutex_enter(&spa->spa_scrub_lock);
1502 1513                  while (spa->spa_scrub_inflight > 0) {
1503 1514                          cv_wait(&spa->spa_scrub_io_cv,
1504 1515                              &spa->spa_scrub_lock);
1505 1516                  }
1506 1517                  mutex_exit(&spa->spa_scrub_lock);
1507 1518          }
↓ open down ↓ 216 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX