summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Levon <john.levon@joyent.com>2018-03-19 17:00:42 +0000
committerJohn Levon <john.levon@joyent.com>2018-03-21 19:39:31 +0000
commitf3195f72a46cb863b80329145921191a60882155 (patch)
treef69f4da970520bf5630516887a56eca019efc63a
parent15c41273372517a01fee3e63e3ce3edbe11a8de1 (diff)
downloadillumos-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.c9
-rw-r--r--usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c9
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");