diff options
| author | Bernd Schubert <bernd@bsbernd.com> | 2026-08-21 18:19:09 +0200 |
|---|---|---|
| committer | Miklos Szeredi <mszeredi@redhat.com> | 2026-08-24 12:18:02 +0200 |
| commit | 1f59015e958174e89be58cc8db16d70a60d17255 (patch) | |
| tree | 481b8d71e3f220e1880bdac6b41d86be5c251623 | |
| parent | 26d7e1f5c407b5859122b5cd47d7ebbf4b4c1cd2 (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>
| -rw-r--r-- | fs/fuse/dev_uring.c | 31 | ||||
| -rw-r--r-- | fs/fuse/inode.c | 4 |
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; |
