summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorBernd Schubert <bernd@bsbernd.com>2026-08-21 18:19:09 +0200
committerMiklos Szeredi <mszeredi@redhat.com>2026-08-24 12:18:02 +0200
commit1f59015e958174e89be58cc8db16d70a60d17255 (patch)
tree481b8d71e3f220e1880bdac6b41d86be5c251623 /fs
parent26d7e1f5c407b5859122b5cd47d7ebbf4b4c1cd2 (diff)
fuse: Fix the condition to enable over-io-uring
The existing condition in fuse_uring_cmd() is there only to avoid disabling io-uring for connections that already run with it, missing was a condition to refuse any IORING_OP_URING_CMD if the connection/channel didn't get enabled because of missing FUSE_INIT reply flag FUSE_OVER_IO_URING. Without the reply flag the barrier in fuse_uring_ready() doesn't work and IO could already be going on and cause deadlock states (at a minimum one between fch->bg_lock and queue->lock). The change itself is trivial, but brings behavior change, FUSE_OVER_IO_URING has to be set in the FUSE_INIT_REPLY by fuse servers to accept any IORING_OP_URING_CMD. Libfuse does that and the only non-libfuse implementation I found (fractal-fuse) also does it. Qemu patches for fuse-io-uring are not merged yet, as far as I know. Moved up is the smp_load_acquire(&fch->initialized) check, as a fuse-server implementation might try to setup io-uring before FUSE_INIT is processed and might have gotten -EOPNOTSUPP instead of -EAGAIN. Also fixed is a stale comment that explains the handling of the FUSE_OVER_IO_URING flag in early RFC versions. If there should be a report from any library or application we probably need to revert this commit. Fixes: 3393ff964e0f ("fuse: block request allocation until io-uring init is complete") Signed-off-by: Bernd Schubert <bernd@bsbernd.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/fuse/dev_uring.c31
-rw-r--r--fs/fuse/inode.c4
2 files changed, 18 insertions, 17 deletions
diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c
index e22a48c9a678..c6dd420c4034 100644
--- a/fs/fuse/dev_uring.c
+++ b/fs/fuse/dev_uring.c
@@ -1665,26 +1665,31 @@ int fuse_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
}
fch = fud->chan;
- /* Once a connection has io-uring enabled on it, it can't be disabled */
- if (!enable_uring && !fch->io_uring) {
- pr_info_ratelimited("fuse-io-uring is disabled\n");
- return -EOPNOTSUPP;
- }
-
- if (fch->abort_with_err)
- return -ECONNABORTED;
- if (!fch->connected)
- return -ENOTCONN;
-
/*
- * fuse_uring_register() needs the ring to be initialized,
- * we need to know the max payload size
+ * The ring is sized from values negotiated by FUSE_INIT
*
* Pairs with smp_store_release() in fuse_chan_set_initialized()
*/
if (!smp_load_acquire(&fch->initialized))
return -EAGAIN;
+ if (fch->abort_with_err)
+ return -ECONNABORTED;
+ if (!fch->connected)
+ return -ENOTCONN;
+
+ /* Once a connection has io-uring enabled on it, it can't be disabled */
+ if (!enable_uring && !fch->io_uring) {
+ pr_info_ratelimited("fuse-io-uring is disabled by module parameter\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (!fch->io_uring) {
+ pr_info_ratelimited(
+ "fuse-io-uring not enabled on this connection\n");
+ return -EOPNOTSUPP;
+ }
+
switch (cmd_op) {
case FUSE_IO_URING_CMD_REGISTER:
err = fuse_uring_register(cmd, issue_flags, fch);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 1c6ee01c6796..e9552be3637b 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -1480,10 +1480,6 @@ static struct fuse_init_args *fuse_new_init(struct fuse_mount *fm)
if (IS_ENABLED(CONFIG_FUSE_PASSTHROUGH))
flags |= FUSE_PASSTHROUGH;
- /*
- * This is just an information flag for fuse server. No need to check
- * the reply - server is either sending IORING_OP_URING_CMD or not.
- */
if (fuse_uring_enabled())
flags |= FUSE_OVER_IO_URING | FUSE_HAS_IO_URING_BUFPOOL;