From 31f61e9fd68258588910c05dcbd50af381fe8b96 Mon Sep 17 00:00:00 2001 From: Yuezhang Mo Date: Mon, 14 Oct 2024 12:52:28 +0800 Subject: [PATCH] exfat: do not update ->valid_size in exfat_get_block() if map for direct write Signed-off-by: Yuezhang Mo --- fs/exfat/inode.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/fs/exfat/inode.c b/fs/exfat/inode.c index d338a59c27f7..6e1312f30846 100644 --- a/fs/exfat/inode.c +++ b/fs/exfat/inode.c @@ -261,8 +261,8 @@ static int exfat_map_cluster(struct inode *inode, unsigned int clu_offset, return 0; } -static int exfat_get_block(struct inode *inode, sector_t iblock, - struct buffer_head *bh_result, int create) +static int __exfat_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create, bool dio) { struct exfat_inode_info *ei = EXFAT_I(inode); struct super_block *sb = inode->i_sb; @@ -323,8 +323,10 @@ static int exfat_get_block(struct inode *inode, sector_t iblock, /* The area has not been written, map and mark as new. */ set_buffer_new(bh_result); - ei->valid_size = EXFAT_BLK_TO_B(iblock + max_blocks, sb); - mark_inode_dirty(inode); + if (!dio) { + ei->valid_size = EXFAT_BLK_TO_B(iblock + max_blocks, sb); + mark_inode_dirty(inode); + } } else { valid_blks = EXFAT_B_TO_BLK(ei->valid_size, sb); @@ -381,6 +383,18 @@ static int exfat_get_block(struct inode *inode, sector_t iblock, return err; } +static int exfat_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create) +{ + return __exfat_get_block(inode, iblock, bh_result, create, false); +} + +static int exfat_get_block_for_dio(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create) +{ + return __exfat_get_block(inode, iblock, bh_result, create, true); +} + static int exfat_read_folio(struct file *file, struct folio *folio) { return mpage_read_folio(folio, exfat_get_block); @@ -479,7 +493,7 @@ static ssize_t exfat_direct_IO(struct kiocb *iocb, struct iov_iter *iter) * Need to use the DIO_LOCKING for avoiding the race * condition of exfat_get_block() and ->truncate(). */ - ret = blockdev_direct_IO(iocb, inode, iter, exfat_get_block); + ret = blockdev_direct_IO(iocb, inode, iter, exfat_get_block_for_dio); if (ret < 0) { if (rw == WRITE && ret != -EIOCBQUEUED) exfat_write_failed(mapping, size); -- 2.34.1