Skip to content

Commit

Permalink
scrub: add option to scrub only recent data
Browse files Browse the repository at this point in the history
Sponsored-By: Wasabi Technology, Inc.
Sponsored-By: Klara Inc.
Signed-off-by: Mariusz Zaborski <[email protected]>
  • Loading branch information
oshogbo committed Oct 31, 2024
1 parent 3acec49 commit b08bd76
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 9 deletions.
34 changes: 29 additions & 5 deletions cmd/zpool/zpool_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ get_usage(zpool_help_t idx)
return (gettext("\tinitialize [-c | -s | -u] [-w] <pool> "
"[<device> ...]\n"));
case HELP_SCRUB:
return (gettext("\tscrub [-e | -s | -p | -C] [-w] "
return (gettext("\tscrub [-e | -s | -p | -C | -R] [-w] "
"<pool> ...\n"));
case HELP_RESILVER:
return (gettext("\tresilver <pool> ...\n"));
Expand Down Expand Up @@ -8413,13 +8413,14 @@ wait_callback(zpool_handle_t *zhp, void *data)
}

/*
* zpool scrub [-e | -s | -p | -C] [-w] <pool> ...
* zpool scrub [-e | -s | -p | -C | -R] [-w] <pool> ...
*
* -e Only scrub blocks in the error log.
* -s Stop. Stops any in-progress scrub.
* -p Pause. Pause in-progress scrub.
* -w Wait. Blocks until scrub has completed.
* -C Scrub from last saved txg.
* -R Scrub only recent data.
*/
int
zpool_do_scrub(int argc, char **argv)
Expand All @@ -8436,9 +8437,10 @@ zpool_do_scrub(int argc, char **argv)
boolean_t is_pause = B_FALSE;
boolean_t is_stop = B_FALSE;
boolean_t is_txg_continue = B_FALSE;
boolean_t is_recent_scrub = B_FALSE;

/* check options */
while ((c = getopt(argc, argv, "spweC")) != -1) {
while ((c = getopt(argc, argv, "spweCR")) != -1) {
switch (c) {
case 'e':
is_error_scrub = B_TRUE;
Expand All @@ -8455,6 +8457,9 @@ zpool_do_scrub(int argc, char **argv)
case 'C':
is_txg_continue = B_TRUE;
break;
case 'R':
is_recent_scrub = B_TRUE;
break;
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
Expand All @@ -8478,11 +8483,30 @@ zpool_do_scrub(int argc, char **argv)
(void) fprintf(stderr, gettext("invalid option "
"combination :-e and -C are mutually exclusive\n"));
usage(B_FALSE);
} else if (is_recent_scrub && is_txg_continue) {
(void) fprintf(stderr, gettext("invalid option "
"combination :-R and -C are mutually exclusive\n"));
usage(B_FALSE);
} else if (is_pause && is_recent_scrub) {
(void) fprintf(stderr, gettext("invalid option "
"combination :-p and -R are mutually exclusive\n"));
usage(B_FALSE);
} else if (is_stop && is_recent_scrub) {
(void) fprintf(stderr, gettext("invalid option "
"combination :-s and -R are mutually exclusive\n"));
usage(B_FALSE);
} else if (is_error_scrub && is_recent_scrub) {
(void) fprintf(stderr, gettext("invalid option "
"combination :-e and -R are mutually exclusive\n"));
usage(B_FALSE);
} else {
if (is_error_scrub)
if (is_error_scrub) {
cb.cb_type = POOL_SCAN_ERRORSCRUB;
}

if (is_pause) {
if (is_recent_scrub) {
cb.cb_scrub_cmd = POOL_SCRUB_RECENT_TXGS;
} else if (is_pause) {
cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
} else if (is_stop) {
cb.cb_type = POOL_SCAN_NONE;
Expand Down
1 change: 1 addition & 0 deletions include/sys/dsl_scan.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ struct dsl_pool;
struct dmu_tx;

extern int zfs_scan_suspend_progress;
extern uint_t zfs_scrub_recent_txgs;

/*
* All members of this structure must be uint64_t, for byteswap
Expand Down
1 change: 1 addition & 0 deletions include/sys/fs/zfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,7 @@ typedef enum pool_scrub_cmd {
POOL_SCRUB_NORMAL = 0,
POOL_SCRUB_PAUSE,
POOL_SCRUB_FROM_LAST_TXG,
POOL_SCRUB_RECENT_TXGS,
POOL_SCRUB_FLAGS_END
} pool_scrub_cmd_t;

Expand Down
6 changes: 4 additions & 2 deletions lib/libzfs/libzfs.abi
Original file line number Diff line number Diff line change
Expand Up @@ -3132,7 +3132,8 @@
<enumerator name='ZPOOL_PROP_DEDUP_TABLE_SIZE' value='36'/>
<enumerator name='ZPOOL_PROP_DEDUP_TABLE_QUOTA' value='37'/>
<enumerator name='ZPOOL_PROP_DEDUPCACHED' value='38'/>
<enumerator name='ZPOOL_NUM_PROPS' value='39'/>
<enumerator name='ZPOOL_PROP_LAST_SCRUBBED_TXG' value='39'/>
<enumerator name='ZPOOL_NUM_PROPS' value='40'/>
</enum-decl>
<typedef-decl name='zpool_prop_t' type-id='af1ba157' id='5d0c23fb'/>
<typedef-decl name='regoff_t' type-id='95e97e5e' id='54a2a2a8'/>
Expand Down Expand Up @@ -5985,7 +5986,8 @@
<enumerator name='POOL_SCRUB_NORMAL' value='0'/>
<enumerator name='POOL_SCRUB_PAUSE' value='1'/>
<enumerator name='POOL_SCRUB_FROM_LAST_TXG' value='2'/>
<enumerator name='POOL_SCRUB_FLAGS_END' value='3'/>
<enumerator name='POOL_SCRUB_RECENT_TXGS' value='3'/>
<enumerator name='POOL_SCRUB_FLAGS_END' value='4'/>
</enum-decl>
<typedef-decl name='pool_scrub_cmd_t' type-id='a1474cbd' id='b51cf3c2'/>
<enum-decl name='zpool_errata' id='d9abbf54'>
Expand Down
2 changes: 1 addition & 1 deletion lib/libzfsbootenv/libzfsbootenv.abi
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<abi-corpus version='2.0' architecture='elf-amd-x86_64' soname='libzfsbootenv.so.1'>
<elf-needed>
<dependency name='libzfs.so.4'/>
<dependency name='libzfs.so.6'/>
<dependency name='libnvpair.so.3'/>
<dependency name='libc.so.6'/>
</elf-needed>
Expand Down
3 changes: 3 additions & 0 deletions man/man4/zfs.4
Original file line number Diff line number Diff line change
Expand Up @@ -2044,6 +2044,9 @@ working on a scrub between TXG flushes.
.It Sy zfs_scrub_error_blocks_per_txg Ns = Ns Sy 4096 Pq uint
Error blocks to be scrubbed in one txg.
.
.It Sy zfs_scrub_recent_txgs Ns = Ns Sy 256 Pq uint
Number of txgs to be considered as recent when performing a recent data scrub.
.
.It Sy zfs_scan_checkpoint_intval Ns = Ns Sy 7200 Ns s Po 2 hour Pc Pq uint
To preserve progress across reboots, the sequential scan algorithm periodically
needs to stop metadata scanning and issue all the verification I/O to disk.
Expand Down
6 changes: 5 additions & 1 deletion man/man8/zpool-scrub.8
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
.Sh SYNOPSIS
.Nm zpool
.Cm scrub
.Op Ns Fl e | Ns Fl p | Fl s Ns | Fl C Ns
.Op Ns Fl e | Ns Fl p | Fl s Ns | Fl C Ns | Fl R Ns
.Op Fl w
.Ar pool Ns
.
Expand Down Expand Up @@ -117,6 +117,10 @@ resilvering, nor can it be run when a regular scrub is paused.
Continue scrub from last saved txg (see zpool
.Sy last_scrubbed_txg
property).
.It Fl R
Scrub only recent data (this can be controlled by the
.Sy zfs_scrub_recent_txgs
parameter).
.El
.Sh EXAMPLES
.Ss Example 1
Expand Down
6 changes: 6 additions & 0 deletions module/zfs/dsl_scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,9 @@ static int zfs_free_bpobj_enabled = 1;
/* Error blocks to be scrubbed in one txg. */
static uint_t zfs_scrub_error_blocks_per_txg = 1 << 12;

/* The number of TXGs should be scrubbed while scrubbing recent data. */
uint_t zfs_scrub_recent_txgs = 256;

/* the order has to match pool_scan_type */
static scan_cb_t *scan_funcs[POOL_SCAN_FUNCS] = {
NULL,
Expand Down Expand Up @@ -5349,4 +5352,7 @@ ZFS_MODULE_PARAM(zfs, zfs_, resilver_defer_percent, UINT, ZMOD_RW,

ZFS_MODULE_PARAM(zfs, zfs_, scrub_error_blocks_per_txg, UINT, ZMOD_RW,
"Error blocks to be scrubbed in one txg");

ZFS_MODULE_PARAM(zfs, zfs_, scrub_recent_txgs, UINT, ZMOD_RW,
"The number of TXGs should be scrubbed while scrubbing recent data");
/* END CSTYLED */
10 changes: 10 additions & 0 deletions module/zfs/zfs_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1721,6 +1721,16 @@ zfs_ioc_pool_scrub(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
} else if (scan_cmd == POOL_SCRUB_FROM_LAST_TXG) {
error = spa_scan_range(spa, scan_type,
spa_get_last_scrubbed_txg(spa), 0);
} else if (scan_cmd == POOL_SCRUB_RECENT_TXGS) {
uint64_t start;

start = 0;
if (spa_last_synced_txg(spa) > zfs_scrub_recent_txgs) {
start = spa_last_synced_txg(spa) -
zfs_scrub_recent_txgs;
}

error = spa_scan_range(spa, scan_type, start, 0);
} else {
error = spa_scan(spa, scan_type);
}
Expand Down

0 comments on commit b08bd76

Please sign in to comment.