diff options
author | George Wilson <[email protected]> | 2018-12-19 09:20:39 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2019-01-07 11:03:08 -0800 |
commit | c10d37dd9f5d56e19330add732f1a713250d24f7 (patch) | |
tree | a43f6b7c1592612fe4277bcaf5d99c02543523b8 /include/sys | |
parent | 619f09769393d4e0cbaa5f662362138e1c699159 (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 'include/sys')
-rw-r--r-- | include/sys/spa.h | 3 | ||||
-rw-r--r-- | include/sys/vdev_impl.h | 1 | ||||
-rw-r--r-- | include/sys/vdev_initialize.h | 5 |
3 files changed, 7 insertions, 2 deletions
diff --git a/include/sys/spa.h b/include/sys/spa.h index 4a66260ef..febf0e8f2 100644 --- a/include/sys/spa.h +++ b/include/sys/spa.h @@ -788,7 +788,8 @@ extern int spa_vdev_detach(spa_t *spa, uint64_t guid, uint64_t pguid, int replace_done); extern int spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare); extern boolean_t spa_vdev_remove_active(spa_t *spa); -extern int spa_vdev_initialize(spa_t *spa, uint64_t guid, uint64_t cmd_type); +extern int spa_vdev_initialize(spa_t *spa, nvlist_t *nv, uint64_t cmd_type, + nvlist_t *vdev_errlist); extern int spa_vdev_setpath(spa_t *spa, uint64_t guid, const char *newpath); extern int spa_vdev_setfru(spa_t *spa, uint64_t guid, const char *newfru); extern int spa_vdev_split_mirror(spa_t *spa, char *newname, nvlist_t *config, diff --git a/include/sys/vdev_impl.h b/include/sys/vdev_impl.h index ae21e037e..5fe05c54b 100644 --- a/include/sys/vdev_impl.h +++ b/include/sys/vdev_impl.h @@ -263,6 +263,7 @@ struct vdev { boolean_t vdev_initialize_exit_wanted; vdev_initializing_state_t vdev_initialize_state; + list_node_t vdev_initialize_node; kthread_t *vdev_initialize_thread; /* Protects vdev_initialize_thread and vdev_initialize_state. */ kmutex_t vdev_initialize_lock; diff --git a/include/sys/vdev_initialize.h b/include/sys/vdev_initialize.h index db4b0572c..319fb9bc0 100644 --- a/include/sys/vdev_initialize.h +++ b/include/sys/vdev_initialize.h @@ -26,15 +26,18 @@ #ifndef _SYS_VDEV_INITIALIZE_H #define _SYS_VDEV_INITIALIZE_H +#include <sys/spa.h> + #ifdef __cplusplus extern "C" { #endif extern void vdev_initialize(vdev_t *vd); extern void vdev_initialize_stop(vdev_t *vd, - vdev_initializing_state_t tgt_state); + vdev_initializing_state_t tgt_state, list_t *vd_list); extern void vdev_initialize_stop_all(vdev_t *vd, vdev_initializing_state_t tgt_state); +extern void vdev_initialize_stop_wait(spa_t *spa, list_t *vd_list); extern void vdev_initialize_restart(vdev_t *vd); extern void vdev_xlate(vdev_t *vd, const range_seg_t *logical_rs, range_seg_t *physical_rs); |