summaryrefslogtreecommitdiffstats
path: root/cddl/contrib/opensolaris/lib/libzfs/common
diff options
context:
space:
mode:
authoravg <avg@FreeBSD.org>2017-09-26 09:34:18 +0000
committeravg <avg@FreeBSD.org>2017-09-26 09:34:18 +0000
commitb60520398f206195e21774c315afb59a0f6d7146 (patch)
treecd1f348c5d90819cdc0225e23d3466438421b2b4 /cddl/contrib/opensolaris/lib/libzfs/common
parent3b00a62a3635ddfd563366ae6b35d38adbf61dde (diff)
downloadFreeBSD-src-b60520398f206195e21774c315afb59a0f6d7146.zip
FreeBSD-src-b60520398f206195e21774c315afb59a0f6d7146.tar.gz
MFC r323355: MFV r323107: 8414 Implemented zpool scrub pause/resume
illumos/illumos-gate@1702cce751c5cb7ead878d0205a6c90b027e3de8 https://github.com/illumos/illumos-gate/commit/1702cce751c5cb7ead878d0205a6c90b027e3de8 FreeBSD note: rather than merging the zpool.8 update I copied the zpool scrub section from the illumos zpool.1m to FreeBSD zpool.8 almost verbatim. Now that the illumos page uses the mdoc format, it was an easier option. Perhaps the change is not in perfect compliance with the FreeBSD style, but I think that it is acceptible. https://www.illumos.org/issues/8414 This issue tracks the port of scrub pause from ZoL: https://github.com/zfsonlinux/zfs/pull/6167 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. Description 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. Motivation and Context Scrub pausing can be an I/O intensive operation and people have been asking for the ability to pause a scrub for a while. This allows one to preserve scrub progress while freeing up bandwidth for other I/O. Reviewed by: George Melikov <mail@gmelikov.ru> Reviewed by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed by: Brad Lewis <brad.lewis@delphix.com> Reviewed by: Serapheim Dimitropoulos <serapheim@delphix.com> Reviewed by: Matt Ahrens <mahrens@delphix.com> Approved by: Dan McDonald <danmcd@joyent.com> Author: Alek Pinchuk <apinchuk@datto.com>
Diffstat (limited to 'cddl/contrib/opensolaris/lib/libzfs/common')
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h4
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c44
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c4
3 files changed, 40 insertions, 12 deletions
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
index 937e9b2..f2a9ebf 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
@@ -28,6 +28,7 @@
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2016 Nexenta Systems, Inc.
+ * Copyright (c) 2017 Datto Inc.
*/
#ifndef _LIBZFS_H
@@ -129,6 +130,7 @@ typedef enum zfs_error {
EZFS_DIFF, /* general failure of zfs diff */
EZFS_DIFFDATA, /* bad zfs diff data */
EZFS_POOLREADONLY, /* pool is in read-only mode */
+ EZFS_SCRUB_PAUSED, /* scrub currently paused */
EZFS_UNKNOWN
} zfs_error_t;
@@ -241,7 +243,7 @@ typedef struct splitflags {
/*
* Functions to manipulate pool and vdev state
*/
-extern int zpool_scan(zpool_handle_t *, pool_scan_func_t);
+extern int zpool_scan(zpool_handle_t *, pool_scan_func_t, pool_scrub_cmd_t);
extern int zpool_clear(zpool_handle_t *, const char *, nvlist_t *);
extern int zpool_reguid(zpool_handle_t *);
extern int zpool_reopen(zpool_handle_t *);
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
index af1767f..f2efcba 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
@@ -25,6 +25,7 @@
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright 2016 Nexenta Systems, Inc.
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
+ * Copyright (c) 2017 Datto Inc.
*/
#include <sys/types.h>
@@ -1841,22 +1842,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)
+ return (0);
+
+ err = errno;
- if (zfs_ioctl(hdl, ZFS_IOC_POOL_SCAN, &zc) == 0 ||
- (errno == ENOENT && func != POOL_SCAN_NONE))
+ /* 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"),
@@ -1865,7 +1883,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;
@@ -1874,14 +1892,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));
}
}
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c
index b60e25e..a2ae8b0 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_util.c
@@ -24,6 +24,7 @@
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
+ * Copyright (c) 2017 Datto Inc.
*/
/*
@@ -224,6 +225,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"));
OpenPOWER on IntegriCloud