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