@@ -458,7 +458,8 @@ get_usage(zpool_help_t idx)
458458 return (gettext ("\tattach [-fsw] [-o property=value] "
459459 "<pool> <device> <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 :
@@ -8155,8 +8156,74 @@ zpool_do_offline(int argc, char **argv)
81558156 return (ret );
81568157}
81578158
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+
81588225/*
8159- * zpool clear [-nF ]|[--power] <pool> [device]
8226+ * zpool clear [-nsF ]|[--power] <pool> [device]
81608227 *
81618228 * Clear all errors associated with a pool or a particular device.
81628229 */
@@ -8169,6 +8236,7 @@ zpool_do_clear(int argc, char **argv)
81698236 boolean_t do_rewind = B_FALSE ;
81708237 boolean_t xtreme_rewind = B_FALSE ;
81718238 boolean_t is_power_on = B_FALSE ;
8239+ boolean_t scrub = B_FALSE ;
81728240 uint32_t rewind_policy = ZPOOL_NO_REWIND ;
81738241 nvlist_t * policy = NULL ;
81748242 zpool_handle_t * zhp ;
@@ -8180,7 +8248,7 @@ zpool_do_clear(int argc, char **argv)
81808248 };
81818249
81828250 /* check options */
8183- while ((c = getopt_long (argc , argv , "FnX " , long_options ,
8251+ while ((c = getopt_long (argc , argv , "FnsX " , long_options ,
81848252 NULL )) != -1 ) {
81858253 switch (c ) {
81868254 case 'F' :
@@ -8189,6 +8257,9 @@ zpool_do_clear(int argc, char **argv)
81898257 case 'n' :
81908258 dryrun = B_TRUE ;
81918259 break ;
8260+ case 's' :
8261+ scrub = B_TRUE ;
8262+ break ;
81928263 case 'X' :
81938264 xtreme_rewind = B_TRUE ;
81948265 break ;
@@ -8256,6 +8327,14 @@ zpool_do_clear(int argc, char **argv)
82568327 if (zpool_clear (zhp , device , policy ) != 0 )
82578328 ret = 1 ;
82588329
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+
82598338 zpool_close (zhp );
82608339
82618340 nvlist_free (policy );
@@ -8357,66 +8436,6 @@ zpool_do_reopen(int argc, char **argv)
83578436 return (ret );
83588437}
83598438
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-
84208439static int
84218440wait_callback (zpool_handle_t * zhp , void * data )
84228441{
@@ -8452,14 +8471,15 @@ struct zpool_scrub_option {
84528471};
84538472
84548473/*
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> ...]
84568475 *
84578476 * -a Scrub all pools.
84588477 * -e Only scrub blocks in the error log.
84598478 * -E End date of scrub.
84608479 * -S Start date of scrub.
84618480 * -s Stop. Stops any in-progress scrub.
84628481 * -p Pause. Pause in-progress scrub.
8482+ * -R Scrub only recent data.
84638483 * -w Wait. Blocks until scrub has completed.
84648484 * -C Scrub from last saved txg.
84658485 */
@@ -8478,11 +8498,12 @@ zpool_do_scrub(int argc, char **argv)
84788498 struct zpool_scrub_option is_error_scrub = {'e' , B_FALSE };
84798499 struct zpool_scrub_option is_pause = {'p' , B_FALSE };
84808500 struct zpool_scrub_option is_stop = {'s' , B_FALSE };
8501+ struct zpool_scrub_option is_recent = {'R' , B_FALSE };
84818502 struct zpool_scrub_option is_txg_continue = {'C' , B_FALSE };
84828503 struct zpool_scrub_option scrub_all = {'a' , B_FALSE };
84838504
84848505 /* check options */
8485- while ((c = getopt (argc , argv , "aspweCE:S:" )) != -1 ) {
8506+ while ((c = getopt (argc , argv , "aspweCE:S:R " )) != -1 ) {
84868507 switch (c ) {
84878508 case 'a' :
84888509 scrub_all .enabled = B_TRUE ;
@@ -8506,6 +8527,9 @@ zpool_do_scrub(int argc, char **argv)
85068527 case 'p' :
85078528 is_pause .enabled = B_TRUE ;
85088529 break ;
8530+ case 'R' :
8531+ is_recent .enabled = B_TRUE ;
8532+ break ;
85098533 case 'w' :
85108534 wait .enabled = B_TRUE ;
85118535 break ;
@@ -8526,9 +8550,13 @@ zpool_do_scrub(int argc, char **argv)
85268550 {& is_stop , & is_pause },
85278551 {& is_stop , & is_txg_continue },
85288552 {& is_stop , & is_error_scrub },
8553+ {& is_stop , & is_recent },
85298554 {& is_pause , & is_txg_continue },
85308555 {& is_pause , & is_error_scrub },
8556+ {& is_pause , & is_recent },
85318557 {& is_error_scrub , & is_txg_continue },
8558+ {& is_error_scrub , & is_recent },
8559+ {& is_recent , & is_txg_continue },
85328560 };
85338561
85348562 for (int i = 0 ; i < sizeof (scrub_exclusive_options ) /
@@ -8553,6 +8581,8 @@ zpool_do_scrub(int argc, char **argv)
85538581 cb .cb_type = POOL_SCAN_NONE ;
85548582 } else if (is_txg_continue .enabled ) {
85558583 cb .cb_scrub_cmd = POOL_SCRUB_FROM_LAST_TXG ;
8584+ } else if (is_recent .enabled ) {
8585+ cb .cb_scrub_cmd = POOL_SCRUB_RECENT ;
85568586 } else {
85578587 cb .cb_scrub_cmd = POOL_SCRUB_NORMAL ;
85588588 }
0 commit comments