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 <behlendorf1@llnl.gov>
Reviewed-by: Igor Kozhukhov <igor@dilos.org>
Signed-off-by: Tom Caputi <tcaputi@datto.com>
Closes #8700
This commit is contained in:
Tom Caputi 2019-05-02 19:42:31 -04:00 committed by Brian Behlendorf
parent 85bdc68401
commit fa24166074
6 changed files with 30 additions and 1 deletions

View File

@ -146,6 +146,7 @@ typedef enum zfs_error {
EZFS_TRIMMING, /* currently trimming */ EZFS_TRIMMING, /* currently trimming */
EZFS_NO_TRIM, /* no active trim */ EZFS_NO_TRIM, /* no active trim */
EZFS_TRIM_NOTSUP, /* device does not support trim */ EZFS_TRIM_NOTSUP, /* device does not support trim */
EZFS_NO_RESILVER_DEFER, /* pool doesn't support resilver_defer */
EZFS_UNKNOWN EZFS_UNKNOWN
} zfs_error_t; } zfs_error_t;

View File

@ -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, (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
"cannot scrub %s"), zc.zc_name); "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) { } else if (func == POOL_SCAN_NONE) {
(void) snprintf(msg, sizeof (msg), (void) snprintf(msg, sizeof (msg),
dgettext(TEXT_DOMAIN, "cannot cancel scrubbing %s"), 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) { } else if (err == ENOENT) {
return (zfs_error(hdl, EZFS_NO_SCRUB, msg)); 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 { } else {
return (zpool_standard_error(hdl, err, msg)); return (zpool_standard_error(hdl, err, msg));
} }

View File

@ -300,6 +300,9 @@ libzfs_error_description(libzfs_handle_t *hdl)
case EZFS_TRIM_NOTSUP: case EZFS_TRIM_NOTSUP:
return (dgettext(TEXT_DOMAIN, "trim operations are not " return (dgettext(TEXT_DOMAIN, "trim operations are not "
"supported by this device")); "supported by this device"));
case EZFS_NO_RESILVER_DEFER:
return (dgettext(TEXT_DOMAIN, "this action requires the "
"resilver_defer feature"));
case EZFS_UNKNOWN: case EZFS_UNKNOWN:
return (dgettext(TEXT_DOMAIN, "unknown error")); return (dgettext(TEXT_DOMAIN, "unknown error"));
default: default:

View File

@ -2216,7 +2216,9 @@ again.
.Xc .Xc
Starts a resilver. If an existing resilver is already running it will be 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 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 .It Xo
.Nm .Nm
.Cm trim .Cm trim

View File

@ -7261,6 +7261,10 @@ spa_scan(spa_t *spa, pool_scan_func_t func)
if (func >= POOL_SCAN_FUNCS || func == POOL_SCAN_NONE) if (func >= POOL_SCAN_FUNCS || func == POOL_SCAN_NONE)
return (SET_ERROR(ENOTSUP)); 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 * If a resilver was requested, but there is no DTL on a
* writeable leaf device, we have nothing to do. * writeable leaf device, we have nothing to do.

View File

@ -35,6 +35,8 @@
# 1. Create an array containing bad 'zpool reilver' parameters. # 1. Create an array containing bad 'zpool reilver' parameters.
# 2. For each element, execute the sub-command. # 2. For each element, execute the sub-command.
# 3. Verify it returns an error. # 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" verify_runnable "global"
@ -45,6 +47,13 @@ set -A args "" "-?" "blah blah" "-%" "--?" "-*" "-=" \
"-A" "-B" "-C" "-D" "-E" "-F" "-G" "-H" "-I" "-J" "-K" "-L" \ "-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" "-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." log_assert "Execute 'zpool resilver' using invalid parameters."
@ -55,4 +64,8 @@ while [[ $i -lt ${#args[*]} ]]; do
((i = i + 1)) ((i = i + 1))
done 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." log_pass "Badly formed 'zpool resilver' parameters fail as expected."