summaryrefslogtreecommitdiffstats
path: root/module/zfs
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs')
-rw-r--r--module/zfs/zvol.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c
index b2392305b..7730c28c6 100644
--- a/module/zfs/zvol.c
+++ b/module/zfs/zvol.c
@@ -1964,22 +1964,27 @@ zvol_remove_minors_impl(const char *name)
(strncmp(zv->zv_name, name, namelen) == 0 &&
(zv->zv_name[namelen] == '/' ||
zv->zv_name[namelen] == '@'))) {
-
- /* If in use, leave alone */
- if (zv->zv_open_count > 0 ||
- atomic_read(&zv->zv_suspend_ref))
- continue;
/*
* By taking zv_state_lock here, we guarantee that no
* one is currently using this zv
*/
mutex_enter(&zv->zv_state_lock);
+
+ /* If in use, leave alone */
+ if (zv->zv_open_count > 0 ||
+ atomic_read(&zv->zv_suspend_ref)) {
+ mutex_exit(&zv->zv_state_lock);
+ continue;
+ }
+
zvol_remove(zv);
- mutex_exit(&zv->zv_state_lock);
/* clear this so zvol_open won't open it */
zv->zv_disk->private_data = NULL;
+ /* Drop zv_state_lock before zvol_free() */
+ mutex_exit(&zv->zv_state_lock);
+
/* try parallel zv_free, if failed do it in place */
t = taskq_dispatch(system_taskq, zvol_free, zv,
TQ_SLEEP);
@@ -2021,19 +2026,24 @@ zvol_remove_minor_impl(const char *name)
zv_next = list_next(&zvol_state_list, zv);
if (strcmp(zv->zv_name, name) == 0) {
- /* If in use, leave alone */
- if (zv->zv_open_count > 0 ||
- atomic_read(&zv->zv_suspend_ref))
- continue;
/*
* By taking zv_state_lock here, we guarantee that no
* one is currently using this zv
*/
mutex_enter(&zv->zv_state_lock);
+
+ /* If in use, leave alone */
+ if (zv->zv_open_count > 0 ||
+ atomic_read(&zv->zv_suspend_ref)) {
+ mutex_exit(&zv->zv_state_lock);
+ continue;
+ }
zvol_remove(zv);
- mutex_exit(&zv->zv_state_lock);
+
/* clear this so zvol_open won't open it */
zv->zv_disk->private_data = NULL;
+
+ mutex_exit(&zv->zv_state_lock);
break;
}
}