@@ -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 :
@@ -8144,8 +8145,74 @@ zpool_do_offline(int argc, char **argv)
81448145 return (ret );
81458146}
81468147
8148+ typedef struct scrub_cbdata {
8149+ int cb_type ;
8150+ pool_scrub_cmd_t cb_scrub_cmd ;
8151+ time_t cb_date_start ;
8152+ time_t cb_date_end ;
8153+ } scrub_cbdata_t ;
8154+
8155+ static boolean_t
8156+ zpool_has_checkpoint (zpool_handle_t * zhp )
8157+ {
8158+ nvlist_t * config , * nvroot ;
8159+
8160+ config = zpool_get_config (zhp , NULL );
8161+
8162+ if (config != NULL ) {
8163+ pool_checkpoint_stat_t * pcs = NULL ;
8164+ uint_t c ;
8165+
8166+ nvroot = fnvlist_lookup_nvlist (config , ZPOOL_CONFIG_VDEV_TREE );
8167+ (void ) nvlist_lookup_uint64_array (nvroot ,
8168+ ZPOOL_CONFIG_CHECKPOINT_STATS , (uint64_t * * )& pcs , & c );
8169+
8170+ if (pcs == NULL || pcs -> pcs_state == CS_NONE )
8171+ return (B_FALSE );
8172+
8173+ assert (pcs -> pcs_state == CS_CHECKPOINT_EXISTS ||
8174+ pcs -> pcs_state == CS_CHECKPOINT_DISCARDING );
8175+ return (B_TRUE );
8176+ }
8177+
8178+ return (B_FALSE );
8179+ }
8180+
8181+ static int
8182+ zpool_scrub (zpool_handle_t * zhp , scrub_cbdata_t * cb )
8183+ {
8184+ int err ;
8185+
8186+ /*
8187+ * Ignore faulted pools.
8188+ */
8189+ if (zpool_get_state (zhp ) == POOL_STATE_UNAVAIL ) {
8190+ (void ) fprintf (stderr , gettext ("cannot scan '%s': pool is "
8191+ "currently unavailable\n" ), zpool_get_name (zhp ));
8192+ return (1 );
8193+ }
8194+
8195+ err = zpool_scan_range (zhp , cb -> cb_type , cb -> cb_scrub_cmd ,
8196+ cb -> cb_date_start , cb -> cb_date_end );
8197+ if (err == 0 && zpool_has_checkpoint (zhp ) &&
8198+ cb -> cb_type == POOL_SCAN_SCRUB ) {
8199+ (void ) printf (gettext ("warning: will not scrub state that "
8200+ "belongs to the checkpoint of pool '%s'\n" ),
8201+ zpool_get_name (zhp ));
8202+ }
8203+
8204+ return (err != 0 );
8205+ }
8206+
8207+ static int
8208+ scrub_callback (zpool_handle_t * zhp , void * data )
8209+ {
8210+ scrub_cbdata_t * cb = data ;
8211+ return (zpool_scrub (zhp , cb ));
8212+ }
8213+
81478214/*
8148- * zpool clear [-nF ]|[--power] <pool> [device]
8215+ * zpool clear [-nsF ]|[--power] <pool> [device]
81498216 *
81508217 * Clear all errors associated with a pool or a particular device.
81518218 */
@@ -8158,6 +8225,7 @@ zpool_do_clear(int argc, char **argv)
81588225 boolean_t do_rewind = B_FALSE ;
81598226 boolean_t xtreme_rewind = B_FALSE ;
81608227 boolean_t is_power_on = B_FALSE ;
8228+ boolean_t scrub = B_FALSE ;
81618229 uint32_t rewind_policy = ZPOOL_NO_REWIND ;
81628230 nvlist_t * policy = NULL ;
81638231 zpool_handle_t * zhp ;
@@ -8169,7 +8237,7 @@ zpool_do_clear(int argc, char **argv)
81698237 };
81708238
81718239 /* check options */
8172- while ((c = getopt_long (argc , argv , "FnX " , long_options ,
8240+ while ((c = getopt_long (argc , argv , "FnsX " , long_options ,
81738241 NULL )) != -1 ) {
81748242 switch (c ) {
81758243 case 'F' :
@@ -8178,6 +8246,9 @@ zpool_do_clear(int argc, char **argv)
81788246 case 'n' :
81798247 dryrun = B_TRUE ;
81808248 break ;
8249+ case 's' :
8250+ scrub = B_TRUE ;
8251+ break ;
81818252 case 'X' :
81828253 xtreme_rewind = B_TRUE ;
81838254 break ;
@@ -8245,6 +8316,14 @@ zpool_do_clear(int argc, char **argv)
82458316 if (zpool_clear (zhp , device , policy ) != 0 )
82468317 ret = 1 ;
82478318
8319+ if (ret == 0 && !dryrun && scrub ) {
8320+ scrub_cbdata_t cbdata = {
8321+ .cb_type = POOL_SCAN_SCRUB ,
8322+ .cb_scrub_cmd = POOL_SCRUB_RECENT ,
8323+ };
8324+ ret = scrub_callback (zhp , & cbdata );
8325+ }
8326+
82488327 zpool_close (zhp );
82498328
82508329 nvlist_free (policy );
@@ -8346,66 +8425,6 @@ zpool_do_reopen(int argc, char **argv)
83468425 return (ret );
83478426}
83488427
8349- typedef struct scrub_cbdata {
8350- int cb_type ;
8351- pool_scrub_cmd_t cb_scrub_cmd ;
8352- time_t cb_date_start ;
8353- time_t cb_date_end ;
8354- } scrub_cbdata_t ;
8355-
8356- static boolean_t
8357- zpool_has_checkpoint (zpool_handle_t * zhp )
8358- {
8359- nvlist_t * config , * nvroot ;
8360-
8361- config = zpool_get_config (zhp , NULL );
8362-
8363- if (config != NULL ) {
8364- pool_checkpoint_stat_t * pcs = NULL ;
8365- uint_t c ;
8366-
8367- nvroot = fnvlist_lookup_nvlist (config , ZPOOL_CONFIG_VDEV_TREE );
8368- (void ) nvlist_lookup_uint64_array (nvroot ,
8369- ZPOOL_CONFIG_CHECKPOINT_STATS , (uint64_t * * )& pcs , & c );
8370-
8371- if (pcs == NULL || pcs -> pcs_state == CS_NONE )
8372- return (B_FALSE );
8373-
8374- assert (pcs -> pcs_state == CS_CHECKPOINT_EXISTS ||
8375- pcs -> pcs_state == CS_CHECKPOINT_DISCARDING );
8376- return (B_TRUE );
8377- }
8378-
8379- return (B_FALSE );
8380- }
8381-
8382- static int
8383- scrub_callback (zpool_handle_t * zhp , void * data )
8384- {
8385- scrub_cbdata_t * cb = data ;
8386- int err ;
8387-
8388- /*
8389- * Ignore faulted pools.
8390- */
8391- if (zpool_get_state (zhp ) == POOL_STATE_UNAVAIL ) {
8392- (void ) fprintf (stderr , gettext ("cannot scan '%s': pool is "
8393- "currently unavailable\n" ), zpool_get_name (zhp ));
8394- return (1 );
8395- }
8396-
8397- err = zpool_scan_range (zhp , cb -> cb_type , cb -> cb_scrub_cmd ,
8398- cb -> cb_date_start , cb -> cb_date_end );
8399- if (err == 0 && zpool_has_checkpoint (zhp ) &&
8400- cb -> cb_type == POOL_SCAN_SCRUB ) {
8401- (void ) printf (gettext ("warning: will not scrub state that "
8402- "belongs to the checkpoint of pool '%s'\n" ),
8403- zpool_get_name (zhp ));
8404- }
8405-
8406- return (err != 0 );
8407- }
8408-
84098428static int
84108429wait_callback (zpool_handle_t * zhp , void * data )
84118430{
@@ -8441,14 +8460,15 @@ struct zpool_scrub_option {
84418460};
84428461
84438462/*
8444- * zpool scrub [-e | -s | -p | -C | -E | -S] [-w] [-a | <pool> ...]
8463+ * zpool scrub [-e | -s | -p | -C | -E | -S | -R ] [-w] [-a | <pool> ...]
84458464 *
84468465 * -a Scrub all pools.
84478466 * -e Only scrub blocks in the error log.
84488467 * -E End date of scrub.
84498468 * -S Start date of scrub.
84508469 * -s Stop. Stops any in-progress scrub.
84518470 * -p Pause. Pause in-progress scrub.
8471+ * -R Scrub only recent data.
84528472 * -w Wait. Blocks until scrub has completed.
84538473 * -C Scrub from last saved txg.
84548474 */
@@ -8467,11 +8487,12 @@ zpool_do_scrub(int argc, char **argv)
84678487 struct zpool_scrub_option is_error_scrub = {'e' , B_FALSE };
84688488 struct zpool_scrub_option is_pause = {'p' , B_FALSE };
84698489 struct zpool_scrub_option is_stop = {'s' , B_FALSE };
8490+ struct zpool_scrub_option is_recent = {'R' , B_FALSE };
84708491 struct zpool_scrub_option is_txg_continue = {'C' , B_FALSE };
84718492 struct zpool_scrub_option scrub_all = {'a' , B_FALSE };
84728493
84738494 /* check options */
8474- while ((c = getopt (argc , argv , "aspweCE:S:" )) != -1 ) {
8495+ while ((c = getopt (argc , argv , "aspweCE:S:R " )) != -1 ) {
84758496 switch (c ) {
84768497 case 'a' :
84778498 scrub_all .enabled = B_TRUE ;
@@ -8495,6 +8516,9 @@ zpool_do_scrub(int argc, char **argv)
84958516 case 'p' :
84968517 is_pause .enabled = B_TRUE ;
84978518 break ;
8519+ case 'R' :
8520+ is_recent .enabled = B_TRUE ;
8521+ break ;
84988522 case 'w' :
84998523 wait .enabled = B_TRUE ;
85008524 break ;
@@ -8515,9 +8539,13 @@ zpool_do_scrub(int argc, char **argv)
85158539 {& is_stop , & is_pause },
85168540 {& is_stop , & is_txg_continue },
85178541 {& is_stop , & is_error_scrub },
8542+ {& is_stop , & is_recent },
85188543 {& is_pause , & is_txg_continue },
85198544 {& is_pause , & is_error_scrub },
8545+ {& is_pause , & is_recent },
85208546 {& is_error_scrub , & is_txg_continue },
8547+ {& is_error_scrub , & is_recent },
8548+ {& is_recent , & is_txg_continue },
85218549 };
85228550
85238551 for (int i = 0 ; i < sizeof (scrub_exclusive_options ) /
@@ -8542,6 +8570,8 @@ zpool_do_scrub(int argc, char **argv)
85428570 cb .cb_type = POOL_SCAN_NONE ;
85438571 } else if (is_txg_continue .enabled ) {
85448572 cb .cb_scrub_cmd = POOL_SCRUB_FROM_LAST_TXG ;
8573+ } else if (is_recent .enabled ) {
8574+ cb .cb_scrub_cmd = POOL_SCRUB_RECENT ;
85458575 } else {
85468576 cb .cb_scrub_cmd = POOL_SCRUB_NORMAL ;
85478577 }
0 commit comments