Re: [PATCH v2 1/2] fuse: add negotiated per-inode open and release suppression

From: Randy Dunlap

Date: Thu Oct 08 2026 - 14:22:01 EST


Hi,

On 10/8/26 11:06 AM, Stanislav Kinsburskii wrote:
> Filesystems serving cached content may not need per-open state for most
> inodes, while still relying on OPEN for control files. The connection-wide
> no-open behavior selected by ENOSYS cannot express this distinction.
>
> Add FUSE_PER_INODE_NO_OPEN to INIT negotiation and FUSE_ATTR_NO_OPEN to
> inode attributes. For marked inodes, use the existing zero-handle defaults
> and normally omit OPEN/OPENDIR and the corresponding RELEASE/RELEASEDIR.
> Remember whether each handle was opened locally, so later attribute updates
> do not determine the release behavior of existing handles.
>
> Retain RELEASE after a successful remote flock operation, even when OPEN
> was skipped, so FUSE_RELEASE_FLOCK_UNLOCK can clean up server-side locks.
> Servers negotiating remote flock must accept this RELEASE with a zero file
> handle and no preceding OPEN, including after an explicit unlock.
>
> Keep the release argument allocation for regular files, which pins the
> inode while asynchronous I/O completes. Honor the hint for internal opens
> used by file-attribute ioctls as well. The capability check excludes CUSE
> before accessing its non-FUSE inode as a fuse_inode.
>
> The per-inode hint does not suppress OPEN for atomic O_TRUNC, since the
> server must perform the truncation. CREATE retains its existing handle
> lifecycle. Connection-wide no-open/no-opendir behavior selected by ENOSYS
> continues to take precedence.
>
> Update the cached hint from LOOKUP, GETATTR, SETATTR and READDIRPLUS
> attributes. Preserve it across STATX replies, which do not carry
> fuse_attr.flags.
>
> Document negotiation, cache and handle semantics, and the server's
> responsibilities. No additional access-time or open-reference accounting
> is introduced.
>
> Signed-off-by: Stanislav Kinsburskii <skinsburskii@xxxxxxxxx>
> ---
> Documentation/filesystems/fuse/fuse-no-open.rst | 49 +++++++++++++++++++++++++
> Documentation/filesystems/fuse/index.rst | 1 +
> fs/fuse/file.c | 26 ++++++++++---
> fs/fuse/fuse_i.h | 17 ++++++++-
> fs/fuse/inode.c | 9 +++++
> fs/fuse/ioctl.c | 3 +-
> include/uapi/linux/fuse.h | 13 ++++++-
> 7 files changed, 110 insertions(+), 8 deletions(-)
>
> diff --git a/Documentation/filesystems/fuse/fuse-no-open.rst b/Documentation/filesystems/fuse/fuse-no-open.rst
> new file mode 100644
> index 000000000000..4526512d358c
> --- /dev/null
> +++ b/Documentation/filesystems/fuse/fuse-no-open.rst
> @@ -0,0 +1,49 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> +Per-inode open suppression
> +=========================

Documentation/filesystems/fuse/fuse-no-open.rst:4: WARNING: Title underline too short.

Per-inode open suppression
========================= [docutils]

> +
> +A filesystem can avoid OPEN and RELEASE requests for individual inodes by
> +negotiating FUSE_PER_INODE_NO_OPEN in INIT and setting FUSE_ATTR_NO_OPEN in
> +``fuse_attr.flags``. For directories, the flag suppresses OPENDIR and
> +RELEASEDIR instead. This allows, for example, cached content files to avoid
> +open round trips while control files on the same connection retain their
> +open handlers. Without the negotiated capability the attribute is ignored.
> +
> +The kernel updates the hint when it accepts attributes in replies such as
> +LOOKUP, GETATTR, SETATTR and READDIRPLUS. STATX replies do not carry
> +``fuse_attr.flags`` and leave the hint unchanged. The hint is cached inode
> +state; it is not independently revalidated on every open. A server changing
> +the hint must arrange for fresh attributes to reach the kernel and tolerate
> +concurrent opens using the previous value.
> +
> +For an open served locally, the file handle is zero, FOPEN_KEEP_CACHE is
> +set, and directories also have FOPEN_CACHE_DIR set. Subsequent requests
> +identify the object by the node ID and may carry a zero file handle. The
> +server must support these requests without per-open state. Whether OPEN was
> +sent is recorded for each handle and is not changed by later attribute
> +updates. An existing server-opened handle still receives its matching
> +RELEASE if the inode hint subsequently becomes set.
> +
> +Remote flock locking is an exception to RELEASE suppression. When
> +FUSE_FLOCK_LOCKS is negotiated and a handle has successfully performed a
> +server-side flock operation, its final close sends RELEASE with
> +FUSE_RELEASE_FLOCK_UNLOCK and the lock owner, even if OPEN was suppressed.
> +The server must accept this RELEASE with a zero file handle and no preceding
> +OPEN, and use the node ID and lock owner to remove any remaining flock locks.
> +This also applies after an explicit unlock, since the kernel records whether
> +a flock operation succeeded rather than tracking the server's current locks.
> +
> +When FUSE_ATOMIC_O_TRUNC is negotiated, an open with O_TRUNC still sends
> +OPEN and receives a matching RELEASE, so the server can perform truncation.
> +CREATE also retains its usual open and release semantics. Connection-wide
> +no-open behavior selected by an ENOSYS response continues to take precedence.
> +
> +The hint does not make an inode immutable, grant permissions, or suppress
> +other operations such as FLUSH, FSYNC, locking or data I/O. Servers supporting
> +remote flock must implement the RELEASE cleanup described above. A server must
> +only set it when its access policy and file semantics permit the default
> +open behavior described above. Servers needing per-open authorization,
> +nonzero handles, direct I/O, passthrough or other OPEN reply flags must keep
> +handling OPEN for those inodes. No additional access-time or open-reference
> +accounting is performed by this feature.


--
~Randy