[PATCH v7 0/4] fuse: compound commands

From: Horst Birthelmer

Date: Thu Jun 04 2026 - 05:57:01 EST


This series adds a single new opcode, FUSE_COMPOUND, that bundles a
sequence of subrequests into one round trip. The wire format is

fuse_in_header (opcode FUSE_COMPOUND)
fuse_compound_in
fuse_compound_req_in
fuse_in_header
payload
... (repeated per subop)

Compound is opt-in per connection and discovered by trial: the kernel
assumes support and clears its flag on the first -ENOSYS reply.
-EOPNOTSUPP declines a specific combination without disabling the
feature. In both cases the kernel replays the subops individually
via fuse_simple_request(), so callers never need a separate
non-compound code path.

The series ships two consumers:

- open + getattr, used when fuse_file_open() needs both ff->fh and
fresh attrs (O_APPEND, or cached attrs already stale). This
closes the open-then-stat race described in [1].
- dentry revalidate, fusing LOOKUP + GETATTR when both the entry
and the attribute caches are stale.

The matching libfuse pull request is here [2]. It contains a helper
that decodes a compound and runs each subop in turn, plus a
passthrough_hp patch demonstrating both that path and the
alternative of handling the compound entirely server-side.

Compounds were reccently discussed more of a thing for fusex
but I think we should add them to the 'classic' FUSE as well,
and as long as fusex hasn't landed and the full fuse channels
are not here, we could add these here.

[1] https://lore.kernel.org/all/20240813212149.1909627-1-joannelkoong@xxxxxxxxx/
[2] https://github.com/libfuse/libfuse/pull/1418

Signed-off-by: Horst Birthelmer <hbirthelmer@xxxxxxx>
---
Changes in v7:
- simplify fuse_open_args_fill() handling
- share result handling between the open+getattr compound and the old code
- send open+getattr only when the attributes we have are expired
or we have open flag O_APPEND
- remove fuse_compound_alloc()/fuse_compound_free()
- add small header for every request in a compound to send compound flags
to fuse server
- Link to v6: https://lore.kernel.org/r/20260226-fuse-compounds-upstream-v6-0-8585c5fcd2fc@xxxxxxx

Changes in v6:
- got rid of the count in the compound header
- added the automatic calling of the combined request if the fuse
server doesn't process the compound and the implementation allows it
- due to the variable max operations in the compounds request struct
fuse_compound_free() had be brought back
- Link to v5: https://lore.kernel.org/r/20260210-fuse-compounds-upstream-v5-0-ea0585f62daa@xxxxxxx

Changes in v5:
- introduced the flag FUSE_COMPOUND_SEPARABLE as discussed here
- simplify result parsing and streamline the code
- simplify the result and error handling for open+getattr
- fixed a couple of issues pointed out by Joanne
- Link to v4: https://lore.kernel.org/r/20260109-fuse-compounds-upstream-v4-0-0d3b82a4666f@xxxxxxx

Changes in v4:
- removed RFC
- removed the unnecessary 'parsed' variable in fuse_compound_req, since
we parse the result only once
- reordered the patches about the helper functions to fill in the fuse
args for open and getattr calls
- Link to v3: https://lore.kernel.org/r/20260108-fuse-compounds-upstream-v3-0-8dc91ebf3740@xxxxxxx

Changes in v3:
- simplified the data handling for compound commands
- remove the validating functionality, since it was only a helper for
development
- remove fuse_compound_request() and use fuse_simple_request()
- add helper functions for creating args for open and attr
- use the newly createn helper functions for arg creation for open and
getattr
- Link to v2: https://lore.kernel.org/r/20251223-fuse-compounds-upstream-v2-0-0f7b4451c85e@xxxxxxx

Changes in v2:
- fixed issues with error handling in the compounds as well as in the
open+getattr
- Link to v1: https://lore.kernel.org/r/20251223-fuse-compounds-upstream-v1-0-7bade663947b@xxxxxxx

---
Horst Birthelmer (4):
fuse: add compound command to combine multiple requests
fuse: create helper functions for filling in fuse args for open and getattr
fuse: add an implementation of open+getattr
fuse: add compound command for dentry revalidation

fs/fuse/Makefile | 2 +-
fs/fuse/compound.c | 126 ++++++++++++++++++++++++++++
fs/fuse/dev.c | 206 +++++++++++++++++++++++++++++++++++++++++++---
fs/fuse/dev_uring.c | 31 ++++++-
fs/fuse/dir.c | 139 ++++++++++++++++++++++++++++---
fs/fuse/file.c | 115 +++++++++++++++++++++-----
fs/fuse/fuse_dev_i.h | 5 ++
fs/fuse/fuse_i.h | 39 +++++++++
fs/fuse/inode.c | 9 ++
fs/fuse/ioctl.c | 2 +-
include/uapi/linux/fuse.h | 56 +++++++++++++
11 files changed, 685 insertions(+), 45 deletions(-)
---
base-commit: e43ffb69e0438cddd72aaa30898b4dc446f664f8
change-id: 20251223-fuse-compounds-upstream-c85b4e39b3d3

Best regards,
--
Horst Birthelmer <hbirthelmer@xxxxxxx>