@@ -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