[PATCH v4 0/3] fs: drain in-flight DIO before buffered write fallback
From: Jiale Yao
Date: Sat Oct 03 2026 - 05:32:08 EST
An asynchronous direct write can remain in flight after its submitting
thread releases the inode lock. If a buffered write dirties page cache
in the meantime, the direct write can complete post-I/O invalidation after
the pages become dirty. The invalidation then reports a page cache
invalidation failure and records -EIO in the mapping error sequence. A
later fsync() returns -EIO.
Commit 15cdefd0c0522f9d5e12d947fa04f4c11649b699 ("ext4: drain
in-flight DIO before buffered write fallback") fixed this race in ext4.
The same ordering is missing from the buffered fallback paths in ext2,
NTFS, and exFAT, and from the regular buffered-write and valid-size
extension paths in exFAT.
This series adds inode_dio_wait() before these paths dirty page cache.
Each patch fixes one filesystem and remains independently buildable. The
NTFS patch also avoids entering the blocking fallback for IOCB_NOWAIT
requests: it returns -EAGAIN if DIO made no progress and preserves a
positive result after a partial direct write.
A reproducer using concurrent AIO direct writes and buffered fallback
triggered the following warning on all three filesystems and made a
subsequent fsync() return -EIO:
Page cache invalidation failure on direct I/O. Possible data corruption
due to collision with buffered I/O!
Changes in v4:
- Add inode_dio_wait() to exfat_extend_valid_size(), as requested by
Chi Zhiling.
Changes in v3:
- Add inode_dio_wait() to both the regular and fallback buffered-write
paths in exFAT, and move the explanatory comment to
exfat_file_write_iter(), as requested by Chi Zhiling.
- Add Baolin Liu's Reviewed-by tag to the NTFS patch.
Changes in v2:
- Handle IOCB_NOWAIT before the potentially blocking NTFS fallback,
returning -EAGAIN before any bytes are written and preserving a positive
short-write result otherwise, as requested in review.
Jiale Yao (3):
ext2: drain in-flight DIO before buffered write fallback
ntfs: drain in-flight DIO before buffered write fallback
exfat: drain in-flight DIO before buffered writes
fs/exfat/file.c | 14 ++++++++++++--
fs/ext2/file.c | 7 +++++++
fs/ntfs/file.c | 13 +++++++++++++
3 files changed, 32 insertions(+), 2 deletions(-)
--
2.34.1