@@ -458,7 +458,8 @@ get_usage(zpool_help_t idx)
458
458
return (gettext ("\tattach [-fsw] [-o property=value] "
459
459
"<pool> <device> <new-device>\n" ));
460
460
case HELP_CLEAR :
461
- return (gettext ("\tclear [[--power]|[-nF]] <pool> [device]\n" ));
461
+ return (gettext ("\tclear [[--power]|[-nsF]] <pool> "
462
+ "[device]\n" ));
462
463
case HELP_CREATE :
463
464
return (gettext ("\tcreate [-fnd] [-o property=value] ... \n"
464
465
"\t [-O file-system-property=value] ... \n"
@@ -513,8 +514,8 @@ get_usage(zpool_help_t idx)
513
514
return (gettext ("\tinitialize [-c | -s | -u] [-w] <-a | <pool> "
514
515
"[<device> ...]>\n" ));
515
516
case HELP_SCRUB :
516
- return (gettext ("\tscrub [-e | -s | -p | -C | -E | -S] [-w ] "
517
- "<-a | <pool> [<pool> ...]>\n" ));
517
+ return (gettext ("\tscrub [-e | -s | -p | -C | -E | -S | -R ] "
518
+ "[-w] <-a | <pool> [<pool> ...]>\n" ));
518
519
case HELP_RESILVER :
519
520
return (gettext ("\tresilver <pool> ...\n" ));
520
521
case HELP_TRIM :
@@ -8155,8 +8156,74 @@ zpool_do_offline(int argc, char **argv)
8155
8156
return (ret );
8156
8157
}
8157
8158
8159
+ typedef struct scrub_cbdata {
8160
+ int cb_type ;
8161
+ pool_scrub_cmd_t cb_scrub_cmd ;
8162
+ time_t cb_date_start ;
8163
+ time_t cb_date_end ;
8164
+ } scrub_cbdata_t ;
8165
+
8166
+ static boolean_t
8167
+ zpool_has_checkpoint (zpool_handle_t * zhp )
8168
+ {
8169
+ nvlist_t * config , * nvroot ;
8170
+
8171
+ config = zpool_get_config (zhp , NULL );
8172
+
8173
+ if (config != NULL ) {
8174
+ pool_checkpoint_stat_t * pcs = NULL ;
8175
+ uint_t c ;
8176
+
8177
+ nvroot = fnvlist_lookup_nvlist (config , ZPOOL_CONFIG_VDEV_TREE );
8178
+ (void ) nvlist_lookup_uint64_array (nvroot ,
8179
+ ZPOOL_CONFIG_CHECKPOINT_STATS , (uint64_t * * )& pcs , & c );
8180
+
8181
+ if (pcs == NULL || pcs -> pcs_state == CS_NONE )
8182
+ return (B_FALSE );
8183
+
8184
+ assert (pcs -> pcs_state == CS_CHECKPOINT_EXISTS ||
8185
+ pcs -> pcs_state == CS_CHECKPOINT_DISCARDING );
8186
+ return (B_TRUE );
8187
+ }
8188
+
8189
+ return (B_FALSE );
8190
+ }
8191
+
8192
+ static int
8193
+ zpool_scrub (zpool_handle_t * zhp , scrub_cbdata_t * cb )
8194
+ {
8195
+ int err ;
8196
+
8197
+ /*
8198
+ * Ignore faulted pools.
8199
+ */
8200
+ if (zpool_get_state (zhp ) == POOL_STATE_UNAVAIL ) {
8201
+ (void ) fprintf (stderr , gettext ("cannot scan '%s': pool is "
8202
+ "currently unavailable\n" ), zpool_get_name (zhp ));
8203
+ return (1 );
8204
+ }
8205
+
8206
+ err = zpool_scan_range (zhp , cb -> cb_type , cb -> cb_scrub_cmd ,
8207
+ cb -> cb_date_start , cb -> cb_date_end );
8208
+ if (err == 0 && zpool_has_checkpoint (zhp ) &&
8209
+ cb -> cb_type == POOL_SCAN_SCRUB ) {
8210
+ (void ) printf (gettext ("warning: will not scrub state that "
8211
+ "belongs to the checkpoint of pool '%s'\n" ),
8212
+ zpool_get_name (zhp ));
8213
+ }
8214
+
8215
+ return (err != 0 );
8216
+ }
8217
+
8218
+ static int
8219
+ scrub_callback (zpool_handle_t * zhp , void * data )
8220
+ {
8221
+ scrub_cbdata_t * cb = data ;
8222
+ return (zpool_scrub (zhp , cb ));
8223
+ }
8224
+
8158
8225
/*
8159
- * zpool clear [-nF ]|[--power] <pool> [device]
8226
+ * zpool clear [-nsF ]|[--power] <pool> [device]
8160
8227
*
8161
8228
* Clear all errors associated with a pool or a particular device.
8162
8229
*/
@@ -8169,6 +8236,7 @@ zpool_do_clear(int argc, char **argv)
8169
8236
boolean_t do_rewind = B_FALSE ;
8170
8237
boolean_t xtreme_rewind = B_FALSE ;
8171
8238
boolean_t is_power_on = B_FALSE ;
8239
+ boolean_t scrub = B_FALSE ;
8172
8240
uint32_t rewind_policy = ZPOOL_NO_REWIND ;
8173
8241
nvlist_t * policy = NULL ;
8174
8242
zpool_handle_t * zhp ;
@@ -8180,7 +8248,7 @@ zpool_do_clear(int argc, char **argv)
8180
8248
};
8181
8249
8182
8250
/* check options */
8183
- while ((c = getopt_long (argc , argv , "FnX " , long_options ,
8251
+ while ((c = getopt_long (argc , argv , "FnsX " , long_options ,
8184
8252
NULL )) != -1 ) {
8185
8253
switch (c ) {
8186
8254
case 'F' :
@@ -8189,6 +8257,9 @@ zpool_do_clear(int argc, char **argv)
8189
8257
case 'n' :
8190
8258
dryrun = B_TRUE ;
8191
8259
break ;
8260
+ case 's' :
8261
+ scrub = B_TRUE ;
8262
+ break ;
8192
8263
case 'X' :
8193
8264
xtreme_rewind = B_TRUE ;
8194
8265
break ;
@@ -8256,6 +8327,14 @@ zpool_do_clear(int argc, char **argv)
8256
8327
if (zpool_clear (zhp , device , policy ) != 0 )
8257
8328
ret = 1 ;
8258
8329
8330
+ if (ret == 0 && !dryrun && scrub ) {
8331
+ scrub_cbdata_t cbdata = {
8332
+ .cb_type = POOL_SCAN_SCRUB ,
8333
+ .cb_scrub_cmd = POOL_SCRUB_RECENT ,
8334
+ };
8335
+ ret = scrub_callback (zhp , & cbdata );
8336
+ }
8337
+
8259
8338
zpool_close (zhp );
8260
8339
8261
8340
nvlist_free (policy );
@@ -8357,66 +8436,6 @@ zpool_do_reopen(int argc, char **argv)
8357
8436
return (ret );
8358
8437
}
8359
8438
8360
- typedef struct scrub_cbdata {
8361
- int cb_type ;
8362
- pool_scrub_cmd_t cb_scrub_cmd ;
8363
- time_t cb_date_start ;
8364
- time_t cb_date_end ;
8365
- } scrub_cbdata_t ;
8366
-
8367
- static boolean_t
8368
- zpool_has_checkpoint (zpool_handle_t * zhp )
8369
- {
8370
- nvlist_t * config , * nvroot ;
8371
-
8372
- config = zpool_get_config (zhp , NULL );
8373
-
8374
- if (config != NULL ) {
8375
- pool_checkpoint_stat_t * pcs = NULL ;
8376
- uint_t c ;
8377
-
8378
- nvroot = fnvlist_lookup_nvlist (config , ZPOOL_CONFIG_VDEV_TREE );
8379
- (void ) nvlist_lookup_uint64_array (nvroot ,
8380
- ZPOOL_CONFIG_CHECKPOINT_STATS , (uint64_t * * )& pcs , & c );
8381
-
8382
- if (pcs == NULL || pcs -> pcs_state == CS_NONE )
8383
- return (B_FALSE );
8384
-
8385
- assert (pcs -> pcs_state == CS_CHECKPOINT_EXISTS ||
8386
- pcs -> pcs_state == CS_CHECKPOINT_DISCARDING );
8387
- return (B_TRUE );
8388
- }
8389
-
8390
- return (B_FALSE );
8391
- }
8392
-
8393
- static int
8394
- scrub_callback (zpool_handle_t * zhp , void * data )
8395
- {
8396
- scrub_cbdata_t * cb = data ;
8397
- int err ;
8398
-
8399
- /*
8400
- * Ignore faulted pools.
8401
- */
8402
- if (zpool_get_state (zhp ) == POOL_STATE_UNAVAIL ) {
8403
- (void ) fprintf (stderr , gettext ("cannot scan '%s': pool is "
8404
- "currently unavailable\n" ), zpool_get_name (zhp ));
8405
- return (1 );
8406
- }
8407
-
8408
- err = zpool_scan_range (zhp , cb -> cb_type , cb -> cb_scrub_cmd ,
8409
- cb -> cb_date_start , cb -> cb_date_end );
8410
- if (err == 0 && zpool_has_checkpoint (zhp ) &&
8411
- cb -> cb_type == POOL_SCAN_SCRUB ) {
8412
- (void ) printf (gettext ("warning: will not scrub state that "
8413
- "belongs to the checkpoint of pool '%s'\n" ),
8414
- zpool_get_name (zhp ));
8415
- }
8416
-
8417
- return (err != 0 );
8418
- }
8419
-
8420
8439
static int
8421
8440
wait_callback (zpool_handle_t * zhp , void * data )
8422
8441
{
@@ -8452,14 +8471,15 @@ struct zpool_scrub_option {
8452
8471
};
8453
8472
8454
8473
/*
8455
- * zpool scrub [-e | -s | -p | -C | -E | -S] [-w] [-a | <pool> ...]
8474
+ * zpool scrub [-e | -s | -p | -C | -E | -S | -R ] [-w] [-a | <pool> ...]
8456
8475
*
8457
8476
* -a Scrub all pools.
8458
8477
* -e Only scrub blocks in the error log.
8459
8478
* -E End date of scrub.
8460
8479
* -S Start date of scrub.
8461
8480
* -s Stop. Stops any in-progress scrub.
8462
8481
* -p Pause. Pause in-progress scrub.
8482
+ * -R Scrub only recent data.
8463
8483
* -w Wait. Blocks until scrub has completed.
8464
8484
* -C Scrub from last saved txg.
8465
8485
*/
@@ -8478,11 +8498,12 @@ zpool_do_scrub(int argc, char **argv)
8478
8498
struct zpool_scrub_option is_error_scrub = {'e' , B_FALSE };
8479
8499
struct zpool_scrub_option is_pause = {'p' , B_FALSE };
8480
8500
struct zpool_scrub_option is_stop = {'s' , B_FALSE };
8501
+ struct zpool_scrub_option is_recent = {'R' , B_FALSE };
8481
8502
struct zpool_scrub_option is_txg_continue = {'C' , B_FALSE };
8482
8503
struct zpool_scrub_option scrub_all = {'a' , B_FALSE };
8483
8504
8484
8505
/* check options */
8485
- while ((c = getopt (argc , argv , "aspweCE:S:" )) != -1 ) {
8506
+ while ((c = getopt (argc , argv , "aspweCE:S:R " )) != -1 ) {
8486
8507
switch (c ) {
8487
8508
case 'a' :
8488
8509
scrub_all .enabled = B_TRUE ;
@@ -8506,6 +8527,9 @@ zpool_do_scrub(int argc, char **argv)
8506
8527
case 'p' :
8507
8528
is_pause .enabled = B_TRUE ;
8508
8529
break ;
8530
+ case 'R' :
8531
+ is_recent .enabled = B_TRUE ;
8532
+ break ;
8509
8533
case 'w' :
8510
8534
wait .enabled = B_TRUE ;
8511
8535
break ;
@@ -8526,9 +8550,13 @@ zpool_do_scrub(int argc, char **argv)
8526
8550
{& is_stop , & is_pause },
8527
8551
{& is_stop , & is_txg_continue },
8528
8552
{& is_stop , & is_error_scrub },
8553
+ {& is_stop , & is_recent },
8529
8554
{& is_pause , & is_txg_continue },
8530
8555
{& is_pause , & is_error_scrub },
8556
+ {& is_pause , & is_recent },
8531
8557
{& is_error_scrub , & is_txg_continue },
8558
+ {& is_error_scrub , & is_recent },
8559
+ {& is_recent , & is_txg_continue },
8532
8560
};
8533
8561
8534
8562
for (int i = 0 ; i < sizeof (scrub_exclusive_options ) /
@@ -8553,6 +8581,8 @@ zpool_do_scrub(int argc, char **argv)
8553
8581
cb .cb_type = POOL_SCAN_NONE ;
8554
8582
} else if (is_txg_continue .enabled ) {
8555
8583
cb .cb_scrub_cmd = POOL_SCRUB_FROM_LAST_TXG ;
8584
+ } else if (is_recent .enabled ) {
8585
+ cb .cb_scrub_cmd = POOL_SCRUB_RECENT ;
8556
8586
} else {
8557
8587
cb .cb_scrub_cmd = POOL_SCRUB_NORMAL ;
8558
8588
}
0 commit comments