Skip to content

Linux 6.8: backport mmap changes - #261

Merged
hbirth merged 6 commits into
DDNStorage:redfs-ubuntu-noble-6.8.0-58.60from
hbirth:redfs-ubuntu-noble-6.8.0-58.60
Oct 16, 2026
Merged

hbirth merged 6 commits into
DDNStorage:redfs-ubuntu-noble-6.8.0-58.60from
hbirth:redfs-ubuntu-noble-6.8.0-58.60

Conversation

@hbirth

@hbirth hbirth commented Oct 14, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

hbirth and others added 6 commits October 7, 2026 14:11
Under DLM the server's time stamps are authoritative, fuse_get_cache_mask()
returns 0 and the reply overwrites whatever fuse_do_setattr() set locally.
Do not claim the local stamps in the request either: send FATTR_MTIME_NOW
for truncate(2) and utimes(UTIME_NOW), and no mtime for ftruncate(2) and
no ctime at all, as without the writeback cache.

Signed-off-by: Horst Birthelmer <hbirthelmer@ddn.com>
A page fault filled the page cache without a grant, so a remote write
never invalidated the page.  Ask for the grant before filemap_fault()
runs, a write grant when the mapping is shared and writable.  The
page_mkwrite request stays for the writethrough case only.

The fault must not block under mmap_lock: the read and write paths
hold the coherency gate while faulting in their user buffers, which
takes mmap_lock, so a fault blocking on the gate or the server with a
pending mmap_lock writer queued deadlocks three ways.  A fast path
maps a resident page off a recorded grant under a gate trylock.
Otherwise the fault lock is dropped, the grant is taken and the pages
are read into private folios and installed under the gate, and the
fault is retried.  Only a fault that allows no retry blocks in place.

Grant and read cover a 16-page window centred on the faulted page, so
the neighbour of a spanning access maps without a server round trip
whose revoke would drop the page just mapped.  A resident page that is
not uptodate is filled from the private read under a trylock, or the
install would -EEXIST against it on every pass.

Port of deb9a15, bf37dc5, 9cdd0ba and 26d2a04 from
redfs-rhel10_0 (Linux 6.12).  That branch fences the fault with the IO
range lock; this one has the per-inode gate (fi->wb_inval_rwsem), under
whose write side a revoke drops both the grant record and the pages, so
a grant seen under the read side holds for the whole hold.

Signed-off-by: Horst Birthelmer <hbirthelmer@ddn.com>
With the writeback cache on, page_mkwrite skipped the DLM lock request,
assuming fuse_filemap_fault() had taken a write grant for any page a
shared-writable mapping could dirty.  Fault-around (filemap_map_pages)
PTE-maps any resident folio in its window without calling ->fault, so a
folio read in under a READ grant takes its first write fault with no
WRITE grant ever requested, and writeback sends a WRITE the server sees
under a read lock.

page_mkwrite cannot take the grant itself: it runs with mmap_lock (or
the per-VMA lock) held and has no VM_FAULT_RETRY protocol to drop it,
while the buffered IO paths hold the coherency gate while faulting in
their user buffers.

Give shared-writable VMAs under the writeback cache with DLM a
vm_operations_struct without ->map_pages, so the first touch of every
page goes through fuse_filemap_fault().  page_mkwrite keeps a
non-blocking check of the recorded grant under a gate trylock and
returns VM_FAULT_NOPAGE on a miss: a verified miss means a revoke or
truncate in flight whose page drop clears the PTE, and a contended
trylock re-faults with mmap_lock released in between.

Port of 52b0cfb from redfs-rhel10_0 (Linux 6.12); the gate trylock
replaces the range lock trylock.

Reported-by: Hai Zhong Zhou
Suggested-by: Yong Ze Chen
Signed-off-by: Allison Henderson <allison.henderson@ddn.com>
Signed-off-by: Horst Birthelmer <hbirthelmer@ddn.com>
With the writeback cache and DLM, fuse_filemap_fault()'s slow path
drops the fault lock, takes the DLM grant and reads the batch window
into private folios, and returns VM_FAULT_RETRY.  Errors on that path
cannot be reported: once the fault lock is dropped, VM_FAULT_RETRY is
the only answer the fault can give, and a retried fault that keeps
failing comes straight back.

An aborted connection fails every request, so a task touching a
non-resident page of a mapping on that mount refaults forever.  It
spends all its time in the kernel, ignores every signal but SIGKILL,
and its mapping keeps the mount busy, so the mount cannot be unmounted
and recovered.

Check the connection on the slow path while the fault lock is still
held, and return VM_FAULT_SIGBUS when it is gone, which is what a
fault on a non-resident page of an aborted mount returns without DLM.
Resident pages with a recorded grant still map through the fast path.

A persistent error on a live connection still loops the same way.

Port of ae0e8f9 from redfs-rhel10_0 (Linux 6.12); the hunk is
identical.

Signed-off-by: Sven Oehme <soehme@ddn.com>
Signed-off-by: Horst Birthelmer <hbirthelmer@ddn.com>
Nothing held under the coherency gate may wait for the server, but the
cached read path could: generic_file_read_iter() faults on the user
buffer during copy-out, and a buffer backed by a shared-writable
mapping of a fuse file sends fuse_filemap_fault() after a WRITE grant.
Granting that can first require the server to revoke the reading
node's own READ grant, and the revoke's invalidation waits on the gate
the reader holds: an ABBA with the server in the middle.  A pread()
into a shared-writable mapping of the same byte range reproduces it,
and the victim sits in request_wait_answer(), which no longer dies to
SIGKILL once the request has reached userspace.

Copy with page faults disabled instead, so a non-resident user page
makes the copy come back short rather than fault, then drop the gate,
fault the buffer in, re-cover the grant (it may have been revoked
while the gate was dropped), re-enter and resume.  The re-entry
re-validates the grant and the forced-DIO latch as the first pass
does.  Same shape as gfs2_file_read_iter() around its glock.

The write path is not changed: its WRITE grant covers the IO range, so
a fault on a source buffer overlapping the destination finds the grant
recorded.  A source buffer backed by a different, ungranted fuse range
can still hit the same ABBA through generic_perform_write()'s fault-in
and is left for a follow-up.

Port of b7bc973 from redfs-rhel10_0 (Linux 6.12); the gate drop
and re-entry replace the range lock INIT and LOCKED transitions.

Signed-off-by: Allison Henderson <allison.henderson@ddn.com>
Signed-off-by: Horst Birthelmer <hbirthelmer@ddn.com>
SPECsfs warmup reads on a write-back fuse mount returned EFAULT from
fuse_cache_read_iter().  The copy runs with page faults disabled, then
faults the user buffer in with the gate dropped.  The loop gives up the
first time a pass copies nothing, so one large fault-in that does not
stick becomes EFAULT.  Netmist reported that as platform error 14.

gfs2's should_fault_in_pages() drops to a single page when a pass
makes no progress.  Its buffered read retries for as long as fault-in
faults a byte, which spins if the page is already resident and the
copy still returns -EFAULT.  Stop after one single-page retry and warn.

Port of 1faf584 from redfs-rhel10_0 (Linux 6.12), itself a pick of
44fdde8 from redfs-ubuntu-hwe-6.17.0-16.16-24.04.1.

Signed-off-by: Sven Oehme <soehme@ddn.com>
Signed-off-by: Horst Birthelmer <hbirthelmer@ddn.com>
@hbirth

hbirth commented Oct 14, 2026

Copy link
Copy Markdown
Collaborator Author

This actually passes xfstests with the same failures the previous version did, so no observable change in correctness

@hbirth
hbirth merged commit d6e06ab into DDNStorage:redfs-ubuntu-noble-6.8.0-58.60 Oct 16, 2026
2 checks passed
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