@@ -458,7 +458,8 @@ get_usage(zpool_help_t idx)
458458 return (gettext ("\tattach [-fsw] [-o property=value] "
459459 "<pool> <vdev> <new-device>\n" ));
460460 case HELP_CLEAR :
461- return (gettext ("\tclear [[--power]|[-nF]] <pool> [device]\n" ));
461+ return (gettext ("\tclear [[--power]|[-nsF]] <pool> "
462+ "[device]\n" ));
462463 case HELP_CREATE :
463464 return (gettext ("\tcreate [-fnd] [-o property=value] ... \n"
464465 "\t [-O file-system-property=value] ... \n"
@@ -513,8 +514,8 @@ get_usage(zpool_help_t idx)
513514 return (gettext ("\tinitialize [-c | -s | -u] [-w] <-a | <pool> "
514515 "[<device> ...]>\n" ));
515516 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" ));
518519 case HELP_RESILVER :
519520 return (gettext ("\tresilver <pool> ...\n" ));
520521 case HELP_TRIM :
@@ -8193,8 +8194,74 @@ zpool_do_offline(int argc, char **argv)
81938194 return (ret );
81948195}
81958196
8197+ typedef struct scrub_cbdata {
8198+ int cb_type ;
8199+ pool_scrub_cmd_t cb_scrub_cmd ;
8200+ time_t cb_date_start ;
8201+ time_t cb_date_end ;
8202+ } scrub_cbdata_t ;
8203+
8204+ static boolean_t
8205+ zpool_has_checkpoint (zpool_handle_t * zhp )
8206+ {
8207+ nvlist_t * config , * nvroot ;
8208+
8209+ config = zpool_get_config (zhp , NULL );
8210+
8211+ if (config != NULL ) {
8212+ pool_checkpoint_stat_t * pcs = NULL ;
8213+ uint_t c ;
8214+
8215+ nvroot = fnvlist_lookup_nvlist (config , ZPOOL_CONFIG_VDEV_TREE );
8216+ (void ) nvlist_lookup_uint64_array (nvroot ,
8217+ ZPOOL_CONFIG_CHECKPOINT_STATS , (uint64_t * * )& pcs , & c );
8218+
8219+ if (pcs == NULL || pcs -> pcs_state == CS_NONE )
8220+ return (B_FALSE );
8221+
8222+ assert (pcs -> pcs_state == CS_CHECKPOINT_EXISTS ||
8223+ pcs -> pcs_state == CS_CHECKPOINT_DISCARDING );
8224+ return (B_TRUE );
8225+ }
8226+
8227+ return (B_FALSE );
8228+ }
8229+
8230+ static int
8231+ zpool_scrub (zpool_handle_t * zhp , scrub_cbdata_t * cb )
8232+ {
8233+ int err ;
8234+
8235+ /*
8236+ * Ignore faulted pools.
8237+ */
8238+ if (zpool_get_state (zhp ) == POOL_STATE_UNAVAIL ) {
8239+ (void ) fprintf (stderr , gettext ("cannot scan '%s': pool is "
8240+ "currently unavailable\n" ), zpool_get_name (zhp ));
8241+ return (1 );
8242+ }
8243+
8244+ err = zpool_scan_range (zhp , cb -> cb_type , cb -> cb_scrub_cmd ,
8245+ cb -> cb_date_start , cb -> cb_date_end );
8246+ if (err == 0 && zpool_has_checkpoint (zhp ) &&
8247+ cb -> cb_type == POOL_SCAN_SCRUB ) {
8248+ (void ) printf (gettext ("warning: will not scrub state that "
8249+ "belongs to the checkpoint of pool '%s'\n" ),
8250+ zpool_get_name (zhp ));
8251+ }
8252+
8253+ return (err != 0 );
8254+ }
8255+
8256+ static int
8257+ scrub_callback (zpool_handle_t * zhp , void * data )
8258+ {
8259+ scrub_cbdata_t * cb = data ;
8260+ return (zpool_scrub (zhp , cb ));
8261+ }
8262+
81968263/*
8197- * zpool clear [-nF ]|[--power] <pool> [device]
8264+ * zpool clear [-nsF ]|[--power] <pool> [device]
81988265 *
81998266 * Clear all errors associated with a pool or a particular device.
82008267 */
@@ -8207,6 +8274,7 @@ zpool_do_clear(int argc, char **argv)
82078274 boolean_t do_rewind = B_FALSE ;
82088275 boolean_t xtreme_rewind = B_FALSE ;
82098276 boolean_t is_power_on = B_FALSE ;
8277+ boolean_t scrub = B_FALSE ;
82108278 uint32_t rewind_policy = ZPOOL_NO_REWIND ;
82118279 nvlist_t * policy = NULL ;
82128280 zpool_handle_t * zhp ;
@@ -8218,7 +8286,7 @@ zpool_do_clear(int argc, char **argv)
82188286 };
82198287
82208288 /* check options */
8221- while ((c = getopt_long (argc , argv , "FnX " , long_options ,
8289+ while ((c = getopt_long (argc , argv , "FnsX " , long_options ,
82228290 NULL )) != -1 ) {
82238291 switch (c ) {
82248292 case 'F' :
@@ -8227,6 +8295,9 @@ zpool_do_clear(int argc, char **argv)
82278295 case 'n' :
82288296 dryrun = B_TRUE ;
82298297 break ;
8298+ case 's' :
8299+ scrub = B_TRUE ;
8300+ break ;
82308301 case 'X' :
82318302 xtreme_rewind = B_TRUE ;
82328303 break ;
@@ -8294,6 +8365,14 @@ zpool_do_clear(int argc, char **argv)
82948365 if (zpool_clear (zhp , device , policy ) != 0 )
82958366 ret = 1 ;
82968367
8368+ if (ret == 0 && !dryrun && scrub ) {
8369+ scrub_cbdata_t cbdata = {
8370+ .cb_type = POOL_SCAN_SCRUB ,
8371+ .cb_scrub_cmd = POOL_SCRUB_RECENT ,
8372+ };
8373+ ret = scrub_callback (zhp , & cbdata );
8374+ }
8375+
82978376 zpool_close (zhp );
82988377
82998378 nvlist_free (policy );
@@ -8395,66 +8474,6 @@ zpool_do_reopen(int argc, char **argv)
83958474 return (ret );
83968475}
83978476
8398- typedef struct scrub_cbdata {
8399- int cb_type ;
8400- pool_scrub_cmd_t cb_scrub_cmd ;
8401- time_t cb_date_start ;
8402- time_t cb_date_end ;
8403- } scrub_cbdata_t ;
8404-
8405- static boolean_t
8406- zpool_has_checkpoint (zpool_handle_t * zhp )
8407- {
8408- nvlist_t * config , * nvroot ;
8409-
8410- config = zpool_get_config (zhp , NULL );
8411-
8412- if (config != NULL ) {
8413- pool_checkpoint_stat_t * pcs = NULL ;
8414- uint_t c ;
8415-
8416- nvroot = fnvlist_lookup_nvlist (config , ZPOOL_CONFIG_VDEV_TREE );
8417- (void ) nvlist_lookup_uint64_array (nvroot ,
8418- ZPOOL_CONFIG_CHECKPOINT_STATS , (uint64_t * * )& pcs , & c );
8419-
8420- if (pcs == NULL || pcs -> pcs_state == CS_NONE )
8421- return (B_FALSE );
8422-
8423- assert (pcs -> pcs_state == CS_CHECKPOINT_EXISTS ||
8424- pcs -> pcs_state == CS_CHECKPOINT_DISCARDING );
8425- return (B_TRUE );
8426- }
8427-
8428- return (B_FALSE );
8429- }
8430-
8431- static int
8432- scrub_callback (zpool_handle_t * zhp , void * data )
8433- {
8434- scrub_cbdata_t * cb = data ;
8435- int err ;
8436-
8437- /*
8438- * Ignore faulted pools.
8439- */
8440- if (zpool_get_state (zhp ) == POOL_STATE_UNAVAIL ) {
8441- (void ) fprintf (stderr , gettext ("cannot scan '%s': pool is "
8442- "currently unavailable\n" ), zpool_get_name (zhp ));
8443- return (1 );
8444- }
8445-
8446- err = zpool_scan_range (zhp , cb -> cb_type , cb -> cb_scrub_cmd ,
8447- cb -> cb_date_start , cb -> cb_date_end );
8448- if (err == 0 && zpool_has_checkpoint (zhp ) &&
8449- cb -> cb_type == POOL_SCAN_SCRUB ) {
8450- (void ) printf (gettext ("warning: will not scrub state that "
8451- "belongs to the checkpoint of pool '%s'\n" ),
8452- zpool_get_name (zhp ));
8453- }
8454-
8455- return (err != 0 );
8456- }
8457-
84588477static int
84598478wait_callback (zpool_handle_t * zhp , void * data )
84608479{
@@ -8490,14 +8509,15 @@ struct zpool_scrub_option {
84908509};
84918510
84928511/*
8493- * zpool scrub [-e | -s | -p | -C | -E | -S] [-w] [-a | <pool> ...]
8512+ * zpool scrub [-e | -s | -p | -C | -E | -S | -R ] [-w] [-a | <pool> ...]
84948513 *
84958514 * -a Scrub all pools.
84968515 * -e Only scrub blocks in the error log.
84978516 * -E End date of scrub.
84988517 * -S Start date of scrub.
84998518 * -s Stop. Stops any in-progress scrub.
85008519 * -p Pause. Pause in-progress scrub.
8520+ * -R Scrub only recent data.
85018521 * -w Wait. Blocks until scrub has completed.
85028522 * -C Scrub from last saved txg.
85038523 */
@@ -8516,11 +8536,12 @@ zpool_do_scrub(int argc, char **argv)
85168536 struct zpool_scrub_option is_error_scrub = {'e' , B_FALSE };
85178537 struct zpool_scrub_option is_pause = {'p' , B_FALSE };
85188538 struct zpool_scrub_option is_stop = {'s' , B_FALSE };
8539+ struct zpool_scrub_option is_recent = {'R' , B_FALSE };
85198540 struct zpool_scrub_option is_txg_continue = {'C' , B_FALSE };
85208541 struct zpool_scrub_option scrub_all = {'a' , B_FALSE };
85218542
85228543 /* check options */
8523- while ((c = getopt (argc , argv , "aspweCE:S:" )) != -1 ) {
8544+ while ((c = getopt (argc , argv , "aspweCE:S:R " )) != -1 ) {
85248545 switch (c ) {
85258546 case 'a' :
85268547 scrub_all .enabled = B_TRUE ;
@@ -8544,6 +8565,9 @@ zpool_do_scrub(int argc, char **argv)
85448565 case 'p' :
85458566 is_pause .enabled = B_TRUE ;
85468567 break ;
8568+ case 'R' :
8569+ is_recent .enabled = B_TRUE ;
8570+ break ;
85478571 case 'w' :
85488572 wait .enabled = B_TRUE ;
85498573 break ;
@@ -8564,9 +8588,13 @@ zpool_do_scrub(int argc, char **argv)
85648588 {& is_stop , & is_pause },
85658589 {& is_stop , & is_txg_continue },
85668590 {& is_stop , & is_error_scrub },
8591+ {& is_stop , & is_recent },
85678592 {& is_pause , & is_txg_continue },
85688593 {& is_pause , & is_error_scrub },
8594+ {& is_pause , & is_recent },
85698595 {& is_error_scrub , & is_txg_continue },
8596+ {& is_error_scrub , & is_recent },
8597+ {& is_recent , & is_txg_continue },
85708598 };
85718599
85728600 for (int i = 0 ; i < sizeof (scrub_exclusive_options ) /
@@ -8591,6 +8619,8 @@ zpool_do_scrub(int argc, char **argv)
85918619 cb .cb_type = POOL_SCAN_NONE ;
85928620 } else if (is_txg_continue .enabled ) {
85938621 cb .cb_scrub_cmd = POOL_SCRUB_FROM_LAST_TXG ;
8622+ } else if (is_recent .enabled ) {
8623+ cb .cb_scrub_cmd = POOL_SCRUB_RECENT ;
85948624 } else {
85958625 cb .cb_scrub_cmd = POOL_SCRUB_NORMAL ;
85968626 }
0 commit comments