From fa241660743d75a97001509c613b400fb60f26be Mon Sep 17 00:00:00 2001 From: Tom Caputi Date: Thu, 2 May 2019 19:42:31 -0400 Subject: [PATCH] Add feature check for 'zpool resilver' command The 'zpool resilver' command requires that the resilver_defer feature is active on the pool. Unfortunately, the check for this was left out of the original patch. This commit simply corrects this so that the command properly returns an error in this case. Reviewed by: Brian Behlendorf Reviewed-by: Igor Kozhukhov Signed-off-by: Tom Caputi Closes #8700 --- include/libzfs.h | 1 + lib/libzfs/libzfs_pool.c | 6 ++++++ lib/libzfs/libzfs_util.c | 3 +++ man/man8/zpool.8 | 4 +++- module/zfs/spa.c | 4 ++++ .../zpool_resilver/zpool_resilver_bad_args.ksh | 13 +++++++++++++ 6 files changed, 30 insertions(+), 1 deletion(-) diff --git a/include/libzfs.h b/include/libzfs.h index 8d79fe69e..e2ec2d9bc 100644 --- a/include/libzfs.h +++ b/include/libzfs.h @@ -146,6 +146,7 @@ typedef enum zfs_error { EZFS_TRIMMING, /* currently trimming */ EZFS_NO_TRIM, /* no active trim */ EZFS_TRIM_NOTSUP, /* device does not support trim */ + EZFS_NO_RESILVER_DEFER, /* pool doesn't support resilver_defer */ EZFS_UNKNOWN } zfs_error_t; diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c index 6c797d06b..a6e26ebcd 100644 --- a/lib/libzfs/libzfs_pool.c +++ b/lib/libzfs/libzfs_pool.c @@ -2354,6 +2354,10 @@ zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func, pool_scrub_cmd_t cmd) (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, "cannot scrub %s"), zc.zc_name); } + } else if (func == POOL_SCAN_RESILVER) { + assert(cmd == POOL_SCRUB_NORMAL); + (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, + "cannot restart resilver on %s"), zc.zc_name); } else if (func == POOL_SCAN_NONE) { (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, "cannot cancel scrubbing %s"), @@ -2381,6 +2385,8 @@ zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func, pool_scrub_cmd_t cmd) } } else if (err == ENOENT) { return (zfs_error(hdl, EZFS_NO_SCRUB, msg)); + } else if (err == ENOTSUP && func == POOL_SCAN_RESILVER) { + return (zfs_error(hdl, EZFS_NO_RESILVER_DEFER, msg)); } else { return (zpool_standard_error(hdl, err, msg)); } diff --git a/lib/libzfs/libzfs_util.c b/lib/libzfs/libzfs_util.c index b988d8f31..19bb57ad4 100644 --- a/lib/libzfs/libzfs_util.c +++ b/lib/libzfs/libzfs_util.c @@ -300,6 +300,9 @@ libzfs_error_description(libzfs_handle_t *hdl) case EZFS_TRIM_NOTSUP: return (dgettext(TEXT_DOMAIN, "trim operations are not " "supported by this device")); + case EZFS_NO_RESILVER_DEFER: + return (dgettext(TEXT_DOMAIN, "this action requires the " + "resilver_defer feature")); case EZFS_UNKNOWN: return (dgettext(TEXT_DOMAIN, "unknown error")); default: diff --git a/man/man8/zpool.8 b/man/man8/zpool.8 index eb93d3bb3..971501d8d 100644 --- a/man/man8/zpool.8 +++ b/man/man8/zpool.8 @@ -2216,7 +2216,9 @@ again. .Xc Starts a resilver. If an existing resilver is already running it will be restarted from the beginning. Any drives that were scheduled for a deferred -resilver will be added to the new one. +resilver will be added to the new one. This requires the +.Sy resilver_defer +feature. .It Xo .Nm .Cm trim diff --git a/module/zfs/spa.c b/module/zfs/spa.c index c76163b6f..4d26d698e 100644 --- a/module/zfs/spa.c +++ b/module/zfs/spa.c @@ -7261,6 +7261,10 @@ spa_scan(spa_t *spa, pool_scan_func_t func) if (func >= POOL_SCAN_FUNCS || func == POOL_SCAN_NONE) return (SET_ERROR(ENOTSUP)); + if (func == POOL_SCAN_RESILVER && + !spa_feature_is_enabled(spa, SPA_FEATURE_RESILVER_DEFER)) + return (SET_ERROR(ENOTSUP)); + /* * If a resilver was requested, but there is no DTL on a * writeable leaf device, we have nothing to do. diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_bad_args.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_bad_args.ksh index 9d973bec7..abd514086 100755 --- a/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_bad_args.ksh +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_resilver/zpool_resilver_bad_args.ksh @@ -35,6 +35,8 @@ # 1. Create an array containing bad 'zpool reilver' parameters. # 2. For each element, execute the sub-command. # 3. Verify it returns an error. +# 4. Confirm the sub-command returns an error if the resilver_defer +# feature isn't active. # verify_runnable "global" @@ -45,6 +47,13 @@ set -A args "" "-?" "blah blah" "-%" "--?" "-*" "-=" \ "-A" "-B" "-C" "-D" "-E" "-F" "-G" "-H" "-I" "-J" "-K" "-L" \ "-M" "-N" "-O" "-P" "-Q" "-R" "-S" "-T" "-U" "-V" "-W" "-X" "-W" "-Z" +function cleanup +{ + log_must destroy_pool $TESTPOOL2 + log_must rm -f $TEST_BASE_DIR/zpool_resilver.dat +} + +log_onexit cleanup log_assert "Execute 'zpool resilver' using invalid parameters." @@ -55,4 +64,8 @@ while [[ $i -lt ${#args[*]} ]]; do ((i = i + 1)) done +log_must mkfile $MINVDEVSIZE $TEST_BASE_DIR/zpool_resilver.dat +log_must zpool create -d $TESTPOOL2 $TEST_BASE_DIR/zpool_resilver.dat +log_mustnot zpool resilver $TESTPOOL2 + log_pass "Badly formed 'zpool resilver' parameters fail as expected."