Skip to content

Commit 6630ea4

Browse files
YuezhangMonamjaejeon
authored andcommitted
exfat: move extend valid_size into ->page_mkwrite()
It is not a good way to extend valid_size to the end of the mmap area by writing zeros in mmap. Because after calling mmap, no data may be written, or only a small amount of data may be written to the head of the mmap area. This commit moves extending valid_size to exfat_page_mkwrite(). In exfat_page_mkwrite() only extend valid_size to the starting position of new data writing, which reduces unnecessary writing of zeros. If the block is not mapped and is marked as new after being mapped for writing, block_write_begin() will zero the page cache corresponding to the block, so there is no need to call zero_user_segment() in exfat_file_zeroed_range(). And after moving extending valid_size to exfat_page_mkwrite(), the data written by mmap will be copied to the page cache but the page cache may be not mapped to the disk. Calling zero_user_segment() will cause the data written by mmap to be cleared. So this commit removes calling zero_user_segment() from exfat_file_zeroed_range() and renames exfat_file_zeroed_range() to exfat_extend_valid_size(). Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
1 parent d2b537b commit 6630ea4

File tree

1 file changed

+45
-25
lines changed

1 file changed

+45
-25
lines changed

fs/exfat/file.c

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -532,32 +532,32 @@ int exfat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
532532
return blkdev_issue_flush(inode->i_sb->s_bdev);
533533
}
534534

535-
static int exfat_file_zeroed_range(struct file *file, loff_t start, loff_t end)
535+
static int exfat_extend_valid_size(struct file *file, loff_t new_valid_size)
536536
{
537537
int err;
538+
loff_t pos;
538539
struct inode *inode = file_inode(file);
540+
struct exfat_inode_info *ei = EXFAT_I(inode);
539541
struct address_space *mapping = inode->i_mapping;
540542
const struct address_space_operations *ops = mapping->a_ops;
541543

542-
while (start < end) {
543-
u32 zerofrom, len;
544+
pos = ei->valid_size;
545+
while (pos < new_valid_size) {
546+
u32 len;
544547
struct folio *folio;
545548

546-
zerofrom = start & (PAGE_SIZE - 1);
547-
len = PAGE_SIZE - zerofrom;
548-
if (start + len > end)
549-
len = end - start;
549+
len = PAGE_SIZE - (pos & (PAGE_SIZE - 1));
550+
if (pos + len > new_valid_size)
551+
len = new_valid_size - pos;
550552

551-
err = ops->write_begin(file, mapping, start, len, &folio, NULL);
553+
err = ops->write_begin(file, mapping, pos, len, &folio, NULL);
552554
if (err)
553555
goto out;
554556

555-
folio_zero_range(folio, offset_in_folio(folio, start), len);
556-
557-
err = ops->write_end(file, mapping, start, len, len, folio, NULL);
557+
err = ops->write_end(file, mapping, pos, len, len, folio, NULL);
558558
if (err < 0)
559559
goto out;
560-
start += len;
560+
pos += len;
561561

562562
balance_dirty_pages_ratelimited(mapping);
563563
cond_resched();
@@ -585,7 +585,7 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter)
585585
goto unlock;
586586

587587
if (pos > valid_size) {
588-
ret = exfat_file_zeroed_range(file, valid_size, pos);
588+
ret = exfat_extend_valid_size(file, pos);
589589
if (ret < 0 && ret != -ENOSPC) {
590590
exfat_err(inode->i_sb,
591591
"write: fail to zero from %llu to %llu(%zd)",
@@ -619,26 +619,46 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter)
619619
return ret;
620620
}
621621

622-
static int exfat_file_mmap(struct file *file, struct vm_area_struct *vma)
622+
static vm_fault_t exfat_page_mkwrite(struct vm_fault *vmf)
623623
{
624-
int ret;
624+
int err;
625+
struct vm_area_struct *vma = vmf->vma;
626+
struct file *file = vma->vm_file;
625627
struct inode *inode = file_inode(file);
626628
struct exfat_inode_info *ei = EXFAT_I(inode);
627-
loff_t start = ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
628-
loff_t end = min_t(loff_t, i_size_read(inode),
629+
loff_t start, end;
630+
631+
if (!inode_trylock(inode))
632+
return VM_FAULT_RETRY;
633+
634+
start = ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
635+
end = min_t(loff_t, i_size_read(inode),
629636
start + vma->vm_end - vma->vm_start);
630637

631-
if ((vma->vm_flags & VM_WRITE) && ei->valid_size < end) {
632-
ret = exfat_file_zeroed_range(file, ei->valid_size, end);
633-
if (ret < 0) {
634-
exfat_err(inode->i_sb,
635-
"mmap: fail to zero from %llu to %llu(%d)",
636-
start, end, ret);
637-
return ret;
638+
if (ei->valid_size < end) {
639+
err = exfat_extend_valid_size(file, end);
640+
if (err < 0) {
641+
inode_unlock(inode);
642+
return vmf_fs_error(err);
638643
}
639644
}
640645

641-
return generic_file_mmap(file, vma);
646+
inode_unlock(inode);
647+
648+
return filemap_page_mkwrite(vmf);
649+
}
650+
651+
static const struct vm_operations_struct exfat_file_vm_ops = {
652+
.fault = filemap_fault,
653+
.map_pages = filemap_map_pages,
654+
.page_mkwrite = exfat_page_mkwrite,
655+
};
656+
657+
static int exfat_file_mmap(struct file *file, struct vm_area_struct *vma)
658+
{
659+
file_accessed(file);
660+
vma->vm_ops = &exfat_file_vm_ops;
661+
return 0;
642662
}
643663

644664
const struct file_operations exfat_file_operations = {

0 commit comments

Comments
 (0)