Skip to content

Commit f55c096

Browse files
YuezhangMonamjaejeon
authored andcommitted
exfat: do not zero the extended part
Since the read operation beyond the ValidDataLength returns zero, if we just extend the size of the file, we don't need to zero the extended part, but only change the DataLength without changing the ValidDataLength. Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com> Reviewed-by: Andy Wu <Andy.Wu@sony.com> Reviewed-by: Aoyama Wataru <wataru.aoyama@sony.com> Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
1 parent 11a347f commit f55c096

File tree

2 files changed

+70
-21
lines changed

2 files changed

+70
-21
lines changed

fs/exfat/file.c

Lines changed: 57 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,69 @@
1818

1919
static int exfat_cont_expand(struct inode *inode, loff_t size)
2020
{
21-
struct address_space *mapping = inode->i_mapping;
22-
loff_t start = i_size_read(inode), count = size - i_size_read(inode);
23-
int err, err2;
21+
int ret;
22+
unsigned int num_clusters, new_num_clusters, last_clu;
23+
struct exfat_inode_info *ei = EXFAT_I(inode);
24+
struct super_block *sb = inode->i_sb;
25+
struct exfat_sb_info *sbi = EXFAT_SB(sb);
26+
struct exfat_chain clu;
2427

25-
err = generic_cont_expand_simple(inode, size);
26-
if (err)
27-
return err;
28+
ret = inode_newsize_ok(inode, size);
29+
if (ret)
30+
return ret;
31+
32+
num_clusters = EXFAT_B_TO_CLU_ROUND_UP(ei->i_size_ondisk, sbi);
33+
new_num_clusters = EXFAT_B_TO_CLU_ROUND_UP(size, sbi);
34+
35+
if (new_num_clusters == num_clusters)
36+
goto out;
37+
38+
exfat_chain_set(&clu, ei->start_clu, num_clusters, ei->flags);
39+
ret = exfat_find_last_cluster(sb, &clu, &last_clu);
40+
if (ret)
41+
return ret;
2842

43+
clu.dir = (last_clu == EXFAT_EOF_CLUSTER) ?
44+
EXFAT_EOF_CLUSTER : last_clu + 1;
45+
clu.size = 0;
46+
clu.flags = ei->flags;
47+
48+
ret = exfat_alloc_cluster(inode, new_num_clusters - num_clusters,
49+
&clu, IS_DIRSYNC(inode));
50+
if (ret)
51+
return ret;
52+
53+
/* Append new clusters to chain */
54+
if (clu.flags != ei->flags) {
55+
exfat_chain_cont_cluster(sb, ei->start_clu, num_clusters);
56+
ei->flags = ALLOC_FAT_CHAIN;
57+
}
58+
if (clu.flags == ALLOC_FAT_CHAIN)
59+
if (exfat_ent_set(sb, last_clu, clu.dir))
60+
goto free_clu;
61+
62+
if (num_clusters == 0)
63+
ei->start_clu = clu.dir;
64+
65+
out:
2966
inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
30-
EXFAT_I(inode)->valid_size = size;
31-
mark_inode_dirty(inode);
67+
/* Expanded range not zeroed, do not update valid_size */
68+
i_size_write(inode, size);
3269

33-
if (!IS_SYNC(inode))
34-
return 0;
70+
ei->i_size_aligned = round_up(size, sb->s_blocksize);
71+
ei->i_size_ondisk = ei->i_size_aligned;
72+
inode->i_blocks = round_up(size, sbi->cluster_size) >> 9;
3573

36-
err = filemap_fdatawrite_range(mapping, start, start + count - 1);
37-
err2 = sync_mapping_buffers(mapping);
38-
if (!err)
39-
err = err2;
40-
err2 = write_inode_now(inode, 1);
41-
if (!err)
42-
err = err2;
43-
if (err)
44-
return err;
74+
if (IS_DIRSYNC(inode))
75+
return write_inode_now(inode, 1);
76+
77+
mark_inode_dirty(inode);
78+
79+
return 0;
4580

46-
return filemap_fdatawait_range(mapping, start, start + count - 1);
81+
free_clu:
82+
exfat_free_cluster(inode, &clu);
83+
return -EIO;
4784
}
4885

4986
static bool exfat_allow_set_time(struct exfat_sb_info *sbi, struct inode *inode)

fs/exfat/inode.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,17 @@ int __exfat_write_inode(struct inode *inode, int sync)
7575
if (ei->start_clu == EXFAT_EOF_CLUSTER)
7676
on_disk_size = 0;
7777

78-
ep2->dentry.stream.valid_size = cpu_to_le64(ei->valid_size);
7978
ep2->dentry.stream.size = cpu_to_le64(on_disk_size);
79+
/*
80+
* mmap write does not use exfat_write_end(), valid_size may be
81+
* extended to the sector-aligned length in exfat_get_block().
82+
* So we need to fixup valid_size to the writren length.
83+
*/
84+
if (on_disk_size < ei->valid_size)
85+
ep2->dentry.stream.valid_size = ep2->dentry.stream.size;
86+
else
87+
ep2->dentry.stream.valid_size = cpu_to_le64(ei->valid_size);
88+
8089
if (on_disk_size) {
8190
ep2->dentry.stream.flags = ei->flags;
8291
ep2->dentry.stream.start_clu = cpu_to_le32(ei->start_clu);
@@ -340,6 +349,9 @@ static int exfat_get_block(struct inode *inode, sector_t iblock,
340349
pos, ei->i_size_aligned);
341350
goto unlock_ret;
342351
}
352+
353+
ei->valid_size = EXFAT_BLK_TO_B(iblock + max_blocks, sb);
354+
mark_inode_dirty(inode);
343355
} else {
344356
valid_blks = EXFAT_B_TO_BLK(ei->valid_size, sb);
345357

0 commit comments

Comments
 (0)