diff options
-rw-r--r-- | module/os/linux/zfs/zvol_os.c | 13 | ||||
-rw-r--r-- | module/zfs/zvol.c | 7 |
2 files changed, 14 insertions, 6 deletions
diff --git a/module/os/linux/zfs/zvol_os.c b/module/os/linux/zfs/zvol_os.c index b89028dc3..2cb0cfca7 100644 --- a/module/os/linux/zfs/zvol_os.c +++ b/module/os/linux/zfs/zvol_os.c @@ -845,6 +845,11 @@ out_kmem: * At this time, the structure is not opened by anyone, is taken off * the zvol_state_list, and has its private data set to NULL. * The zvol_state_lock is dropped. + * + * This function may take many milliseconds to complete (e.g. we've seen + * it take over 256ms), due to the calls to "blk_cleanup_queue" and + * "del_gendisk". Thus, consumers need to be careful to account for this + * latency when calling this function. */ static void zvol_free(zvol_state_t *zv) @@ -1089,6 +1094,14 @@ zvol_fini(void) { zvol_remove_minors_impl(NULL); + /* + * The call to "zvol_remove_minors_impl" may dispatch entries to + * the system_taskq, but it doesn't wait for those entires to + * complete before it returns. Thus, we must wait for all of the + * removals to finish, before we can continue. + */ + taskq_wait_outstanding(system_taskq, 0); + zvol_fini_impl(); blk_unregister_region(MKDEV(zvol_major, 0), 1UL << MINORBITS); unregister_blkdev(zvol_major, ZVOL_DRIVER); diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c index 9b26084bb..e76a1c61b 100644 --- a/module/zfs/zvol.c +++ b/module/zfs/zvol.c @@ -1170,7 +1170,7 @@ zvol_remove_minors_impl(const char *name) { zvol_state_t *zv, *zv_next; int namelen = ((name) ? strlen(name) : 0); - taskqid_t t, tid = TASKQID_INVALID; + taskqid_t t; list_t free_list; if (zvol_inhibit_dev) @@ -1217,8 +1217,6 @@ zvol_remove_minors_impl(const char *name) (task_func_t *)ops->zv_free, zv, TQ_SLEEP); if (t == TASKQID_INVALID) list_insert_head(&free_list, zv); - else - tid = t; } else { mutex_exit(&zv->zv_state_lock); } @@ -1230,9 +1228,6 @@ zvol_remove_minors_impl(const char *name) list_remove(&free_list, zv); ops->zv_free(zv); } - - if (tid != TASKQID_INVALID) - taskq_wait_outstanding(system_taskq, tid); } /* Remove minor for this specific volume only */ |