@@ -480,7 +480,7 @@ get_usage(zpool_help_t idx)
480
480
return (gettext ("\tinitialize [-c | -s | -u] [-w] <pool> "
481
481
"[<device> ...]\n" ));
482
482
case HELP_SCRUB :
483
- return (gettext ("\tscrub [-e | -s | -p | -C] [-w] "
483
+ return (gettext ("\tscrub [-e | -s | -p | -C| -E | -S ] [-w] "
484
484
"<pool> ...\n" ));
485
485
case HELP_RESILVER :
486
486
return (gettext ("\tresilver <pool> ...\n" ));
@@ -8330,6 +8330,8 @@ zpool_do_reopen(int argc, char **argv)
8330
8330
typedef struct scrub_cbdata {
8331
8331
int cb_type ;
8332
8332
pool_scrub_cmd_t cb_scrub_cmd ;
8333
+ time_t cb_date_start ;
8334
+ time_t cb_date_end ;
8333
8335
} scrub_cbdata_t ;
8334
8336
8335
8337
static boolean_t
@@ -8373,8 +8375,8 @@ scrub_callback(zpool_handle_t *zhp, void *data)
8373
8375
return (1 );
8374
8376
}
8375
8377
8376
- err = zpool_scan (zhp , cb -> cb_type , cb -> cb_scrub_cmd );
8377
-
8378
+ err = zpool_scan_range (zhp , cb -> cb_type , cb -> cb_scrub_cmd ,
8379
+ cb -> cb_date_start , cb -> cb_date_end );
8378
8380
if (err == 0 && zpool_has_checkpoint (zhp ) &&
8379
8381
cb -> cb_type == POOL_SCAN_SCRUB ) {
8380
8382
(void ) printf (gettext ("warning: will not scrub state that "
@@ -8392,10 +8394,34 @@ wait_callback(zpool_handle_t *zhp, void *data)
8392
8394
return (zpool_wait (zhp , * act ));
8393
8395
}
8394
8396
8397
+ static time_t
8398
+ date_string_to_sec (const char * timestr , boolean_t rounding )
8399
+ {
8400
+ struct tm tm = {0 };
8401
+ int adjustment = rounding ? 1 : 0 ;
8402
+
8403
+ /* Allow mktime to determine timezone. */
8404
+ tm .tm_isdst = -1 ;
8405
+
8406
+ if (strptime (timestr , "%Y-%m-%d %H:%M" , & tm ) == NULL ) {
8407
+ if (strptime (timestr , "%Y-%m-%d" , & tm ) == NULL ) {
8408
+ fprintf (stderr , gettext ("Failed to parse the date.\n" ));
8409
+ usage (B_FALSE );
8410
+ }
8411
+ adjustment *= 24 * 60 * 60 ;
8412
+ } else {
8413
+ adjustment *= 60 ;
8414
+ }
8415
+
8416
+ return (mktime (& tm ) + adjustment );
8417
+ }
8418
+
8395
8419
/*
8396
- * zpool scrub [-e | -s | -p | -C] [-w] <pool> ...
8420
+ * zpool scrub [-e | -s | -p | -C | -E | -S ] [-w] <pool> ...
8397
8421
*
8398
8422
* -e Only scrub blocks in the error log.
8423
+ * -E End date of scrub.
8424
+ * -S Start date of scrub.
8399
8425
* -s Stop. Stops any in-progress scrub.
8400
8426
* -p Pause. Pause in-progress scrub.
8401
8427
* -w Wait. Blocks until scrub has completed.
@@ -8411,21 +8437,32 @@ zpool_do_scrub(int argc, char **argv)
8411
8437
8412
8438
cb .cb_type = POOL_SCAN_SCRUB ;
8413
8439
cb .cb_scrub_cmd = POOL_SCRUB_NORMAL ;
8440
+ cb .cb_date_start = cb .cb_date_end = 0 ;
8414
8441
8415
8442
boolean_t is_error_scrub = B_FALSE ;
8416
8443
boolean_t is_pause = B_FALSE ;
8417
8444
boolean_t is_stop = B_FALSE ;
8418
8445
boolean_t is_txg_continue = B_FALSE ;
8419
8446
8420
8447
/* check options */
8421
- while ((c = getopt (argc , argv , "spweC " )) != -1 ) {
8448
+ while ((c = getopt (argc , argv , "spweCE:S: " )) != -1 ) {
8422
8449
switch (c ) {
8423
8450
case 'e' :
8424
8451
is_error_scrub = B_TRUE ;
8425
8452
break ;
8453
+ case 'E' :
8454
+ /*
8455
+ * Round the date. It's better to scrub more data than
8456
+ * less. This also makes the date inclusive.
8457
+ */
8458
+ cb .cb_date_end = date_string_to_sec (optarg , B_TRUE );
8459
+ break ;
8426
8460
case 's' :
8427
8461
is_stop = B_TRUE ;
8428
8462
break ;
8463
+ case 'S' :
8464
+ cb .cb_date_start = date_string_to_sec (optarg , B_FALSE );
8465
+ break ;
8429
8466
case 'p' :
8430
8467
is_pause = B_TRUE ;
8431
8468
break ;
@@ -8485,6 +8522,19 @@ zpool_do_scrub(int argc, char **argv)
8485
8522
}
8486
8523
}
8487
8524
8525
+ if ((cb .cb_date_start != 0 || cb .cb_date_end != 0 ) &&
8526
+ cb .cb_scrub_cmd != POOL_SCRUB_NORMAL ) {
8527
+ (void ) fprintf (stderr , gettext ("invalid option combination: "
8528
+ "start/end date is available only with normal scrub\n" ));
8529
+ usage (B_FALSE );
8530
+ }
8531
+ if (cb .cb_date_start != 0 && cb .cb_date_end != 0 &&
8532
+ cb .cb_date_start > cb .cb_date_end ) {
8533
+ (void ) fprintf (stderr , gettext ("invalid arguments: "
8534
+ "end date has to be later than start date\n" ));
8535
+ usage (B_FALSE );
8536
+ }
8537
+
8488
8538
if (wait && (cb .cb_type == POOL_SCAN_NONE ||
8489
8539
cb .cb_scrub_cmd == POOL_SCRUB_PAUSE )) {
8490
8540
(void ) fprintf (stderr , gettext ("invalid option combination: "
@@ -8525,6 +8575,7 @@ zpool_do_resilver(int argc, char **argv)
8525
8575
8526
8576
cb .cb_type = POOL_SCAN_RESILVER ;
8527
8577
cb .cb_scrub_cmd = POOL_SCRUB_NORMAL ;
8578
+ cb .cb_date_start = cb .cb_date_end = 0 ;
8528
8579
8529
8580
/* check options */
8530
8581
while ((c = getopt (argc , argv , "" )) != -1 ) {
0 commit comments