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,8 @@ 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 | -C | -E | -S | -t ] "
517+ "[-w] <-a | <pool> [<pool> ...]>\n" ));
517518 case HELP_RESILVER :
518519 return (gettext ("\tresilver <pool> ...\n" ));
519520 case HELP_TRIM :
@@ -8518,7 +8519,7 @@ date_string_to_sec(const char *timestr, boolean_t rounding)
85188519}
85198520
85208521/*
8521- * zpool scrub [-e | -s | -p | -C | -E | -S] [-w] [-a | <pool> ...]
8522+ * zpool scrub [-e | -s | -p | -C | -E | -S | -t ] [-w] [-a | <pool> ...]
85228523 *
85238524 * -a Scrub all pools.
85248525 * -e Only scrub blocks in the error log.
@@ -8527,6 +8528,7 @@ date_string_to_sec(const char *timestr, boolean_t rounding)
85278528 * -s Stop. Stops any in-progress scrub.
85288529 * -p Pause. Pause in-progress scrub.
85298530 * -w Wait. Blocks until scrub has completed.
8531+ * -t Decompress and decrypt (if key is loaded) scrubbed blocks.
85308532 * -C Scrub from last saved txg.
85318533 */
85328534int
@@ -8538,24 +8540,26 @@ zpool_do_scrub(int argc, char **argv)
85388540 int error ;
85398541
85408542 cb .cb_type = POOL_SCAN_SCRUB ;
8541- cb .cb_scrub_cmd = POOL_SCRUB_NORMAL ;
8543+ cb .cb_scrub_cmd = 0 ;
85428544 cb .cb_date_start = cb .cb_date_end = 0 ;
85438545
85448546 boolean_t is_error_scrub = B_FALSE ;
85458547 boolean_t is_pause = B_FALSE ;
85468548 boolean_t is_stop = B_FALSE ;
8547- boolean_t is_txg_continue = B_FALSE ;
85488549 boolean_t scrub_all = B_FALSE ;
85498550
85508551 /* check options */
8551- while ((c = getopt (argc , argv , "aspweCE:S:" )) != -1 ) {
8552+ while ((c = getopt (argc , argv , "aspweCE:S:t " )) != -1 ) {
85528553 switch (c ) {
85538554 case 'a' :
85548555 scrub_all = B_TRUE ;
85558556 break ;
85568557 case 'e' :
85578558 is_error_scrub = B_TRUE ;
85588559 break ;
8560+ case 't' :
8561+ cb .cb_scrub_cmd |= POOL_SCRUB_THOROUGH ;
8562+ break ;
85598563 case 'E' :
85608564 /*
85618565 * Round the date. It's better to scrub more data than
@@ -8576,7 +8580,7 @@ zpool_do_scrub(int argc, char **argv)
85768580 wait = B_TRUE ;
85778581 break ;
85788582 case 'C' :
8579- is_txg_continue = B_TRUE ;
8583+ cb . cb_scrub_cmd |= POOL_SCRUB_FROM_LAST_TXG ;
85808584 break ;
85818585 case '?' :
85828586 (void ) fprintf (stderr , gettext ("invalid option '%c'\n" ),
@@ -8589,18 +8593,31 @@ zpool_do_scrub(int argc, char **argv)
85898593 (void ) fprintf (stderr , gettext ("invalid option "
85908594 "combination: -s and -p are mutually exclusive\n" ));
85918595 usage (B_FALSE );
8592- } else if (is_pause && is_txg_continue ) {
8596+ } else if (is_pause && ( cb . cb_scrub_cmd & POOL_SCRUB_FROM_LAST_TXG ) ) {
85938597 (void ) fprintf (stderr , gettext ("invalid option "
85948598 "combination: -p and -C are mutually exclusive\n" ));
85958599 usage (B_FALSE );
8596- } else if (is_stop && is_txg_continue ) {
8600+ } else if (is_stop && ( cb . cb_scrub_cmd & POOL_SCRUB_FROM_LAST_TXG ) ) {
85978601 (void ) fprintf (stderr , gettext ("invalid option "
85988602 "combination: -s and -C are mutually exclusive\n" ));
85998603 usage (B_FALSE );
8600- } else if (is_error_scrub && is_txg_continue ) {
8604+ } else if (is_error_scrub &&
8605+ (cb .cb_scrub_cmd & POOL_SCRUB_FROM_LAST_TXG )) {
86018606 (void ) fprintf (stderr , gettext ("invalid option "
86028607 "combination: -e and -C are mutually exclusive\n" ));
86038608 usage (B_FALSE );
8609+ } else if (is_error_scrub && (cb .cb_scrub_cmd & POOL_SCRUB_THOROUGH )) {
8610+ (void ) fprintf (stderr , gettext ("invalid option "
8611+ "combination: -e and -t are mutually exclusive\n" ));
8612+ usage (B_FALSE );
8613+ } else if (is_pause && (cb .cb_scrub_cmd & POOL_SCRUB_THOROUGH )) {
8614+ (void ) fprintf (stderr , gettext ("invalid option "
8615+ "combination: -p and -t are mutually exclusive\n" ));
8616+ usage (B_FALSE );
8617+ } else if (is_stop && (cb .cb_scrub_cmd & POOL_SCRUB_THOROUGH )) {
8618+ (void ) fprintf (stderr , gettext ("invalid option "
8619+ "combination: -s and -t are mutually exclusive\n" ));
8620+ usage (B_FALSE );
86048621 } else {
86058622 if (is_error_scrub )
86068623 cb .cb_type = POOL_SCAN_ERRORSCRUB ;
@@ -8609,19 +8626,24 @@ zpool_do_scrub(int argc, char **argv)
86098626 cb .cb_scrub_cmd = POOL_SCRUB_PAUSE ;
86108627 } else if (is_stop ) {
86118628 cb .cb_type = POOL_SCAN_NONE ;
8612- } else if (is_txg_continue ) {
8613- cb .cb_scrub_cmd = POOL_SCRUB_FROM_LAST_TXG ;
86148629 } else {
8615- cb .cb_scrub_cmd = POOL_SCRUB_NORMAL ;
8630+ if ((cb .cb_scrub_cmd & (POOL_SCRUB_NORMAL |
8631+ POOL_SCRUB_THOROUGH )) == 0 )
8632+ cb .cb_scrub_cmd |= POOL_SCRUB_NORMAL ;
86168633 }
86178634 }
86188635
8636+ uint64_t scrub_kind = cb .cb_scrub_cmd & (POOL_SCRUB_NORMAL |
8637+ POOL_SCRUB_THOROUGH );
86198638 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" ));
8639+ scrub_kind != POOL_SCRUB_NORMAL &&
8640+ scrub_kind != POOL_SCRUB_THOROUGH ) {
8641+ (void ) fprintf (stderr , gettext ("invalid option "
8642+ "combination: start/end date is available only "
8643+ "with normal or thorough scrub\n" ));
86238644 usage (B_FALSE );
86248645 }
8646+
86258647 if (cb .cb_date_start != 0 && cb .cb_date_end != 0 &&
86268648 cb .cb_date_start > cb .cb_date_end ) {
86278649 (void ) fprintf (stderr , gettext ("invalid arguments: "
@@ -8941,7 +8963,7 @@ print_err_scrub_status(pool_scan_stat_t *ps)
89418963 * Print out detailed scrub status.
89428964 */
89438965static void
8944- print_scan_scrub_resilver_status (pool_scan_stat_t * ps )
8966+ print_scan_scrub_resilver_status (pool_scan_stat_t * ps , uint_t c )
89458967{
89468968 time_t start , end , pause ;
89478969 uint64_t pass_scanned , scanned , pass_issued , issued , total_s , total_i ;
@@ -8976,10 +8998,22 @@ print_scan_scrub_resilver_status(pool_scan_stat_t *ps)
89768998 secs_to_dhms (end - start , time_buf );
89778999
89789000 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 ));
9001+ boolean_t is_thorough =
9002+ (c > offsetof(pool_scan_stat_t ,
9003+ pss_pass_scrub_flags ) / 8 ) &&
9004+ (ps -> pss_pass_scrub_flags & DSF_SCRUB_THOROUGH ) !=
9005+ 0 ;
9006+ if (is_thorough ) {
9007+ (void ) printf (gettext ("thorough scrub repaired"
9008+ " %s in %s with %llu errors on %s" ),
9009+ processed_buf , time_buf ,
9010+ (u_longlong_t )ps -> pss_errors , ctime (& end ));
9011+ } else {
9012+ (void ) printf (gettext ("scrub repaired %s "
9013+ "in %s with %llu errors on %s" ),
9014+ processed_buf , time_buf ,
9015+ (u_longlong_t )ps -> pss_errors , ctime (& end ));
9016+ }
89839017 } else if (is_resilver ) {
89849018 (void ) printf (gettext ("resilvered %s "
89859019 "in %s with %llu errors on %s" ), processed_buf ,
@@ -8989,8 +9023,18 @@ print_scan_scrub_resilver_status(pool_scan_stat_t *ps)
89899023 return ;
89909024 } else if (ps -> pss_state == DSS_CANCELED ) {
89919025 if (is_scrub ) {
8992- (void ) printf (gettext ("scrub canceled on %s" ),
8993- ctime (& end ));
9026+ boolean_t is_thorough =
9027+ (c > offsetof(pool_scan_stat_t ,
9028+ pss_pass_scrub_flags ) / 8 ) &&
9029+ (ps -> pss_pass_scrub_flags & DSF_SCRUB_THOROUGH ) !=
9030+ 0 ;
9031+ if (is_thorough ) {
9032+ (void ) printf (gettext ("thorough scrub canceled"
9033+ " on %s" ), ctime (& end ));
9034+ } else {
9035+ (void ) printf (gettext ("scrub canceled on %s" ),
9036+ ctime (& end ));
9037+ }
89949038 } else if (is_resilver ) {
89959039 (void ) printf (gettext ("resilver canceled on %s" ),
89969040 ctime (& end ));
@@ -9002,14 +9046,30 @@ print_scan_scrub_resilver_status(pool_scan_stat_t *ps)
90029046
90039047 /* Scan is in progress. Resilvers can't be paused. */
90049048 if (is_scrub ) {
9049+ boolean_t is_thorough =
9050+ (c > offsetof(pool_scan_stat_t ,
9051+ pss_pass_scrub_flags ) / 8 ) &&
9052+ (ps -> pss_pass_scrub_flags & DSF_SCRUB_THOROUGH ) != 0 ;
90059053 if (pause == 0 ) {
9006- (void ) printf (gettext ("scrub in progress since %s" ),
9007- ctime (& start ));
9054+ if (is_thorough ) {
9055+ (void ) printf (gettext ("thorough scrub in "
9056+ "progress since %s" ), ctime (& start ));
9057+ } else {
9058+ (void ) printf (gettext ("scrub in progress "
9059+ "since %s" ), ctime (& start ));
9060+ }
90089061 } else {
9009- (void ) printf (gettext ("scrub paused since %s" ),
9010- ctime (& pause ));
9011- (void ) printf (gettext ("\tscrub started on %s" ),
9012- ctime (& start ));
9062+ if (is_thorough ) {
9063+ (void ) printf (gettext ("thorough scrub "
9064+ "paused since %s" ), ctime (& pause ));
9065+ (void ) printf (gettext ("\tthorough scrub "
9066+ "started on %s" ), ctime (& start ));
9067+ } else {
9068+ (void ) printf (gettext ("scrub paused since %s" ),
9069+ ctime (& pause ));
9070+ (void ) printf (gettext ("\tscrub started on %s" ),
9071+ ctime (& start ));
9072+ }
90139073 }
90149074 } else if (is_resilver ) {
90159075 (void ) printf (gettext ("resilver in progress since %s" ),
@@ -10124,7 +10184,7 @@ print_scan_status(zpool_handle_t *zhp, nvlist_t *nvroot)
1012410184
1012510185 /* Always print the scrub status when available. */
1012610186 if (have_scrub && scrub_start > errorscrub_start )
10127- print_scan_scrub_resilver_status (ps );
10187+ print_scan_scrub_resilver_status (ps , c );
1012810188 else if (have_errorscrub && errorscrub_start >= scrub_start )
1012910189 print_err_scrub_status (ps );
1013010190
@@ -10134,7 +10194,7 @@ print_scan_status(zpool_handle_t *zhp, nvlist_t *nvroot)
1013410194 */
1013510195 if (active_resilver || (!active_rebuild && have_resilver &&
1013610196 resilver_end_time && resilver_end_time > rebuild_end_time )) {
10137- print_scan_scrub_resilver_status (ps );
10197+ print_scan_scrub_resilver_status (ps , c );
1013810198 } else if (active_rebuild || (!active_resilver && have_rebuild &&
1013910199 rebuild_end_time && rebuild_end_time > resilver_end_time )) {
1014010200 print_rebuild_status (zhp , nvroot );
0 commit comments