Fix for deadlock situation in cuse(3)
The final server unref should be done by the server thread to prevent deadlock in the client cdevpriv destructor, which cannot destroy itself. MFC after: 1 week Sponsored by: Mellanox Technologies
This commit is contained in:
parent
019c8c9330
commit
c7ffaed92e
@ -699,12 +699,38 @@ cuse_server_unref(struct cuse_server *pcs)
|
||||
free(pcs, M_CUSE);
|
||||
}
|
||||
|
||||
static int
|
||||
cuse_server_do_close(struct cuse_server *pcs)
|
||||
{
|
||||
int retval;
|
||||
|
||||
cuse_lock();
|
||||
cuse_server_is_closing(pcs);
|
||||
/* final client wakeup, if any */
|
||||
cuse_server_wakeup_all_client_locked(pcs);
|
||||
|
||||
knlist_clear(&pcs->selinfo.si_note, 1);
|
||||
|
||||
retval = pcs->refs;
|
||||
cuse_unlock();
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
||||
static void
|
||||
cuse_server_free(void *arg)
|
||||
{
|
||||
struct cuse_server *pcs = arg;
|
||||
|
||||
/* drop refcount */
|
||||
/*
|
||||
* The final server unref should be done by the server thread
|
||||
* to prevent deadlock in the client cdevpriv destructor,
|
||||
* which cannot destroy itself.
|
||||
*/
|
||||
while (cuse_server_do_close(pcs) != 1)
|
||||
pause("W", hz);
|
||||
|
||||
/* drop final refcount */
|
||||
cuse_server_unref(pcs);
|
||||
}
|
||||
|
||||
@ -746,21 +772,10 @@ static int
|
||||
cuse_server_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
|
||||
{
|
||||
struct cuse_server *pcs;
|
||||
int error;
|
||||
|
||||
error = cuse_server_get(&pcs);
|
||||
if (error != 0)
|
||||
goto done;
|
||||
if (cuse_server_get(&pcs) == 0)
|
||||
cuse_server_do_close(pcs);
|
||||
|
||||
cuse_lock();
|
||||
cuse_server_is_closing(pcs);
|
||||
/* final client wakeup, if any */
|
||||
cuse_server_wakeup_all_client_locked(pcs);
|
||||
|
||||
knlist_clear(&pcs->selinfo.si_note, 1);
|
||||
cuse_unlock();
|
||||
|
||||
done:
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user