exfat: do not fallback to buffered write
authorYuezhang Mo <Yuezhang.Mo@sony.com>
Tue, 17 Sep 2024 05:58:56 +0000 (14:58 +0900)
committerNamjae Jeon <linkinjeon@kernel.org>
Tue, 17 Sep 2024 06:09:50 +0000 (15:09 +0900)
After commit(11a347fb6cef exfat: change to get file size from
DataLength), the remaining area or hole had been filled with
zeros before calling exfat_direct_IO(), so there is no need to
fallback to buffered write, and ->i_size_aligned is no longer
needed, drop it.

Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
fs/exfat/exfat_fs.h
fs/exfat/file.c
fs/exfat/inode.c
fs/exfat/namei.c
fs/exfat/super.c

index 77cc62b026d39950082ca3d4e0bc067d31a45fd0..5be214288a05b28a69ca6fb9b6ea689c3a2fedc1 100644 (file)
@@ -309,8 +309,6 @@ struct exfat_inode_info {
        /* for avoiding the race between alloc and free */
        unsigned int cache_valid_id;
 
-       /* block-aligned i_size (used in cont_write_begin) */
-       loff_t i_size_aligned;
        /* on-disk position of directory entry or 0 */
        loff_t i_pos;
        loff_t valid_size;
index fd4a8a170c1f798caa591785b08e37498f39064f..860c1f3b2cd7591f5f40ed86703cf1d2fb8841f3 100644 (file)
@@ -74,7 +74,6 @@ out:
        /* Expanded range not zeroed, do not update valid_size */
        i_size_write(inode, size);
 
-       ei->i_size_aligned = round_up(size, sb->s_blocksize);
        inode->i_blocks = round_up(size, sbi->cluster_size) >> 9;
        mark_inode_dirty(inode);
 
@@ -244,8 +243,6 @@ void exfat_truncate(struct inode *inode)
        struct super_block *sb = inode->i_sb;
        struct exfat_sb_info *sbi = EXFAT_SB(sb);
        struct exfat_inode_info *ei = EXFAT_I(inode);
-       unsigned int blocksize = i_blocksize(inode);
-       loff_t aligned_size;
        int err;
 
        mutex_lock(&sbi->s_lock);
@@ -263,14 +260,6 @@ void exfat_truncate(struct inode *inode)
 
        inode->i_blocks = round_up(i_size_read(inode), sbi->cluster_size) >> 9;
 write_size:
-       aligned_size = i_size_read(inode);
-       if (aligned_size & (blocksize - 1)) {
-               aligned_size |= (blocksize - 1);
-               aligned_size++;
-       }
-
-       if (ei->i_size_aligned > i_size_read(inode))
-               ei->i_size_aligned = aligned_size;
        mutex_unlock(&sbi->s_lock);
 }
 
index ed737ef288d2fdc1c1d5a910d0bcbdc2a36e9c99..e7a74a948be1eac7a1abda136bfd5003caeada41 100644 (file)
@@ -258,21 +258,6 @@ static int exfat_map_cluster(struct inode *inode, unsigned int clu_offset,
        return 0;
 }
 
-static int exfat_map_new_buffer(struct exfat_inode_info *ei,
-               struct buffer_head *bh, loff_t pos)
-{
-       if (buffer_delay(bh) && pos > ei->i_size_aligned)
-               return -EIO;
-       set_buffer_new(bh);
-
-       /*
-        * Adjust i_size_aligned if ondisk_size is bigger than it.
-        */
-       if (exfat_ondisk_size(&ei->vfs_inode) > ei->i_size_aligned)
-               ei->i_size_aligned = exfat_ondisk_size(&ei->vfs_inode);
-       return 0;
-}
-
 static int exfat_get_block(struct inode *inode, sector_t iblock,
                struct buffer_head *bh_result, int create)
 {
@@ -286,7 +271,6 @@ static int exfat_get_block(struct inode *inode, sector_t iblock,
        sector_t last_block;
        sector_t phys = 0;
        sector_t valid_blks;
-       loff_t pos;
 
        mutex_lock(&sbi->s_lock);
        last_block = EXFAT_B_TO_BLK_ROUND_UP(i_size_read(inode), sb);
@@ -314,8 +298,6 @@ static int exfat_get_block(struct inode *inode, sector_t iblock,
        mapped_blocks = sbi->sect_per_clus - sec_offset;
        max_blocks = min(mapped_blocks, max_blocks);
 
-       pos = EXFAT_BLK_TO_B((iblock + 1), sb);
-
        map_bh(bh_result, sb, phys);
        if (buffer_delay(bh_result))
                clear_buffer_delay(bh_result);
@@ -336,13 +318,7 @@ static int exfat_get_block(struct inode *inode, sector_t iblock,
                }
 
                /* The area has not been written, map and mark as new. */
-               err = exfat_map_new_buffer(ei, bh_result, pos);
-               if (err) {
-                       exfat_fs_error(sb,
-                                       "requested for bmap out of range(pos : (%llu) > i_size_aligned(%llu)\n",
-                                       pos, ei->i_size_aligned);
-                       goto unlock_ret;
-               }
+               set_buffer_new(bh_result);
 
                ei->valid_size = EXFAT_BLK_TO_B(iblock + max_blocks, sb);
                mark_inode_dirty(inode);
@@ -365,7 +341,7 @@ static int exfat_get_block(struct inode *inode, sector_t iblock,
                         * The block has been partially written,
                         * zero the unwritten part and map the block.
                         */
-                       loff_t size, off;
+                       loff_t size, off, pos;
 
                        max_blocks = 1;
 
@@ -376,7 +352,7 @@ static int exfat_get_block(struct inode *inode, sector_t iblock,
                        if (!bh_result->b_folio)
                                goto done;
 
-                       pos -= sb->s_blocksize;
+                       pos = EXFAT_BLK_TO_B(iblock, sb);
                        size = ei->valid_size - pos;
                        off = pos & (PAGE_SIZE - 1);
 
@@ -463,14 +439,6 @@ static int exfat_write_end(struct file *file, struct address_space *mapping,
        int err;
 
        err = generic_write_end(file, mapping, pos, len, copied, folio, fsdata);
-
-       if (ei->i_size_aligned < i_size_read(inode)) {
-               exfat_fs_error(inode->i_sb,
-                       "invalid size(size(%llu) > aligned(%llu)\n",
-                       i_size_read(inode), ei->i_size_aligned);
-               return -EIO;
-       }
-
        if (err < len)
                exfat_write_failed(mapping, pos+len);
 
@@ -498,20 +466,6 @@ static ssize_t exfat_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
        int rw = iov_iter_rw(iter);
        ssize_t ret;
 
-       if (rw == WRITE) {
-               /*
-                * FIXME: blockdev_direct_IO() doesn't use ->write_begin(),
-                * so we need to update the ->i_size_aligned to block boundary.
-                *
-                * But we must fill the remaining area or hole by nul for
-                * updating ->i_size_aligned
-                *
-                * Return 0, and fallback to normal buffered write.
-                */
-               if (EXFAT_I(inode)->i_size_aligned < size)
-                       return 0;
-       }
-
        /*
         * Need to use the DIO_LOCKING for avoiding the race
         * condition of exfat_get_block() and ->truncate().
@@ -525,8 +479,18 @@ static ssize_t exfat_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
        } else
                size = pos + ret;
 
-       /* zero the unwritten part in the partially written block */
-       if (rw == READ && pos < ei->valid_size && ei->valid_size < size) {
+       if (rw == WRITE) {
+               /*
+                * If the block had been partially written before this write,
+                * ->valid_size will not be updated in exfat_get_block(),
+                * update it here.
+                */
+               if (ei->valid_size < size) {
+                       ei->valid_size = size;
+                       mark_inode_dirty(inode);
+               }
+       } else if (pos < ei->valid_size && ei->valid_size < size) {
+               /* zero the unwritten part in the partially written block */
                iov_iter_revert(iter, size - ei->valid_size);
                iov_iter_zero(size - ei->valid_size, iter);
        }
@@ -661,14 +625,6 @@ static int exfat_fill_inode(struct inode *inode, struct exfat_dir_entry *info)
 
        i_size_write(inode, size);
 
-       /* ondisk and aligned size should be aligned with block size */
-       if (size & (inode->i_sb->s_blocksize - 1)) {
-               size |= (inode->i_sb->s_blocksize - 1);
-               size++;
-       }
-
-       ei->i_size_aligned = size;
-
        exfat_save_attr(inode, info->attr);
 
        inode->i_blocks = round_up(i_size_read(inode), sbi->cluster_size) >> 9;
index 6313dee5c9bbeeb3ef12779d4b1a1e16b516ff8d..3e6c789a72c4f47f5e101b9830c55ce94c3d2f49 100644 (file)
@@ -372,7 +372,6 @@ static int exfat_find_empty_entry(struct inode *inode,
 
                /* directory inode should be updated in here */
                i_size_write(inode, size);
-               ei->i_size_aligned += sbi->cluster_size;
                ei->valid_size += sbi->cluster_size;
                ei->flags = p_dir->flags;
                inode->i_blocks += sbi->cluster_size >> 9;
index 6516edff38fc8173aa70458a7205daff6e1d8344..904583f874338bef07707850d1744c18981d4139 100644 (file)
@@ -370,7 +370,6 @@ static int exfat_read_root(struct inode *inode)
 
        inode->i_blocks = round_up(i_size_read(inode), sbi->cluster_size) >> 9;
        ei->i_pos = ((loff_t)sbi->root_dir << 32) | 0xffffffff;
-       ei->i_size_aligned = i_size_read(inode);
 
        exfat_save_attr(inode, EXFAT_ATTR_SUBDIR);
        ei->i_crtime = simple_inode_init_ts(inode);