[PATCH] fuse: Fix the condition to enable over-io-uring

Bernd Schubert via B4 Relay <[email protected]>
Newsgroups dev.linux.lists.fuse-devel,org.kernel.feeds.b4-sent
Message-ID <[email protected]>
From: Bernd Schubert <[email protected]>

I had accidentally used "&&" instead of "||" and totally broken
the intention of the condition. This has several implications

1) fuse-servers can bypass the module option "enable_uring"
   by setting FUSE_OVER_IO_URING in the FUSE_INIT reply, although
   fuse-client/kernel wouldn't have announced availability of
   that flag. I.e.

2) fuse-servers do not need to set FUSE_OVER_IO_URING in FUSE_INIT
   reply and could just send FUSE_IO_URING_CMD_REGISTER at
   any time while IO is already going on. That has further
   implications:

    2.1) The barrier in fuse_block_alloc() waiting for fuse_uring_ready()
         is then bypassed - fuse requests are not blocked until queues
         are initialized - results in dynamic switching from /dev/fuse
         to io-uring.

    2.2) The dynamic switching from /dev/fuse to io-uring exposes
         at least one easily exposable lock order issue between
         fch->bg_lock and queue->lock. There might more issues, as
         dynamic run time switching was never tested.

The change itself is simple, 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 that.
Qemu patches for fuse-io-uring are not merged yet, as far as I know.

Also moved up is the check for fch->initialized 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 explain 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, although slightly modified then
to prevent bypassing of the module option.

Signed-off-by: Bernd Schubert <[email protected]>
---
 fs/fuse/dev_uring.c | 16 ++++++++--------
 fs/fuse/inode.c     |  4 ----
 2 files changed, 8 insertions(+), 12 deletions(-)

diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c
index 77c8cec43d9c..eba322f79df1 100644
--- a/fs/fuse/dev_uring.c
+++ b/fs/fuse/dev_uring.c
@@ -1237,8 +1237,15 @@ int fuse_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
 	}
 	fch = fud->chan;
 
+	/*
+	 * fuse_uring_register() needs the ring to be initialized,
+	 * we need to know the max payload size
+	 */
+	if (!fch->initialized)
+		return -EAGAIN;
+
 	/* Once a connection has io-uring enabled on it, it can't be disabled */
-	if (!enable_uring && !fch->io_uring) {
+	if (!enable_uring || !fch->io_uring) {
 		pr_info_ratelimited("fuse-io-uring is disabled\n");
 		return -EOPNOTSUPP;
 	}
@@ -1248,13 +1255,6 @@ int fuse_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
 	if (!fch->connected)
 		return -ENOTCONN;
 
-	/*
-	 * fuse_uring_register() needs the ring to be initialized,
-	 * we need to know the max payload size
-	 */
-	if (!fch->initialized)
-		return -EAGAIN;
-
 	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 d975073c6029..f29bd7432fa3 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -1474,10 +1474,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;
 

---
base-commit: 818bebeb63dd6bf5f4e07e145f6cdbace520a34c
change-id: 20260821-fuse-fix-enable-condition-df87aa4c25c8

Best regards,
--  
Bernd Schubert <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.