On Tue, Aug 18 2026, Amir Goldstein wrote:

> On Mon, Aug 17, 2026 at 4:11 PM Luis Henriques <[email protected]> wrote:
>>
>> This new file aims at documenting the caches that are used by FUSE.  At
>> the moment only symlink, attributes, ACLs and readdir caches are described.
>>
>> Signed-off-by: Luis Henriques <[email protected]>
>> ---
>>  .../filesystems/fuse/fuse-caches.rst          | 142 ++++++++++++++++++
>>  1 file changed, 142 insertions(+)
>>  create mode 100644 Documentation/filesystems/fuse/fuse-caches.rst
>>
>> diff --git a/Documentation/filesystems/fuse/fuse-caches.rst 
>> b/Documentation/filesystems/fuse/fuse-caches.rst
>> new file mode 100644
>> index 000000000000..071febf45d00
>> --- /dev/null
>> +++ b/Documentation/filesystems/fuse/fuse-caches.rst
>> @@ -0,0 +1,142 @@
>> +.. SPDX-License-Identifier: GPL-2.0
>> +
>> +===========
>> +FUSE Caches
>> +===========
>> +
>> +Introduction
>> +============
>> +
>> +This document summarises the different types of caches that are used in 
>> FUSE.
>> +For each cache type, it attempts to document the rules that are followed to
>> +insert, validate and invalidate data into the cache.
>> +
>> +symlink caching
>> +===============
>> +
>> +Whenever there's a link resolution request, the VFS will call into
>> +``fuse_get_link()`` which will then send a ``FUSE_READLINK`` request to the
>> +user-space FUSE server. However, the server can ask the kernel to cache all
>> +links resolutions by setting the ``FUSE_CACHE_SYMLINKS`` flag during the
>> +``FUSE_INIT`` negotiation.
>> +
>> +If this flag is set, FUSE will immediately call into the VFS
>> +``__page_get_link()`` from the ``->get_link()`` inode operation. The first 
>> time
>> +this is done for a specific link, it will end-up sending the 
>> ``FUSE_READLINK``
>> +to user-space but the link contents will then be added into page-cache. The 
>> next
>> +time the link needs to be resolved, it will use the link content that is 
>> already
>> +cached, and will only fallback into sending the request to use-space if the
>> +folio isn't up-to-date.
>> +
>> +Attributes caching
>> +==================
>> +
>> +Attributes obtained from user-space, for example when an inode is first
>> +looked-up, are cached in the kernel. However, these attributes have a 
>> timeout
>> +associated and once expired they are invalidated.
>> +
>> +Thus, the ``FUSE_GETATTR`` operation will be sent to user-space only if the
>> +attributes aren't yet available, the attributes aren't valid (timeout), or 
>> if
>> +there is an explicit request for doing so (for example, by using the
>> +``AT_STATX_FORCE_SYNC`` flag in ``statx``). This may happen in the following
>> +situations:
>
> "This may happen" what may happen? I don't see it referring to anything.

Yeah, that sentence doesn't really make a lot of sense.  I'll rephrase.

>> +
>> +#. An explicit request from VFS to get the attributes for an inode (through 
>> the
>> +   ``->getattr()`` callback).
>> +#. When an ``->llseek()`` is requested to FUSE with a type of request
>> +   (``whence``):
>> +
>> +   -  ``SEEK_{HOLE,DATA}`` and the user-space doesn't implement the
>> +      ``FUSE_LSEEK`` operation (it has returned ``ENOSYS``), or
>> +   -  ``SEEK_END``
>> +
>> +#. When doing a buffered read past EOF or automatic page cache invalidation 
>> mode
>> +   is enabled (``FUSE_AUTO_INVAL_DATA``).
>> +#. When doing a buffered write with write-back cache enabled
>> +   (``FUSE_CAP_WRITEBACK_CACHE``).
>
> This list is incomplete and strange. it has post EOF write for
> writeback which is the exception
> and leaves out every non writeback write.

This list was meant to list the scenarios where the FUSE_GETATTR is sent
(the "this may happen" above).  But I'll review the list again.

> If you composed this list yourself I highly recommend an LLM for this task
> if you used LLM I suggest a stronger model.
>
> Generally speaking, I find that today's robots are much better at writing 
> these
> sorts of docs than I am - as long as I sit at the helm and guide them
> about where to expand on and where to keep it concise.

Thank you for the suggestion (I did not use an LLM btw).  In fact, do you
think this document is really useful, given that everyone will be running
an LLM anyway?  (I've been asking this question myself...)

>> +
>> +ACL caching
>> +===========
>> +
>> +FUSE has allowed the usage of POSIX ACLs for a long time as they could be 
>> set
>> +and accessed simply as extended attributes. However, it was only with the
>> +addition of the ``FUSE_POSIX_ACL`` flag that ACLs started to be fully 
>> supported.
>> +Without this flag, ACLs can still be set, but the VFS won't use them for
>> +performing permission checks - that would be the user-space server's
>> +responsibility.
>> +
>> +Also, without setting ``FUSE_POSIX_ACL``, ACLs will not be cached by the 
>> kernel.
>> +In this case, new inodes ``i_acl`` and ``i_default_acl`` fields will be set 
>> to
>> +``ACL_DONT_CACHE``.
>> +
>> +On the other hand, if ``FUSE_POSIX_ACL`` is set during ``FUSE_INIT``, when 
>> an
>> +ACL is accessed the VFS layer will first check if it's already cached. If 
>> it is
>> +not, FUSE ``->get_acl`` operation is called, which will eventually send a
>> +user-space request. Future accesses to this inode ACL will then use the 
>> cached
>> +data.
>> +
>> +Setting an ACL in an inode, however, won't cache it immediately. It will 
>> send
>> +user-space a request with the new ACL, and the FUSE server may perform some
>> +modifications before storing it.
>
> Do not encourage this by documenting it please.
> It reinforces that this was by design, rather than an oversight which
> we don't know.

Eh! OK, I'll stop that sentence after the comma :-)

>> +
>> +On the other hand, ACLs will be removed for the cache in the following
>> +situations:
>> +
>> +-  When setting an ACL in an inode and the user-space server has set the
>> +   ``FUSE_POSIX_ACL`` flag, all previously cached ACLs for this inode will 
>> be
>> +   invalidated.
>> +-  When invalidating an inode through the ``FUSE_NOTIFY_INVAL_INODE`` 
>> operation.
>> +-  When ``->d_revalidate()`` is called for a dentry that requires a lookup 
>> (e.g.
>> +   it has expired) and that lookup operation is successful.
>> +-  When the VFS needs to check access rights for an inode (by calling
>> +   ``->permission()``), attributes may need to be refreshed. If that 
>> happens,
>> +   any cached ACLs for that inode will be invalidated.
>> +-  After setting an inode attribute (i.e. operation ``FUSE_SETATTR`` is 
>> sent to
>> +   user-space), the user-space server may have also updated the ACLs, so any
>> +   cached ACLs for this inode are also invalidated.
>> +-  While processing ``FUSE_READDIRPLUS`` and a new dentry is added (unless 
>> this
>> +   dentry is already being looked up (``DCACHE_PAR_LOOKUP``))
>> +-  In general, when there is the need to sent a ``FUSE_STATX`` or
>> +   ``FUSE_GETATTR`` to user-space (e.g. because the attributes have 
>> expired).
>> +   This may happen in the following cases:
>> +
>> +   -  When doing an ``->llseek()`` on a file with ``SEEK_END``, 
>> ``SEEK_HOLE`` or
>> +      ``SEEK_DATA``.
>> +   -  When the ``FUSE_AUTO_INVAL_DATA`` flag is set at ``INIT`` time (to
>> +      automatically invalidate cached pages), and a buffered read
>> +      (``->read_iter()``) past EOF is done on a non-passthrough file.
>> +   -  When the ``FUSE_WRITEBACK_CACHE`` flag is set at ``INIT`` time, and a
>> +      buffered write (``->write_iter()``) past EOF is done on a 
>> non-passthrough
>> +      file.
>> +   -  When the ``FUSE_AUTO_INVAL_DATA`` flag is set at ``INIT`` time and 
>> the VFS
>> +      needs to read a directory contents (``->iterate_shared()``) for a
>> +      directory that is allowed to be cached.
>
> No reason to repeat the reasons for attr cache invalidation that were
> just listed above
>
>> +
>> +readdir caching
>> +===============
>> +
>> +When opening a directory for doing a readdir, a ``FUSE_OPENDIR`` will be 
>> sent
>> +and the user-space server will be responsible for setting the open flags 
>> related
>> +with caching, namely ``FOPEN_KEEP_CACHE`` and ``FOPEN_CACHE_DIR``.
>> +
>> +If neither flags are set by the user-space FUSE server, then every 
>> ``readdir``
>> +will result in a ``FUSE_READDIR`` (or ``FUSE_READDIRPLUS``) request being 
>> sent.
>> +If ``FOPEN_CACHE_DIR`` is set by the server, then the result of a 
>> ``readdir``
>> +will be cached by the kernel and reused. However, if ``FOPEN_KEEP_CACHE`` 
>> isn't
>> +also set, the cache will be invalidated next time the directory is open.
>
> Confusing.
> FOPEN_KEEP_CACHE is about keeping the cache on THIS open not on
> some NEXT open.

Right, that's true.  I just wanted to emphasise that the invalidation
doesn't happen on a close, but on the next open.  But I'll rephrase,
thanks.

Cheers,
-- 
Luís

Reply via email to