Date: Tue, 25 Jun 2019 11:42:54 +0000 (UTC) From: Hans Petter Selasky <hselasky@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r349367 - head/sys/fs/cuse Message-ID: <201906251142.x5PBgsdC035282@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: hselasky Date: Tue Jun 25 11:42:53 2019 New Revision: 349367 URL: https://svnweb.freebsd.org/changeset/base/349367 Log: 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 Modified: head/sys/fs/cuse/cuse.c Modified: head/sys/fs/cuse/cuse.c ============================================================================== --- head/sys/fs/cuse/cuse.c Tue Jun 25 11:40:37 2019 (r349366) +++ head/sys/fs/cuse/cuse.c Tue Jun 25 11:42:53 2019 (r349367) @@ -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); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201906251142.x5PBgsdC035282>