diff options
author | John Levon <john.levon@joyent.com> | 2018-03-19 17:00:42 +0000 |
---|---|---|
committer | John Levon <john.levon@joyent.com> | 2018-03-21 19:39:31 +0000 |
commit | f3195f72a46cb863b80329145921191a60882155 (patch) | |
tree | f69f4da970520bf5630516887a56eca019efc63a | |
parent | 15c41273372517a01fee3e63e3ce3edbe11a8de1 (diff) | |
download | illumos-joyent-f3195f72a46cb863b80329145921191a60882155.tar.gz |
OS-6791 sdev_plugin_unregister() can deadlock
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: Hans Rosenfeld <hans.rosenfeld@joyent.com>
-rw-r--r-- | usr/src/uts/common/fs/dev/sdev_plugin.c | 9 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c | 9 |
2 files changed, 14 insertions, 4 deletions
diff --git a/usr/src/uts/common/fs/dev/sdev_plugin.c b/usr/src/uts/common/fs/dev/sdev_plugin.c index 9100900bef..6e1618dc3c 100644 --- a/usr/src/uts/common/fs/dev/sdev_plugin.c +++ b/usr/src/uts/common/fs/dev/sdev_plugin.c @@ -701,11 +701,17 @@ sdev_plugin_unregister_cb(sdev_node_t *rdp, void *arg) rw_exit(&rdp->sdev_contents); } +int sdev_plugin_unregister_allowed; + /* * Remove a plugin. This will block until everything has become a zombie, thus * guaranteeing the caller that nothing will call into them again once this call * returns. While the call is ongoing, it could be called into. Note that while * this is ongoing, it will block other mounts. + * + * NB: this is not safe when used from detach() context - we will be DEVI_BUSY, + * and other sdev threads may be waiting for this. Only use the over-ride if + * willing to risk it. */ int sdev_plugin_unregister(sdev_plugin_hdl_t hdl) @@ -714,6 +720,9 @@ sdev_plugin_unregister(sdev_plugin_hdl_t hdl) if (spp->sp_islegacy) return (EINVAL); + if (!sdev_plugin_unregister_allowed) + return (EBUSY); + mutex_enter(&sdev_plugin_lock); list_remove(&sdev_plugin_list, spp); mutex_exit(&sdev_plugin_lock); diff --git a/usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c b/usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c index 602889b779..b6f3e40e0a 100644 --- a/usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c +++ b/usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c @@ -1982,17 +1982,18 @@ vmm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) mutex_exit(&vmm_mtx); - /* XXX: This needs updating */ - if (!vmm_arena_fini()) { + if (vmm_sdev_hdl != NULL && sdev_plugin_unregister(vmm_sdev_hdl) != 0) { mutex_exit(&vmmdev_mtx); return (DDI_FAILURE); } - if (vmm_sdev_hdl != NULL && sdev_plugin_unregister(vmm_sdev_hdl) != 0) { + vmm_sdev_hdl = NULL; + + /* XXX: This needs updating */ + if (!vmm_arena_fini()) { mutex_exit(&vmmdev_mtx); return (DDI_FAILURE); } - vmm_sdev_hdl = NULL; /* Remove the control node. */ ddi_remove_minor_node(dip, "ctl"); |