Re: [PATCH v2 4/7] exfat: drop i_rwsem from exfat_page_mkwrite
From: Chi Zhiling
Date: Wed Oct 14 2026 - 19:30:31 EST
On 10/14/26 4:11 PM, Chi Zhiling wrote:
On 10/14/2026 9:19 AM, Namjae Jeon wrote:
@@ -969,8 +969,9 @@ static vm_fault_t exfat_page_mkwrite(struct vm_fault *vmf)exfat_page_mkwrite() reads the file size before iomap_page_mkwrite()
loff_t new_valid_size, mmap_valid_size, fault_page_start;
bool dirty = false;
- if (!inode_trylock(inode))
- return VM_FAULT_RETRY;
locks the page. Because inode_trylock was removed, another thread can
grow the file in between. exfat_cont_expand() does not take
invalidate_lock, so the shared lock does not stop it.
mmap write fault ftruncate/fallocate
Snapshot i_size = 1000
new_valid_size = 1000
dirty = false
Extend i_size to 3000
valid_size stays 1000
iomap_page_mkwrite() locks folio
Checks the current i_size (3000) and succeeds
dirty is still false, so VDL is not advanced
MM makes the page writable
Store at offset 2000, no new page_mkwrite()
The data at offset 2000 is beyond valid_size, so it can later be read
as zero. Could you check and fix this race?
This is the issue Yuezhang mentioned earlier, and he has already submitted a fix:
https://lore.kernel.org/exfat/20261010101200.1211462-2- Yuezhang.Mo@xxxxxxxx/
I misunderstood. This is a different issue. I’ll fix this bug as soon as possible.
Thanks!
+ sb_start_pagefault(inode->i_sb);
+ file_update_time(vmf->vma->vm_file);
+ filemap_invalidate_lock_shared(inode->i_mapping);
With i_size = 12 KB and valid_size = 0, DIO write to [0, 4 KiB can
race with an mmap write fault at offset 8 KB. The fault zeroes and
dirties the gap [0, 8 KiB), then advances valid_size.
DIO write [0,4 KiB) mmap fault at 8 KiB
Starts writing data
Reads the gap as zero
Dirties pages 0 and 1
Advances valid_size
Completes
Post-DIO invalidation cannot remove
the dirty page
Writeback can overwrite DIO data with zeros
Removing inode_trylock() from exfat_page_mkwrite() can introduce
several racy issues. Could you check that the affected paths are
properly synchronized?
Concurrent DIO and mmap writes are undefined behavior, and other filesystems may have similar issues.
I've spent quite a while thinking about this, but I still don't have a good solution. So I added the following patch to the patch series:
"exfat: publish i_size and valid_size on direct I/O completion".
The purpose of this patch is to prevent stale on-disk data from being exposed when DIO and mmap writes happen concurrently. However, the trade-off is that concurrent DIO writes may have their data unexpectedly zeroed.
Do you have any thoughts on this?
Thanks!