Re: [PATCH v4 08/11] exfat: add iomap buffered I/O support

From: Yuezhang.Mo@xxxxxxxx

Date: Tue May 19 2026 - 01:23:14 EST


> @@ -749,28 +750,56 @@ static ssize_t exfat_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
>
> static vm_fault_t exfat_page_mkwrite(struct vm_fault *vmf)
> {
> - int err;
> struct inode *inode = file_inode(vmf->vma->vm_file);
> struct exfat_inode_info *ei = EXFAT_I(inode);
> - loff_t new_valid_size;
> + vm_fault_t ret;
> + loff_t new_valid_size, mmap_valid_size;
>
> if (!inode_trylock(inode))
> return VM_FAULT_RETRY;
>
> - new_valid_size = ((loff_t)vmf->pgoff + 1) << PAGE_SHIFT;
> - new_valid_size = min(new_valid_size, i_size_read(inode));
> + mmap_valid_size = ((loff_t)vmf->pgoff + 1) << PAGE_SHIFT;
> + new_valid_size = min(mmap_valid_size, i_size_read(inode));
>
> if (ei->valid_size < new_valid_size) {
> - err = exfat_extend_valid_size(inode, new_valid_size);
> - if (err < 0) {
> - inode_unlock(inode);
> - return vmf_fs_error(err);
> + if (ei->zeroed_size < mmap_valid_size) {
> + int err;
> +
> + /*
> + * Only zero the range that hasn't been zeroed yet for
> + * this mmap write path. zeroed_size tracks the largest
> + * page-aligned offset that has already been zeroed.
> + *
> + * This prevents unnecessarily zeroing out the entire
> + * tail page on every page fault when userspace writes
> + * data byte-by-byte through mmap (after a small
> + * fallocate). It fixes data corruption in the tail page
> + * while preserving the existing valid_size semantics.
> + */
> + err = iomap_zero_range(inode, ei->zeroed_size,
> + mmap_valid_size - ei->zeroed_size, NULL,
> + &exfat_iomap_ops, NULL, NULL);

For volumes with clusters smaller than 4K, mmap_valid_size may be greater
than exfat_on_disksize(), causing iomap_zero_range() to allocate new clusters
for the file. We need to ensure that mmap_valid_size is not greater than
exfat_on_disksize() to avoid this situation.

> + if (err < 0) {
> + inode_unlock(inode);
> + return vmf_fs_error(err);
> + }
> + ei->zeroed_size = mmap_valid_size;