Re: [PATCH 2/2] ntfs: take invalidate_lock in ntfs_filemap_page_mkwrite()

From: Hongling Zeng

Date: Mon Aug 31 2026 - 04:48:53 EST



在 2026年08月31日 15:24, Namjae Jeon 写道:
if (NInoWofCompressed(NTFS_I(inode)))
@@ -684,7 +685,14 @@ static vm_fault_t ntfs_filemap_page_mkwrite(struct vm_fault *vmf)
sb_start_pagefault(inode->i_sb);
file_update_time(vmf->vma->vm_file);

+ /*
+ * Serialize against truncate/fallocate which hold the lock
+ * exclusively while invalidating pagecache and changing extents.
+ */
+ filemap_invalidate_lock_shared(mapping);
ret = iomap_page_mkwrite(vmf, &ntfs_page_mkwrite_iomap_ops, NULL);
+ filemap_invalidate_unlock_shared(mapping);
+
Please move filemap_invalidate_unlock() after truncate_pagecache() and
pagecache_isize_extended(). Otherwise, ntfs_filemap_page_mkwrite() can
race with the page-cache cleanup after fallocate extends the file.

diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index 1969e4f444f7..a266105180a9 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -1178,13 +1178,15 @@ static long ntfs_fallocate(struct file *file,
int mode, loff_t offset, loff_t le

err = file_modified(file);
out:
+ if (!err && mode == 0 && NInoNonResident(ni) &&
+ offset > old_size) {
+ truncate_pagecache(vi, old_size);
+ pagecache_isize_extended(vi, old_size, offset);
+ }
+
filemap_invalidate_unlock(vi->i_mapping);
+
if (!err) {
- if (mode == 0 && NInoNonResident(ni) &&
- offset > old_size) {
- truncate_pagecache(vi, old_size);
- pagecache_isize_extended(vi, old_size, offset);
- }
NInoSetFileNameDirty(ni);
inode_set_mtime_to_ts(vi, inode_set_ctime_current(vi));
mark_inode_dirty(vi);

Thanks for the review!

You're right. ntfs_fallocate() dropped invalidate_lock before calling
truncate_pagecache() and pagecache_isize_extended(), so a write fault
holding the lock shared could interleave with the page-cache cleanup
and have its folio discarded by truncate_inode_pages(), losing the
mmap write. Moving both calls inside the lock hold range fixes it.

I've posted v2 and addresses your comment.