aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs/zfs_ioctl.c
diff options
context:
space:
mode:
authorGeorge Wilson <[email protected]>2018-12-19 09:20:39 -0700
committerBrian Behlendorf <[email protected]>2019-01-07 11:03:08 -0800
commitc10d37dd9f5d56e19330add732f1a713250d24f7 (patch)
treea43f6b7c1592612fe4277bcaf5d99c02543523b8 /module/zfs/zfs_ioctl.c
parent619f09769393d4e0cbaa5f662362138e1c699159 (diff)
zfs initialize performance enhancements
PROBLEM ======== When invoking "zpool initialize" on a pool the command will create a thread to initialize each disk. Unfortunately, it does this serially across many transaction groups which can result in commands taking a long time to return to the user and may appear hung. The same thing is true when trying to suspend/cancel the operation. SOLUTION ========= This change refactors the way we invoke the initialize interface to ensure we can start or stop the intialization in just a few transaction groups. When stopping or cancelling a vdev initialization perform it in two phases. First signal each vdev initialization thread that it should exit, then after all threads have been signaled wait for them to exit. On a pool with 40 leaf vdevs this reduces the vdev initialize stop/cancel time from ~10 minutes to under a second. The reason for this is spa_vdev_initialize() no longer needs to wait on multiple full TXGs per leaf vdev being stopped. This commit additionally adds some missing checks for the passed "initialize_vdevs" input nvlist. The contents of the user provided input "initialize_vdevs" nvlist must be validated to ensure all values are uint64s. This is done in zfs_ioc_pool_initialize() in order to keep all of these checks in a single location. Updated the innvl and outnvl comments to match the formatting used for all other new sytle ioctls. Reviewed by: Matt Ahrens <[email protected]> Reviewed-by: loli10K <[email protected]> Reviewed-by: Tim Chase <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Signed-off-by: George Wilson <[email protected]> Closes #8230
Diffstat (limited to 'module/zfs/zfs_ioctl.c')
-rw-r--r--module/zfs/zfs_ioctl.c57
1 files changed, 26 insertions, 31 deletions
diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c
index 3c36502d8..0dfa01684 100644
--- a/module/zfs/zfs_ioctl.c
+++ b/module/zfs/zfs_ioctl.c
@@ -3846,73 +3846,68 @@ zfs_ioc_destroy(zfs_cmd_t *zc)
/*
* innvl: {
- * vdevs: {
- * guid 1, guid 2, ...
+ * "initialize_command" -> POOL_INITIALIZE_{CANCEL|DO|SUSPEND} (uint64)
+ * "initialize_vdevs": { -> guids to initialize (nvlist)
+ * "vdev_path_1": vdev_guid_1, (uint64),
+ * "vdev_path_2": vdev_guid_2, (uint64),
+ * ...
* },
- * func: POOL_INITIALIZE_{CANCEL|DO|SUSPEND}
* }
*
* outnvl: {
- * [func: EINVAL (if provided command type didn't make sense)],
- * [vdevs: {
- * guid1: errno, (see function body for possible errnos)
+ * "initialize_vdevs": { -> initialization errors (nvlist)
+ * "vdev_path_1": errno, see function body for possible errnos (uint64)
+ * "vdev_path_2": errno, ... (uint64)
* ...
- * }]
+ * }
* }
*
+ * EINVAL is returned for an unknown commands or if any of the provided vdev
+ * guids have be specified with a type other than uint64.
*/
static const zfs_ioc_key_t zfs_keys_pool_initialize[] = {
- {ZPOOL_INITIALIZE_COMMAND, DATA_TYPE_UINT64, 0},
+ {ZPOOL_INITIALIZE_COMMAND, DATA_TYPE_UINT64, 0},
{ZPOOL_INITIALIZE_VDEVS, DATA_TYPE_NVLIST, 0}
};
static int
zfs_ioc_pool_initialize(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
{
- spa_t *spa;
- int error;
-
- error = spa_open(poolname, &spa, FTAG);
- if (error != 0)
- return (error);
-
uint64_t cmd_type;
if (nvlist_lookup_uint64(innvl, ZPOOL_INITIALIZE_COMMAND,
&cmd_type) != 0) {
- spa_close(spa, FTAG);
return (SET_ERROR(EINVAL));
}
+
if (!(cmd_type == POOL_INITIALIZE_CANCEL ||
cmd_type == POOL_INITIALIZE_DO ||
cmd_type == POOL_INITIALIZE_SUSPEND)) {
- spa_close(spa, FTAG);
return (SET_ERROR(EINVAL));
}
nvlist_t *vdev_guids;
if (nvlist_lookup_nvlist(innvl, ZPOOL_INITIALIZE_VDEVS,
&vdev_guids) != 0) {
- spa_close(spa, FTAG);
return (SET_ERROR(EINVAL));
}
- nvlist_t *vdev_errlist = fnvlist_alloc();
- int total_errors = 0;
-
for (nvpair_t *pair = nvlist_next_nvpair(vdev_guids, NULL);
pair != NULL; pair = nvlist_next_nvpair(vdev_guids, pair)) {
- uint64_t vdev_guid = fnvpair_value_uint64(pair);
-
- error = spa_vdev_initialize(spa, vdev_guid, cmd_type);
- if (error != 0) {
- char guid_as_str[MAXNAMELEN];
-
- (void) snprintf(guid_as_str, sizeof (guid_as_str),
- "%llu", (unsigned long long)vdev_guid);
- fnvlist_add_int64(vdev_errlist, guid_as_str, error);
- total_errors++;
+ uint64_t vdev_guid;
+ if (nvpair_value_uint64(pair, &vdev_guid) != 0) {
+ return (SET_ERROR(EINVAL));
}
}
+
+ spa_t *spa;
+ int error = spa_open(poolname, &spa, FTAG);
+ if (error != 0)
+ return (error);
+
+ nvlist_t *vdev_errlist = fnvlist_alloc();
+ int total_errors = spa_vdev_initialize(spa, vdev_guids, cmd_type,
+ vdev_errlist);
+
if (fnvlist_size(vdev_errlist) > 0) {
fnvlist_add_nvlist(outnvl, ZPOOL_INITIALIZE_VDEVS,
vdev_errlist);