@@ -513,8 +513,8 @@ get_usage(zpool_help_t idx)
513513 return (gettext ("\tinitialize [-c | -s | -u] [-w] <-a | <pool> "
514514 "[<device> ...]>\n" ));
515515 case HELP_SCRUB :
516- return (gettext ("\tscrub [-e | -s | -p | -C] [-w] <-a | "
517- "<pool> [<pool> ...]>\n" ));
516+ return (gettext ("\tscrub [-e | -s | -p | -C | -E | -S ] [-w] "
517+ "<-a | < pool> [<pool> ...]>\n" ));
518518 case HELP_RESILVER :
519519 return (gettext ("\tresilver <pool> ...\n" ));
520520 case HELP_TRIM :
@@ -8359,6 +8359,8 @@ zpool_do_reopen(int argc, char **argv)
83598359typedef struct scrub_cbdata {
83608360 int cb_type ;
83618361 pool_scrub_cmd_t cb_scrub_cmd ;
8362+ time_t cb_date_start ;
8363+ time_t cb_date_end ;
83628364} scrub_cbdata_t ;
83638365
83648366static boolean_t
@@ -8402,8 +8404,8 @@ scrub_callback(zpool_handle_t *zhp, void *data)
84028404 return (1 );
84038405 }
84048406
8405- err = zpool_scan (zhp , cb -> cb_type , cb -> cb_scrub_cmd );
8406-
8407+ err = zpool_scan_range (zhp , cb -> cb_type , cb -> cb_scrub_cmd ,
8408+ cb -> cb_date_start , cb -> cb_date_end );
84078409 if (err == 0 && zpool_has_checkpoint (zhp ) &&
84088410 cb -> cb_type == POOL_SCAN_SCRUB ) {
84098411 (void ) printf (gettext ("warning: will not scrub state that "
@@ -8421,10 +8423,34 @@ wait_callback(zpool_handle_t *zhp, void *data)
84218423 return (zpool_wait (zhp , * act ));
84228424}
84238425
8426+ static time_t
8427+ date_string_to_sec (const char * timestr , boolean_t rounding )
8428+ {
8429+ struct tm tm = {0 };
8430+ int adjustment = rounding ? 1 : 0 ;
8431+
8432+ /* Allow mktime to determine timezone. */
8433+ tm .tm_isdst = -1 ;
8434+
8435+ if (strptime (timestr , "%Y-%m-%d %H:%M" , & tm ) == NULL ) {
8436+ if (strptime (timestr , "%Y-%m-%d" , & tm ) == NULL ) {
8437+ fprintf (stderr , gettext ("Failed to parse the date.\n" ));
8438+ usage (B_FALSE );
8439+ }
8440+ adjustment *= 24 * 60 * 60 ;
8441+ } else {
8442+ adjustment *= 60 ;
8443+ }
8444+
8445+ return (mktime (& tm ) + adjustment );
8446+ }
8447+
84248448/*
8425- * zpool scrub [-e | -s | -p | -C] [-w] <pool> ...
8449+ * zpool scrub [-e | -s | -p | -C | -E | -S ] [-w] <pool> ...
84268450 *
84278451 * -e Only scrub blocks in the error log.
8452+ * -E End date of scrub.
8453+ * -S Start date of scrub.
84288454 * -s Stop. Stops any in-progress scrub.
84298455 * -p Pause. Pause in-progress scrub.
84308456 * -w Wait. Blocks until scrub has completed.
@@ -8440,6 +8466,7 @@ zpool_do_scrub(int argc, char **argv)
84408466
84418467 cb .cb_type = POOL_SCAN_SCRUB ;
84428468 cb .cb_scrub_cmd = POOL_SCRUB_NORMAL ;
8469+ cb .cb_date_start = cb .cb_date_end = 0 ;
84438470
84448471 boolean_t is_error_scrub = B_FALSE ;
84458472 boolean_t is_pause = B_FALSE ;
@@ -8448,17 +8475,27 @@ zpool_do_scrub(int argc, char **argv)
84488475 boolean_t scrub_all = B_FALSE ;
84498476
84508477 /* check options */
8451- while ((c = getopt (argc , argv , "aspweC " )) != -1 ) {
8478+ while ((c = getopt (argc , argv , "aspweCE:S: " )) != -1 ) {
84528479 switch (c ) {
84538480 case 'a' :
84548481 scrub_all = B_TRUE ;
84558482 break ;
84568483 case 'e' :
84578484 is_error_scrub = B_TRUE ;
84588485 break ;
8486+ case 'E' :
8487+ /*
8488+ * Round the date. It's better to scrub more data than
8489+ * less. This also makes the date inclusive.
8490+ */
8491+ cb .cb_date_end = date_string_to_sec (optarg , B_TRUE );
8492+ break ;
84598493 case 's' :
84608494 is_stop = B_TRUE ;
84618495 break ;
8496+ case 'S' :
8497+ cb .cb_date_start = date_string_to_sec (optarg , B_FALSE );
8498+ break ;
84628499 case 'p' :
84638500 is_pause = B_TRUE ;
84648501 break ;
@@ -8506,6 +8543,19 @@ zpool_do_scrub(int argc, char **argv)
85068543 }
85078544 }
85088545
8546+ if ((cb .cb_date_start != 0 || cb .cb_date_end != 0 ) &&
8547+ cb .cb_scrub_cmd != POOL_SCRUB_NORMAL ) {
8548+ (void ) fprintf (stderr , gettext ("invalid option combination: "
8549+ "start/end date is available only with normal scrub\n" ));
8550+ usage (B_FALSE );
8551+ }
8552+ if (cb .cb_date_start != 0 && cb .cb_date_end != 0 &&
8553+ cb .cb_date_start > cb .cb_date_end ) {
8554+ (void ) fprintf (stderr , gettext ("invalid arguments: "
8555+ "end date has to be later than start date\n" ));
8556+ usage (B_FALSE );
8557+ }
8558+
85098559 if (wait && (cb .cb_type == POOL_SCAN_NONE ||
85108560 cb .cb_scrub_cmd == POOL_SCRUB_PAUSE )) {
85118561 (void ) fprintf (stderr , gettext ("invalid option combination: "
@@ -8546,6 +8596,7 @@ zpool_do_resilver(int argc, char **argv)
85468596
85478597 cb .cb_type = POOL_SCAN_RESILVER ;
85488598 cb .cb_scrub_cmd = POOL_SCRUB_NORMAL ;
8599+ cb .cb_date_start = cb .cb_date_end = 0 ;
85498600
85508601 /* check options */
85518602 while ((c = getopt (argc , argv , "" )) != -1 ) {
0 commit comments