Page MenuHomeFreeBSD

D60022.diff
No OneTemporary

D60022.diff

diff --git a/sys/fs/cuse/cuse.c b/sys/fs/cuse/cuse.c
--- a/sys/fs/cuse/cuse.c
+++ b/sys/fs/cuse/cuse.c
@@ -268,33 +268,6 @@
sx_xunlock(&pccmd->sx);
}
-static int
-cuse_kern_init(void)
-{
- TAILQ_INIT(&cuse_server_head);
-
- mtx_init(&cuse_global_mtx, "cuse-global-mtx", NULL, MTX_DEF);
-
- cuse_dev = make_dev_credf(MAKEDEV_CHECKNAME,
- &cuse_server_devsw, 0, NULL, UID_ROOT, GID_OPERATOR, 0600, "cuse");
- if (cuse_dev == NULL)
- return (ENODEV);
-
- return (0);
-}
-
-static void
-cuse_kern_uninit(void)
-{
- /* destroy_dev() runs the cdevpriv destructor of every open instance. */
- if (cuse_dev != NULL)
- destroy_dev(cuse_dev);
-
- MPASS(TAILQ_EMPTY(&cuse_server_head));
-
- mtx_destroy(&cuse_global_mtx);
-}
-
static int
cuse_server_get(struct cuse_server **ppcs)
{
@@ -667,19 +640,24 @@
{
struct cuse_memory *mem;
+ /*
+ * Take the global lock before the server lock, to avoid a lock order
+ * reversal in cuse_kern_uninit().
+ */
+ cuse_global_lock();
cuse_server_lock(pcs);
if (--(pcs->refs) != 0) {
cuse_server_unlock(pcs);
+ cuse_global_unlock();
return;
}
+ TAILQ_REMOVE(&cuse_server_head, pcs, entry);
+ cuse_global_unlock();
+
cuse_server_is_closing(pcs);
/* final client wakeup, if any */
cuse_server_wakeup_all_client_locked(pcs);
- cuse_global_lock();
- TAILQ_REMOVE(&cuse_server_head, pcs, entry);
- cuse_global_unlock();
-
cuse_server_free_devs_locked(pcs);
cuse_free_unit_by_id_locked(pcs, -1);
@@ -1082,10 +1060,10 @@
cuse_server_lock(pcs);
while ((pccmd = TAILQ_FIRST(&pcs->head)) == NULL) {
- error = cv_wait_sig(&pcs->cv, &pcs->mtx);
-
if (pcs->is_closing)
error = ENXIO;
+ else
+ error = cv_wait_sig(&pcs->cv, &pcs->mtx);
if (error) {
cuse_server_unlock(pcs);
@@ -2025,6 +2003,48 @@
return (error);
}
+static int
+cuse_kern_init(void)
+{
+ TAILQ_INIT(&cuse_server_head);
+
+ mtx_init(&cuse_global_mtx, "cuse-global-mtx", NULL, MTX_DEF);
+
+ cuse_dev = make_dev_credf(MAKEDEV_CHECKNAME,
+ &cuse_server_devsw, 0, NULL, UID_ROOT, GID_OPERATOR, 0600, "cuse");
+ if (cuse_dev == NULL)
+ return (ENODEV);
+
+ return (0);
+}
+
+static void
+cuse_kern_uninit(void)
+{
+ struct cuse_server *pcs;
+
+ /*
+ * Wake up the servers sleeping in CUSE_IOCTL_GET_COMMAND, so that
+ * destroy_dev() can return.
+ */
+ cuse_global_lock();
+ TAILQ_FOREACH(pcs, &cuse_server_head, entry) {
+ cuse_server_lock(pcs);
+ cuse_server_is_closing(pcs);
+ cv_broadcast(&pcs->cv);
+ cuse_server_unlock(pcs);
+ }
+ cuse_global_unlock();
+
+ /* destroy_dev() runs the cdevpriv destructor of every open instance. */
+ if (cuse_dev != NULL)
+ destroy_dev(cuse_dev);
+
+ MPASS(TAILQ_EMPTY(&cuse_server_head));
+
+ mtx_destroy(&cuse_global_mtx);
+}
+
static int
cuse_modevent(module_t mod, int type, void *data)
{

File Metadata

Mime Type
text/plain
Expires
Sat, Sep 26, 7:58 PM (5 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39663070
Default Alt Text
D60022.diff (2 KB)

Event Timeline