5959#include <sys/wait.h>
6060#include <zfs_prop.h>
6161#include <sys/fs/zfs.h>
62+ #include <sys/dsl_scan.h>
6263#include <sys/stat.h>
6364#include <sys/systeminfo.h>
6465#include <sys/fm/fs/zfs.h>
@@ -512,8 +513,9 @@ get_usage(zpool_help_t idx)
512513 return (gettext ("\tinitialize [-c | -s | -u] [-w] <-a | <pool> "
513514 "[<device> ...]>\n" ));
514515 case HELP_SCRUB :
515- return (gettext ("\tscrub [-e | -s | -p | -C | -E | -S] [-w] "
516- "<-a | <pool> [<pool> ...]>\n" ));
516+ return (gettext ("\tscrub [-e | -s | -p | -t | -C [-t] | "
517+ "(-E | -S) [-t]] [-w]\n"
518+ "\t <-a | <pool> [<pool> ...]>\n" ));
517519 case HELP_RESILVER :
518520 return (gettext ("\tresilver <pool> ...\n" ));
519521 case HELP_TRIM :
@@ -8518,7 +8520,7 @@ date_string_to_sec(const char *timestr, boolean_t rounding)
85188520}
85198521
85208522/*
8521- * zpool scrub [-e | -s | -p | -C | -E | -S] [-w] [-a | <pool> ...]
8523+ * zpool scrub [-e | -s | -p | -C | -E | -S | -t ] [-w] [-a | <pool> ...]
85228524 *
85238525 * -a Scrub all pools.
85248526 * -e Only scrub blocks in the error log.
@@ -8527,6 +8529,7 @@ date_string_to_sec(const char *timestr, boolean_t rounding)
85278529 * -s Stop. Stops any in-progress scrub.
85288530 * -p Pause. Pause in-progress scrub.
85298531 * -w Wait. Blocks until scrub has completed.
8532+ * -t Decompress and decrypt (if key is loaded) scrubbed blocks.
85308533 * -C Scrub from last saved txg.
85318534 */
85328535int
@@ -8538,24 +8541,26 @@ zpool_do_scrub(int argc, char **argv)
85388541 int error ;
85398542
85408543 cb .cb_type = POOL_SCAN_SCRUB ;
8541- cb .cb_scrub_cmd = POOL_SCRUB_NORMAL ;
8544+ cb .cb_scrub_cmd = 0 ;
85428545 cb .cb_date_start = cb .cb_date_end = 0 ;
85438546
85448547 boolean_t is_error_scrub = B_FALSE ;
85458548 boolean_t is_pause = B_FALSE ;
85468549 boolean_t is_stop = B_FALSE ;
8547- boolean_t is_txg_continue = B_FALSE ;
85488550 boolean_t scrub_all = B_FALSE ;
85498551
85508552 /* check options */
8551- while ((c = getopt (argc , argv , "aspweCE:S:" )) != -1 ) {
8553+ while ((c = getopt (argc , argv , "aspweCE:S:t " )) != -1 ) {
85528554 switch (c ) {
85538555 case 'a' :
85548556 scrub_all = B_TRUE ;
85558557 break ;
85568558 case 'e' :
85578559 is_error_scrub = B_TRUE ;
85588560 break ;
8561+ case 't' :
8562+ cb .cb_scrub_cmd |= POOL_SCRUB_THOROUGH ;
8563+ break ;
85598564 case 'E' :
85608565 /*
85618566 * Round the date. It's better to scrub more data than
@@ -8576,7 +8581,7 @@ zpool_do_scrub(int argc, char **argv)
85768581 wait = B_TRUE ;
85778582 break ;
85788583 case 'C' :
8579- is_txg_continue = B_TRUE ;
8584+ cb . cb_scrub_cmd |= POOL_SCRUB_FROM_LAST_TXG ;
85808585 break ;
85818586 case '?' :
85828587 (void ) fprintf (stderr , gettext ("invalid option '%c'\n" ),
@@ -8589,17 +8594,38 @@ zpool_do_scrub(int argc, char **argv)
85898594 (void ) fprintf (stderr , gettext ("invalid option "
85908595 "combination: -s and -p are mutually exclusive\n" ));
85918596 usage (B_FALSE );
8592- } else if (is_pause && is_txg_continue ) {
8597+ } else if (is_error_scrub && is_pause ) {
8598+ (void ) fprintf (stderr , gettext ("invalid option "
8599+ "combination: -e and -p are mutually exclusive\n" ));
8600+ usage (B_FALSE );
8601+ } else if (is_error_scrub && is_stop ) {
8602+ (void ) fprintf (stderr , gettext ("invalid option "
8603+ "combination: -e and -s are mutually exclusive\n" ));
8604+ usage (B_FALSE );
8605+ } else if (is_error_scrub &&
8606+ (cb .cb_scrub_cmd & POOL_SCRUB_FROM_LAST_TXG )) {
8607+ (void ) fprintf (stderr , gettext ("invalid option "
8608+ "combination: -e and -C are mutually exclusive\n" ));
8609+ usage (B_FALSE );
8610+ } else if (is_error_scrub && (cb .cb_scrub_cmd & POOL_SCRUB_THOROUGH )) {
8611+ (void ) fprintf (stderr , gettext ("invalid option "
8612+ "combination: -e and -t are mutually exclusive\n" ));
8613+ usage (B_FALSE );
8614+ } else if (is_pause && (cb .cb_scrub_cmd & POOL_SCRUB_FROM_LAST_TXG )) {
85938615 (void ) fprintf (stderr , gettext ("invalid option "
85948616 "combination: -p and -C are mutually exclusive\n" ));
85958617 usage (B_FALSE );
8596- } else if (is_stop && is_txg_continue ) {
8618+ } else if (is_pause && (cb .cb_scrub_cmd & POOL_SCRUB_THOROUGH )) {
8619+ (void ) fprintf (stderr , gettext ("invalid option "
8620+ "combination: -p and -t are mutually exclusive\n" ));
8621+ usage (B_FALSE );
8622+ } else if (is_stop && (cb .cb_scrub_cmd & POOL_SCRUB_FROM_LAST_TXG )) {
85978623 (void ) fprintf (stderr , gettext ("invalid option "
85988624 "combination: -s and -C are mutually exclusive\n" ));
85998625 usage (B_FALSE );
8600- } else if (is_error_scrub && is_txg_continue ) {
8626+ } else if (is_stop && ( cb . cb_scrub_cmd & POOL_SCRUB_THOROUGH ) ) {
86018627 (void ) fprintf (stderr , gettext ("invalid option "
8602- "combination: -e and -C are mutually exclusive\n" ));
8628+ "combination: -s and -t are mutually exclusive\n" ));
86038629 usage (B_FALSE );
86048630 } else {
86058631 if (is_error_scrub )
@@ -8609,19 +8635,28 @@ zpool_do_scrub(int argc, char **argv)
86098635 cb .cb_scrub_cmd = POOL_SCRUB_PAUSE ;
86108636 } else if (is_stop ) {
86118637 cb .cb_type = POOL_SCAN_NONE ;
8612- } else if (is_txg_continue ) {
8613- cb .cb_scrub_cmd = POOL_SCRUB_FROM_LAST_TXG ;
8614- } else {
8615- cb .cb_scrub_cmd = POOL_SCRUB_NORMAL ;
86168638 }
86178639 }
86188640
8641+ uint64_t scrub_kind = cb .cb_scrub_cmd & POOL_SCRUB_THOROUGH ;
8642+ if (scrub_kind == 0 )
8643+ scrub_kind = POOL_SCRUB_NORMAL ;
86198644 if ((cb .cb_date_start != 0 || cb .cb_date_end != 0 ) &&
8620- cb .cb_scrub_cmd != POOL_SCRUB_NORMAL ) {
8621- (void ) fprintf (stderr , gettext ("invalid option combination: "
8622- "start/end date is available only with normal scrub\n" ));
8645+ (cb .cb_scrub_cmd & POOL_SCRUB_FROM_LAST_TXG )) {
8646+ (void ) fprintf (stderr , gettext ("invalid option "
8647+ "combination: -C and -S/-E date are mutually "
8648+ "exclusive\n" ));
8649+ usage (B_FALSE );
8650+ } else if ((cb .cb_date_start != 0 || cb .cb_date_end != 0 ) &&
8651+ (is_error_scrub ||
8652+ (scrub_kind != POOL_SCRUB_NORMAL &&
8653+ scrub_kind != POOL_SCRUB_THOROUGH ))) {
8654+ (void ) fprintf (stderr , gettext ("invalid option "
8655+ "combination: start/end date is available only "
8656+ "with normal or thorough scrub\n" ));
86238657 usage (B_FALSE );
86248658 }
8659+
86258660 if (cb .cb_date_start != 0 && cb .cb_date_end != 0 &&
86268661 cb .cb_date_start > cb .cb_date_end ) {
86278662 (void ) fprintf (stderr , gettext ("invalid arguments: "
@@ -8941,7 +8976,7 @@ print_err_scrub_status(pool_scan_stat_t *ps)
89418976 * Print out detailed scrub status.
89428977 */
89438978static void
8944- print_scan_scrub_resilver_status (pool_scan_stat_t * ps )
8979+ print_scan_scrub_resilver_status (pool_scan_stat_t * ps , boolean_t is_thorough )
89458980{
89468981 time_t start , end , pause ;
89478982 uint64_t pass_scanned , scanned , pass_issued , issued , total_s , total_i ;
@@ -8976,10 +9011,11 @@ print_scan_scrub_resilver_status(pool_scan_stat_t *ps)
89769011 secs_to_dhms (end - start , time_buf );
89779012
89789013 if (is_scrub ) {
8979- (void ) printf (gettext ("scrub repaired %s "
8980- "in %s with %llu errors on %s" ), processed_buf ,
8981- time_buf , (u_longlong_t )ps -> pss_errors ,
8982- ctime (& end ));
9014+ (void ) printf (gettext ("%sscrub repaired %s "
9015+ "in %s with %llu errors on %s" ),
9016+ is_thorough ? "thorough " : "" ,
9017+ processed_buf , time_buf ,
9018+ (u_longlong_t )ps -> pss_errors , ctime (& end ));
89839019 } else if (is_resilver ) {
89849020 (void ) printf (gettext ("resilvered %s "
89859021 "in %s with %llu errors on %s" ), processed_buf ,
@@ -8989,7 +9025,8 @@ print_scan_scrub_resilver_status(pool_scan_stat_t *ps)
89899025 return ;
89909026 } else if (ps -> pss_state == DSS_CANCELED ) {
89919027 if (is_scrub ) {
8992- (void ) printf (gettext ("scrub canceled on %s" ),
9028+ (void ) printf (gettext ("%sscrub canceled on %s" ),
9029+ is_thorough ? "thorough " : "" ,
89939030 ctime (& end ));
89949031 } else if (is_resilver ) {
89959032 (void ) printf (gettext ("resilver canceled on %s" ),
@@ -9003,12 +9040,15 @@ print_scan_scrub_resilver_status(pool_scan_stat_t *ps)
90039040 /* Scan is in progress. Resilvers can't be paused. */
90049041 if (is_scrub ) {
90059042 if (pause == 0 ) {
9006- (void ) printf (gettext ("scrub in progress since %s" ),
9043+ (void ) printf (gettext ("%sscrub in progress since %s" ),
9044+ is_thorough ? "thorough " : "" ,
90079045 ctime (& start ));
90089046 } else {
9009- (void ) printf (gettext ("scrub paused since %s" ),
9047+ (void ) printf (gettext ("%sscrub paused since %s" ),
9048+ is_thorough ? "thorough " : "" ,
90109049 ctime (& pause ));
9011- (void ) printf (gettext ("\tscrub started on %s" ),
9050+ (void ) printf (gettext ("\t%sscrub started on %s" ),
9051+ is_thorough ? "thorough " : "" ,
90129052 ctime (& start ));
90139053 }
90149054 } else if (is_resilver ) {
@@ -10099,6 +10139,7 @@ print_scan_status(zpool_handle_t *zhp, nvlist_t *nvroot)
1009910139 pool_checkpoint_stat_t * pcs = NULL ;
1010010140 pool_scan_stat_t * ps = NULL ;
1010110141 uint_t c ;
10142+ boolean_t is_thorough = B_FALSE ;
1010210143 time_t scrub_start = 0 , errorscrub_start = 0 ;
1010310144
1010410145 if (nvlist_lookup_uint64_array (nvroot , ZPOOL_CONFIG_SCAN_STATS ,
@@ -10111,8 +10152,10 @@ print_scan_status(zpool_handle_t *zhp, nvlist_t *nvroot)
1011110152 have_resilver = (ps -> pss_func == POOL_SCAN_RESILVER );
1011210153 have_scrub = (ps -> pss_func == POOL_SCAN_SCRUB );
1011310154 scrub_start = ps -> pss_start_time ;
10114- if (c > offsetof(pool_scan_stat_t ,
10115- pss_pass_error_scrub_pause ) / 8 ) {
10155+ if (POOL_SCAN_STAT_VALID (pss_pass_scrub_flags , c ) &&
10156+ (ps -> pss_pass_scrub_flags & DSF_SCRUB_THOROUGH ) != 0 )
10157+ is_thorough = B_TRUE ;
10158+ if (POOL_SCAN_STAT_VALID (pss_pass_error_scrub_pause , c )) {
1011610159 have_errorscrub = (ps -> pss_error_scrub_func ==
1011710160 POOL_SCAN_ERRORSCRUB );
1011810161 errorscrub_start = ps -> pss_error_scrub_start ;
@@ -10124,7 +10167,7 @@ print_scan_status(zpool_handle_t *zhp, nvlist_t *nvroot)
1012410167
1012510168 /* Always print the scrub status when available. */
1012610169 if (have_scrub && scrub_start > errorscrub_start )
10127- print_scan_scrub_resilver_status (ps );
10170+ print_scan_scrub_resilver_status (ps , is_thorough );
1012810171 else if (have_errorscrub && errorscrub_start >= scrub_start )
1012910172 print_err_scrub_status (ps );
1013010173
@@ -10134,7 +10177,7 @@ print_scan_status(zpool_handle_t *zhp, nvlist_t *nvroot)
1013410177 */
1013510178 if (active_resilver || (!active_rebuild && have_resilver &&
1013610179 resilver_end_time && resilver_end_time > rebuild_end_time )) {
10137- print_scan_scrub_resilver_status (ps );
10180+ print_scan_scrub_resilver_status (ps , is_thorough );
1013810181 } else if (active_rebuild || (!active_resilver && have_rebuild &&
1013910182 rebuild_end_time && rebuild_end_time > resilver_end_time )) {
1014010183 print_rebuild_status (zhp , nvroot );
0 commit comments