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,30 @@ 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+ (cb .cb_scrub_cmd & POOL_SCRUB_FROM_LAST_TXG )) {
8640+ (void ) fprintf (stderr , gettext ("invalid option "
8641+ "combination: -C and -S/-E date are mutually "
8642+ "exclusive\n" ));
8643+ usage (B_FALSE );
8644+ } else if ((cb .cb_date_start != 0 || cb .cb_date_end != 0 ) &&
8645+ scrub_kind != POOL_SCRUB_NORMAL &&
8646+ scrub_kind != POOL_SCRUB_THOROUGH ) {
8647+ (void ) fprintf (stderr , gettext ("invalid option "
8648+ "combination: start/end date is available only "
8649+ "with normal or thorough scrub\n" ));
86238650 usage (B_FALSE );
86248651 }
8652+
86258653 if (cb .cb_date_start != 0 && cb .cb_date_end != 0 &&
86268654 cb .cb_date_start > cb .cb_date_end ) {
86278655 (void ) fprintf (stderr , gettext ("invalid arguments: "
@@ -8941,7 +8969,7 @@ print_err_scrub_status(pool_scan_stat_t *ps)
89418969 * Print out detailed scrub status.
89428970 */
89438971static void
8944- print_scan_scrub_resilver_status (pool_scan_stat_t * ps )
8972+ print_scan_scrub_resilver_status (pool_scan_stat_t * ps , uint_t c )
89458973{
89468974 time_t start , end , pause ;
89478975 uint64_t pass_scanned , scanned , pass_issued , issued , total_s , total_i ;
@@ -8976,10 +9004,22 @@ print_scan_scrub_resilver_status(pool_scan_stat_t *ps)
89769004 secs_to_dhms (end - start , time_buf );
89779005
89789006 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 ));
9007+ boolean_t is_thorough =
9008+ (c > offsetof(pool_scan_stat_t ,
9009+ pss_pass_scrub_flags ) / 8 ) &&
9010+ (ps -> pss_pass_scrub_flags & DSF_SCRUB_THOROUGH ) !=
9011+ 0 ;
9012+ if (is_thorough ) {
9013+ (void ) printf (gettext ("thorough scrub repaired"
9014+ " %s in %s with %llu errors on %s" ),
9015+ processed_buf , time_buf ,
9016+ (u_longlong_t )ps -> pss_errors , ctime (& end ));
9017+ } else {
9018+ (void ) printf (gettext ("scrub repaired %s "
9019+ "in %s with %llu errors on %s" ),
9020+ processed_buf , time_buf ,
9021+ (u_longlong_t )ps -> pss_errors , ctime (& end ));
9022+ }
89839023 } else if (is_resilver ) {
89849024 (void ) printf (gettext ("resilvered %s "
89859025 "in %s with %llu errors on %s" ), processed_buf ,
@@ -8989,8 +9029,18 @@ print_scan_scrub_resilver_status(pool_scan_stat_t *ps)
89899029 return ;
89909030 } else if (ps -> pss_state == DSS_CANCELED ) {
89919031 if (is_scrub ) {
8992- (void ) printf (gettext ("scrub canceled on %s" ),
8993- ctime (& end ));
9032+ boolean_t is_thorough =
9033+ (c > offsetof(pool_scan_stat_t ,
9034+ pss_pass_scrub_flags ) / 8 ) &&
9035+ (ps -> pss_pass_scrub_flags & DSF_SCRUB_THOROUGH ) !=
9036+ 0 ;
9037+ if (is_thorough ) {
9038+ (void ) printf (gettext ("thorough scrub canceled"
9039+ " on %s" ), ctime (& end ));
9040+ } else {
9041+ (void ) printf (gettext ("scrub canceled on %s" ),
9042+ ctime (& end ));
9043+ }
89949044 } else if (is_resilver ) {
89959045 (void ) printf (gettext ("resilver canceled on %s" ),
89969046 ctime (& end ));
@@ -9002,14 +9052,30 @@ print_scan_scrub_resilver_status(pool_scan_stat_t *ps)
90029052
90039053 /* Scan is in progress. Resilvers can't be paused. */
90049054 if (is_scrub ) {
9055+ boolean_t is_thorough =
9056+ (c > offsetof(pool_scan_stat_t ,
9057+ pss_pass_scrub_flags ) / 8 ) &&
9058+ (ps -> pss_pass_scrub_flags & DSF_SCRUB_THOROUGH ) != 0 ;
90059059 if (pause == 0 ) {
9006- (void ) printf (gettext ("scrub in progress since %s" ),
9007- ctime (& start ));
9060+ if (is_thorough ) {
9061+ (void ) printf (gettext ("thorough scrub in "
9062+ "progress since %s" ), ctime (& start ));
9063+ } else {
9064+ (void ) printf (gettext ("scrub in progress "
9065+ "since %s" ), ctime (& start ));
9066+ }
90089067 } else {
9009- (void ) printf (gettext ("scrub paused since %s" ),
9010- ctime (& pause ));
9011- (void ) printf (gettext ("\tscrub started on %s" ),
9012- ctime (& start ));
9068+ if (is_thorough ) {
9069+ (void ) printf (gettext ("thorough scrub "
9070+ "paused since %s" ), ctime (& pause ));
9071+ (void ) printf (gettext ("\tthorough scrub "
9072+ "started on %s" ), ctime (& start ));
9073+ } else {
9074+ (void ) printf (gettext ("scrub paused since %s" ),
9075+ ctime (& pause ));
9076+ (void ) printf (gettext ("\tscrub started on %s" ),
9077+ ctime (& start ));
9078+ }
90139079 }
90149080 } else if (is_resilver ) {
90159081 (void ) printf (gettext ("resilver in progress since %s" ),
@@ -10124,7 +10190,7 @@ print_scan_status(zpool_handle_t *zhp, nvlist_t *nvroot)
1012410190
1012510191 /* Always print the scrub status when available. */
1012610192 if (have_scrub && scrub_start > errorscrub_start )
10127- print_scan_scrub_resilver_status (ps );
10193+ print_scan_scrub_resilver_status (ps , c );
1012810194 else if (have_errorscrub && errorscrub_start >= scrub_start )
1012910195 print_err_scrub_status (ps );
1013010196
@@ -10134,7 +10200,7 @@ print_scan_status(zpool_handle_t *zhp, nvlist_t *nvroot)
1013410200 */
1013510201 if (active_resilver || (!active_rebuild && have_resilver &&
1013610202 resilver_end_time && resilver_end_time > rebuild_end_time )) {
10137- print_scan_scrub_resilver_status (ps );
10203+ print_scan_scrub_resilver_status (ps , c );
1013810204 } else if (active_rebuild || (!active_resilver && have_rebuild &&
1013910205 rebuild_end_time && rebuild_end_time > resilver_end_time )) {
1014010206 print_rebuild_status (zhp , nvroot );
0 commit comments