mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 02:27:36 +03:00
Implemented zpool scrub pause/resume
Currently, there is no way to pause a scrub. Pausing may be useful when the pool is busy with other I/O to preserve bandwidth. This patch adds the ability to pause and resume scrubbing. This is achieved by maintaining a persistent on-disk scrub state. While the state is 'paused' we do not scrub any more blocks. We do however perform regular scan housekeeping such as freeing async destroyed and deadlist blocks while paused. Reviewed by: Matthew Ahrens <mahrens@delphix.com> Reviewed by: Thomas Caputi <tcaputi@datto.com> Reviewed-by: Serapheim Dimitropoulos <serapheimd@gmail.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Alek Pinchuk <apinchuk@datto.com> Closes #6167
This commit is contained in:
+32
-11
@@ -1898,22 +1898,39 @@ zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
|
||||
* Scan the pool.
|
||||
*/
|
||||
int
|
||||
zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func)
|
||||
zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func, pool_scrub_cmd_t cmd)
|
||||
{
|
||||
zfs_cmd_t zc = {"\0"};
|
||||
char msg[1024];
|
||||
int err;
|
||||
libzfs_handle_t *hdl = zhp->zpool_hdl;
|
||||
|
||||
(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
|
||||
zc.zc_cookie = func;
|
||||
zc.zc_flags = cmd;
|
||||
|
||||
if (zfs_ioctl(hdl, ZFS_IOC_POOL_SCAN, &zc) == 0 ||
|
||||
(errno == ENOENT && func != POOL_SCAN_NONE))
|
||||
if (zfs_ioctl(hdl, ZFS_IOC_POOL_SCAN, &zc) == 0)
|
||||
return (0);
|
||||
|
||||
err = errno;
|
||||
|
||||
/* ECANCELED on a scrub means we resumed a paused scrub */
|
||||
if (err == ECANCELED && func == POOL_SCAN_SCRUB &&
|
||||
cmd == POOL_SCRUB_NORMAL)
|
||||
return (0);
|
||||
|
||||
if (err == ENOENT && func != POOL_SCAN_NONE && cmd == POOL_SCRUB_NORMAL)
|
||||
return (0);
|
||||
|
||||
if (func == POOL_SCAN_SCRUB) {
|
||||
(void) snprintf(msg, sizeof (msg),
|
||||
dgettext(TEXT_DOMAIN, "cannot scrub %s"), zc.zc_name);
|
||||
if (cmd == POOL_SCRUB_PAUSE) {
|
||||
(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
|
||||
"cannot pause scrubbing %s"), zc.zc_name);
|
||||
} else {
|
||||
assert(cmd == POOL_SCRUB_NORMAL);
|
||||
(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
|
||||
"cannot scrub %s"), zc.zc_name);
|
||||
}
|
||||
} else if (func == POOL_SCAN_NONE) {
|
||||
(void) snprintf(msg, sizeof (msg),
|
||||
dgettext(TEXT_DOMAIN, "cannot cancel scrubbing %s"),
|
||||
@@ -1922,7 +1939,7 @@ zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func)
|
||||
assert(!"unexpected result");
|
||||
}
|
||||
|
||||
if (errno == EBUSY) {
|
||||
if (err == EBUSY) {
|
||||
nvlist_t *nvroot;
|
||||
pool_scan_stat_t *ps = NULL;
|
||||
uint_t psc;
|
||||
@@ -1931,14 +1948,18 @@ zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func)
|
||||
ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
|
||||
(void) nvlist_lookup_uint64_array(nvroot,
|
||||
ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &psc);
|
||||
if (ps && ps->pss_func == POOL_SCAN_SCRUB)
|
||||
return (zfs_error(hdl, EZFS_SCRUBBING, msg));
|
||||
else
|
||||
if (ps && ps->pss_func == POOL_SCAN_SCRUB) {
|
||||
if (cmd == POOL_SCRUB_PAUSE)
|
||||
return (zfs_error(hdl, EZFS_SCRUB_PAUSED, msg));
|
||||
else
|
||||
return (zfs_error(hdl, EZFS_SCRUBBING, msg));
|
||||
} else {
|
||||
return (zfs_error(hdl, EZFS_RESILVERING, msg));
|
||||
} else if (errno == ENOENT) {
|
||||
}
|
||||
} else if (err == ENOENT) {
|
||||
return (zfs_error(hdl, EZFS_NO_SCRUB, msg));
|
||||
} else {
|
||||
return (zpool_standard_error(hdl, errno, msg));
|
||||
return (zpool_standard_error(hdl, err, msg));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2011, 2014 by Delphix. All rights reserved.
|
||||
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
|
||||
* Copyright (c) 2017 Datto Inc.
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -246,6 +247,9 @@ libzfs_error_description(libzfs_handle_t *hdl)
|
||||
case EZFS_POSTSPLIT_ONLINE:
|
||||
return (dgettext(TEXT_DOMAIN, "disk was split from this pool "
|
||||
"into a new one"));
|
||||
case EZFS_SCRUB_PAUSED:
|
||||
return (dgettext(TEXT_DOMAIN, "scrub is paused; "
|
||||
"use 'zpool scrub' to resume"));
|
||||
case EZFS_SCRUBBING:
|
||||
return (dgettext(TEXT_DOMAIN, "currently scrubbing; "
|
||||
"use 'zpool scrub -s' to cancel current scrub"));
|
||||
|
||||
Reference in New Issue
Block a user