Linux: avoid prefaulting under the ZFS range lock - #18872
Conversation
f7d44ba to
61169b0
Compare
|
I'll leave it to somebody with more Linux VM and VFS experience, but I have feeling that pre-faulting everything might be impossible in some extreme cases, when requests are so big, that system simply does not have enough RAM to pull it all in, or it might not have sense to pull it all in. |
61169b0 to
6d0c2ac
Compare
|
Agreed — prefaulting the complete request is not a sound bound. I revised the patch in After the range lock is acquired, both source-copy paths now run with page faults disabled. If a later page is not resident, Linux preserves any completed bytes and returns a short write instead of faulting or retrying under the lock. This avoids pulling an arbitrarily large request into RAM and keeps the range lock held for the bytes actually written, including The revision also makes the Linux |
6d0c2ac to
dc3f120
Compare
zfs_write() prefaults only the first transaction-sized chunk before taking the file range lock. A larger write faults each later chunk while that lock is held. If its source maps the same ZFS file, the fault enters zfs_getpage() and waits forever for the lock held by the writing thread. Keep prefaulting bounded to one transaction-sized chunk and make Linux iterator copies honor uio_fault_disable. Both the normal DMU path and the full-block ARC buffer path now copy without page faults while the range lock is held. If a later source page is not resident, preserve any completed data and report a Linux short write instead of faulting or retrying under the lock. Closes openzfs#18135 Signed-off-by: nexicturbo <turbonexic@gmail.com>
dc3f120 to
54cbbed
Compare
|
CI note: the amended head
The paired VM summaries in those jobs show no unexpected failure. I tried to rerun only the failed jobs, but GitHub requires repository Actions-admin permission. Could someone with that permission rerun the failed jobs? I have not added unrelated code churn solely to retrigger CI. |
|
I've resubmitted the failed CI jobs. We do still have a handful of flaky tests which is what these failures looks like. |
|
The maintainer reruns are complete on exact head |
Motivation and Context
Fixes #18135.
The deterministic reproducer writes 32 MiB + 1 byte from an mmap of the
same ZFS file.
zfs_write()prefaults only the first transaction-sized32 MiB before taking the file range lock. On the next loop iteration it
prefaults the final byte while that lock is still held. The page fault
enters
zfs_getpage()for the same file and waits forever for the rangelock held by the writing thread.
This matches the reported stack and the existing warning in
zfs_write()that prefaulting under the range lock can deadlock throughzfs_getpage().Reproducer:
https://github.com/jfly/2026-07-31-zfs-deadlock/blob/main/mmap_snake.py
Description
MIN(n, DMU_MAX_ACCESS >> 1)before range-lock acquisition.uio_fault_disable, so the normal DMUwrite path cannot fault while holding the range lock.
an incomplete ARC-buffer copy into
EFAULTinstead of asserting.late
EFAULT; Linux reports that progress as a short write.Large requests no longer require every source page to be resident at once.
If a page beyond the bounded prefault window is not resident, the syscall
returns the bytes already written and userspace can retry the remainder.
The range lock is never dropped during the write, including
O_APPEND, soappend atomicity is not weakened.
How Has This Been Tested?
zfs_write()and Linuxiov_itercontrol flow.zfs_uio_prefaultpages()call inzfs_write()and it precedes write range-lock acquisition.zfs_uio_fault_disable()and that the Linux iterator implementation nowenforces that flag with
pagefault_disable()/pagefault_enable().git diff --checksuccessfully.masterplusexact head
54cbbed772fa59221bc9bd118aac43a30acfb8d9; the previouslyhanging reproduction completes:
Linux: avoid prefaulting under the ZFS range lock #18872 (comment)
This host is Windows without WSL or Docker, so I could not build the Linux
kernel module or run ZTS locally. GitHub CI is validating the amended head.
I did not add an automated deadlock regression because the failing case
waits uninterruptibly on the file's own range lock. A userspace timeout
cannot guarantee cleanup and could wedge a bare-metal ZTS host.
Types of Changes
Checklist
Signed-off-by.