mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-03 19:53:32 +00:00
exfat: fix appending discontinuous clusters to empty file
Eric Hong found that when using ftruncate to expand an empty file,
exfat_ent_set() will fail if discontinuous clusters are allocated.
The reason is that the empty file does not have a cluster chain,
but exfat_ent_set() attempts to append the newly allocated cluster
to the cluster chain. In addition, exfat_find_last_cluster() only
supports finding the last cluster in a non-empty file.
So this commit adds a check whether the file is empty. If the file
is empty, exfat_find_last_cluster() and exfat_ent_set() are no longer
called as they do not need to be called.
Fixes: f55c096f62
("exfat: do not zero the extended part")
Reported-by: Eric Hong <erichong@qnap.com>
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
parent
c02197fc90
commit
3a7845041e
@ -35,13 +35,18 @@ static int exfat_cont_expand(struct inode *inode, loff_t size)
|
||||
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;
|
||||
if (num_clusters) {
|
||||
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 + 1;
|
||||
} else {
|
||||
last_clu = EXFAT_EOF_CLUSTER;
|
||||
clu.dir = EXFAT_EOF_CLUSTER;
|
||||
}
|
||||
|
||||
clu.dir = (last_clu == EXFAT_EOF_CLUSTER) ?
|
||||
EXFAT_EOF_CLUSTER : last_clu + 1;
|
||||
clu.size = 0;
|
||||
clu.flags = ei->flags;
|
||||
|
||||
@ -51,17 +56,19 @@ static int exfat_cont_expand(struct inode *inode, loff_t size)
|
||||
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) {
|
||||
if (clu.flags != ei->flags)
|
||||
if (exfat_chain_cont_cluster(sb, ei->start_clu, num_clusters))
|
||||
goto free_clu;
|
||||
|
||||
if (num_clusters == 0)
|
||||
if (clu.flags == ALLOC_FAT_CHAIN)
|
||||
if (exfat_ent_set(sb, last_clu, clu.dir))
|
||||
goto free_clu;
|
||||
} else
|
||||
ei->start_clu = clu.dir;
|
||||
|
||||
ei->flags = clu.flags;
|
||||
|
||||
out:
|
||||
inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
|
||||
/* Expanded range not zeroed, do not update valid_size */
|
||||
|
Loading…
Reference in New Issue
Block a user