Skip to content

fuse: fence cached reads against NOTIFY invalidate with a percpu gate#189

Open
hbirth wants to merge 1 commit into
DDNStorage:redfs-ubuntu-hwe-6.17.0-16.16-24.04.1from
hbirth:redfs-ubuntu-hwe-6.17.0-16.16-24.04.1
Open

fuse: fence cached reads against NOTIFY invalidate with a percpu gate#189
hbirth wants to merge 1 commit into
DDNStorage:redfs-ubuntu-hwe-6.17.0-16.16-24.04.1from
hbirth:redfs-ubuntu-hwe-6.17.0-16.16-24.04.1

Conversation

@hbirth

@hbirth hbirth commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

A FUSE_NOTIFY_INVAL_INODE is a coherency event: once the server signals a remote modify, no local read may return a page it has superseded. The invalidate ran unserialized against cache-serving reads, so a buffered read could hand back a stale folio it still held a reference to.

Convert the per-inode wb_inval_rwsem to a percpu_rw_semaphore and take its read side around the cache-serving read as well as the existing buffered write. The read side is per-CPU, so it scales on a shared file; the NOTIFY takes the write side blocking, giving the invalidate priority -- it parks new readers, drains in-flight ones, then drops the cache. Every gated invalidate now runs under the write side, not just the storm-latching one.

The gate is allocated only for writeback+dlm regular files and is NULL elsewhere (best-effort invalidate, as before). The blocking write side may run on the notify-delivering server thread, so it is safe only under a server that services request replies on other threads; redfs' dlm server provides that contract.

A FUSE_NOTIFY_INVAL_INODE is a coherency event: once the server signals a
remote modify, no local read may return a page it has superseded.  The
invalidate ran unserialized against cache-serving reads, so a buffered read
could hand back a stale folio it still held a reference to.

Convert the per-inode wb_inval_rwsem to a percpu_rw_semaphore and take its
read side around the cache-serving read as well as the existing buffered
write.  The read side is per-CPU, so it scales on a shared file; the NOTIFY
takes the write side blocking, giving the invalidate priority -- it parks
new readers, drains in-flight ones, then drops the cache.  Every gated
invalidate now runs under the write side, not just the storm-latching one.

The gate is allocated only for writeback+dlm regular files and is NULL
elsewhere (best-effort invalidate, as before).  The blocking write side may
run on the notify-delivering server thread, so it is safe only under a
server that services request replies on other threads; redfs' dlm server
provides that contract.

Signed-off-by: Horst Birthelmer <hbirthelmer@ddn.com>
Comment thread fs/fuse/inode.c
Comment thread fs/fuse/file.c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants