]> www.infradead.org Git - users/hch/misc.git/commitdiff
fuse: fix possible deadlock if rings are never initialized
authorLuis Henriques <luis@igalia.com>
Thu, 6 Mar 2025 11:12:18 +0000 (11:12 +0000)
committerChristian Brauner <brauner@kernel.org>
Wed, 19 Mar 2025 13:00:11 +0000 (14:00 +0100)
When mounting a user-space filesystem using io_uring, the initialization
of the rings is done separately in the server side.  If for some reason
(e.g. a server bug) this step is not performed it will be impossible to
unmount the filesystem if there are already requests waiting.

This issue is easily reproduced with the libfuse passthrough_ll example,
if the queue depth is set to '0' and a request is queued before trying to
unmount the filesystem.  When trying to force the unmount, fuse_abort_conn()
will try to wake up all tasks waiting in fc->blocked_waitq, but because the
rings were never initialized, fuse_uring_ready() will never return 'true'.

Fixes: 3393ff964e0f ("fuse: block request allocation until io-uring init is complete")
Signed-off-by: Luis Henriques <luis@igalia.com>
Link: https://lore.kernel.org/r/20250306111218.13734-1-luis@igalia.com
Acked-by: Miklos Szeredi <mszeredi@redhat.com>
Reviewed-by: Bernd Schubert <bschubert@ddn.com>
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/fuse/dev.c

index 2c3a4d09e500f98232d5d9412a012235af6bec2e..51e31df4c54613280a9c295f530b18e1d461a974 100644 (file)
@@ -77,7 +77,7 @@ void fuse_set_initialized(struct fuse_conn *fc)
 static bool fuse_block_alloc(struct fuse_conn *fc, bool for_background)
 {
        return !fc->initialized || (for_background && fc->blocked) ||
-              (fc->io_uring && !fuse_uring_ready(fc));
+              (fc->io_uring && fc->connected && !fuse_uring_ready(fc));
 }
 
 static void fuse_drop_waiting(struct fuse_conn *fc)