diff options
author | Boris Protopopov <[email protected]> | 2014-03-22 05:07:14 -0400 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2016-03-10 09:49:22 -0800 |
commit | a0bd735adb1b1eb81fef10b4db102ee051c4d4ff (patch) | |
tree | 121fcde3000a116f0c33143b28a530a87fd6073a /module/zfs/spa.c | |
parent | eb0856779f7b57162c9179f238104f6d6e150745 (diff) |
Add support for asynchronous zvol minor operations
zfsonlinux issue #2217 - zvol minor operations: check snapdev
property before traversing snapshots of a dataset
zfsonlinux issue #3681 - lock order inversion between zvol_open()
and dsl_pool_sync()...zvol_rename_minors()
Create a per-pool zvol taskq for asynchronous zvol tasks.
There are a few key design decisions to be aware of.
* Each taskq must be single threaded to ensure tasks are always
processed in the order in which they were dispatched.
* There is a taskq per-pool in order to keep the pools independent.
This way if one pool is suspended it will not impact another.
* The preferred location to dispatch a zvol minor task is a sync
task. In this context there is easy access to the spa_t and
minimal error handling is required because the sync task must
succeed.
Support for asynchronous zvol minor operations address issue #3681.
Signed-off-by: Boris Protopopov <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes #2217
Closes #3678
Closes #3681
Diffstat (limited to 'module/zfs/spa.c')
-rw-r--r-- | module/zfs/spa.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/module/zfs/spa.c b/module/zfs/spa.c index 34a317fbe..01048bfe9 100644 --- a/module/zfs/spa.c +++ b/module/zfs/spa.c @@ -24,6 +24,7 @@ * Copyright (c) 2013 by Delphix. All rights reserved. * Copyright (c) 2013, 2014, Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. + * Copyright (c) 2016 Actifio, Inc. All rights reserved. */ /* @@ -1136,6 +1137,24 @@ spa_activate(spa_t *spa, int mode) avl_create(&spa->spa_errlist_last, spa_error_entry_compare, sizeof (spa_error_entry_t), offsetof(spa_error_entry_t, se_avl)); + + /* + * This taskq is used to perform zvol-minor-related tasks + * asynchronously. This has several advantages, including easy + * resolution of various deadlocks (zfsonlinux bug #3681). + * + * The taskq must be single threaded to ensure tasks are always + * processed in the order in which they were dispatched. + * + * A taskq per pool allows one to keep the pools independent. + * This way if one pool is suspended, it will not impact another. + * + * The preferred location to dispatch a zvol minor task is a sync + * task. In this context, there is easy access to the spa_t and minimal + * error handling is required because the sync task must succeed. + */ + spa->spa_zvol_taskq = taskq_create("z_zvol", 1, defclsyspri, + 1, INT_MAX, 0); } /* @@ -1154,6 +1173,11 @@ spa_deactivate(spa_t *spa) spa_evicting_os_wait(spa); + if (spa->spa_zvol_taskq) { + taskq_destroy(spa->spa_zvol_taskq); + spa->spa_zvol_taskq = NULL; + } + txg_list_destroy(&spa->spa_vdev_txg_list); list_destroy(&spa->spa_config_dirty_list); @@ -3088,10 +3112,8 @@ spa_open_common(const char *pool, spa_t **spapp, void *tag, nvlist_t *nvpolicy, mutex_exit(&spa_namespace_lock); } -#ifdef _KERNEL if (firstopen) - zvol_create_minors(spa->spa_name); -#endif + zvol_create_minors(spa, spa_name(spa), B_TRUE); *spapp = spa; @@ -4211,10 +4233,7 @@ spa_import(char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags) mutex_exit(&spa_namespace_lock); spa_history_log_version(spa, "import"); - -#ifdef _KERNEL - zvol_create_minors(pool); -#endif + zvol_create_minors(spa, pool, B_TRUE); return (0); } @@ -4349,6 +4368,10 @@ spa_export_common(char *pool, int new_state, nvlist_t **oldconfig, spa_open_ref(spa, FTAG); mutex_exit(&spa_namespace_lock); spa_async_suspend(spa); + if (spa->spa_zvol_taskq) { + zvol_remove_minors(spa, spa_name(spa), B_TRUE); + taskq_wait(spa->spa_zvol_taskq); + } mutex_enter(&spa_namespace_lock); spa_close(spa, FTAG); |