mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2024-12-29 09:13:38 +00:00
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>
This commit is contained in:
parent
11a347fb6c
commit
f55c096f62
@ -18,32 +18,69 @@
|
||||
|
||||
static int exfat_cont_expand(struct inode *inode, loff_t size)
|
||||
{
|
||||
struct address_space *mapping = inode->i_mapping;
|
||||
loff_t start = i_size_read(inode), count = size - i_size_read(inode);
|
||||
int err, err2;
|
||||
int ret;
|
||||
unsigned int num_clusters, new_num_clusters, last_clu;
|
||||
struct exfat_inode_info *ei = EXFAT_I(inode);
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||
struct exfat_chain clu;
|
||||
|
||||
err = generic_cont_expand_simple(inode, size);
|
||||
if (err)
|
||||
return err;
|
||||
ret = inode_newsize_ok(inode, size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
num_clusters = EXFAT_B_TO_CLU_ROUND_UP(ei->i_size_ondisk, sbi);
|
||||
new_num_clusters = EXFAT_B_TO_CLU_ROUND_UP(size, sbi);
|
||||
|
||||
if (new_num_clusters == num_clusters)
|
||||
goto out;
|
||||
|
||||
exfat_chain_set(&clu, ei->start_clu, num_clusters, ei->flags);
|
||||
ret = exfat_find_last_cluster(sb, &clu, &last_clu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clu.dir = (last_clu == EXFAT_EOF_CLUSTER) ?
|
||||
EXFAT_EOF_CLUSTER : last_clu + 1;
|
||||
clu.size = 0;
|
||||
clu.flags = ei->flags;
|
||||
|
||||
ret = exfat_alloc_cluster(inode, new_num_clusters - num_clusters,
|
||||
&clu, IS_DIRSYNC(inode));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Append new clusters to chain */
|
||||
if (clu.flags != ei->flags) {
|
||||
exfat_chain_cont_cluster(sb, ei->start_clu, num_clusters);
|
||||
ei->flags = ALLOC_FAT_CHAIN;
|
||||
}
|
||||
if (clu.flags == ALLOC_FAT_CHAIN)
|
||||
if (exfat_ent_set(sb, last_clu, clu.dir))
|
||||
goto free_clu;
|
||||
|
||||
if (num_clusters == 0)
|
||||
ei->start_clu = clu.dir;
|
||||
|
||||
out:
|
||||
inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
|
||||
EXFAT_I(inode)->valid_size = size;
|
||||
/* Expanded range not zeroed, do not update valid_size */
|
||||
i_size_write(inode, size);
|
||||
|
||||
ei->i_size_aligned = round_up(size, sb->s_blocksize);
|
||||
ei->i_size_ondisk = ei->i_size_aligned;
|
||||
inode->i_blocks = round_up(size, sbi->cluster_size) >> 9;
|
||||
|
||||
if (IS_DIRSYNC(inode))
|
||||
return write_inode_now(inode, 1);
|
||||
|
||||
mark_inode_dirty(inode);
|
||||
|
||||
if (!IS_SYNC(inode))
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
err = filemap_fdatawrite_range(mapping, start, start + count - 1);
|
||||
err2 = sync_mapping_buffers(mapping);
|
||||
if (!err)
|
||||
err = err2;
|
||||
err2 = write_inode_now(inode, 1);
|
||||
if (!err)
|
||||
err = err2;
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return filemap_fdatawait_range(mapping, start, start + count - 1);
|
||||
free_clu:
|
||||
exfat_free_cluster(inode, &clu);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static bool exfat_allow_set_time(struct exfat_sb_info *sbi, struct inode *inode)
|
||||
|
@ -75,8 +75,17 @@ int __exfat_write_inode(struct inode *inode, int sync)
|
||||
if (ei->start_clu == EXFAT_EOF_CLUSTER)
|
||||
on_disk_size = 0;
|
||||
|
||||
ep2->dentry.stream.valid_size = cpu_to_le64(ei->valid_size);
|
||||
ep2->dentry.stream.size = cpu_to_le64(on_disk_size);
|
||||
/*
|
||||
* mmap write does not use exfat_write_end(), valid_size may be
|
||||
* extended to the sector-aligned length in exfat_get_block().
|
||||
* So we need to fixup valid_size to the writren length.
|
||||
*/
|
||||
if (on_disk_size < ei->valid_size)
|
||||
ep2->dentry.stream.valid_size = ep2->dentry.stream.size;
|
||||
else
|
||||
ep2->dentry.stream.valid_size = cpu_to_le64(ei->valid_size);
|
||||
|
||||
if (on_disk_size) {
|
||||
ep2->dentry.stream.flags = ei->flags;
|
||||
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,
|
||||
pos, ei->i_size_aligned);
|
||||
goto unlock_ret;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user