exfat: fix the newly allocated clusters are not freed in error handling
In error handling 'free_cluster', before num_alloc clusters allocated, p_chain->size will not updated and always 0, thus the newly allocated clusters are not freed. Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com> Reviewed-by: Andy Wu <Andy.Wu@sony.com> Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
+8
-10
@@ -307,7 +307,7 @@ int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
|
|||||||
struct exfat_chain *p_chain, bool sync_bmap)
|
struct exfat_chain *p_chain, bool sync_bmap)
|
||||||
{
|
{
|
||||||
int ret = -ENOSPC;
|
int ret = -ENOSPC;
|
||||||
unsigned int num_clusters = 0, total_cnt;
|
unsigned int total_cnt;
|
||||||
unsigned int hint_clu, new_clu, last_clu = EXFAT_EOF_CLUSTER;
|
unsigned int hint_clu, new_clu, last_clu = EXFAT_EOF_CLUSTER;
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
struct exfat_sb_info *sbi = EXFAT_SB(sb);
|
||||||
@@ -358,7 +358,7 @@ int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
|
|||||||
if (new_clu != hint_clu &&
|
if (new_clu != hint_clu &&
|
||||||
p_chain->flags == ALLOC_NO_FAT_CHAIN) {
|
p_chain->flags == ALLOC_NO_FAT_CHAIN) {
|
||||||
if (exfat_chain_cont_cluster(sb, p_chain->dir,
|
if (exfat_chain_cont_cluster(sb, p_chain->dir,
|
||||||
num_clusters)) {
|
p_chain->size)) {
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto free_cluster;
|
goto free_cluster;
|
||||||
}
|
}
|
||||||
@@ -371,8 +371,6 @@ int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
|
|||||||
goto free_cluster;
|
goto free_cluster;
|
||||||
}
|
}
|
||||||
|
|
||||||
num_clusters++;
|
|
||||||
|
|
||||||
/* update FAT table */
|
/* update FAT table */
|
||||||
if (p_chain->flags == ALLOC_FAT_CHAIN) {
|
if (p_chain->flags == ALLOC_FAT_CHAIN) {
|
||||||
if (exfat_ent_set(sb, new_clu, EXFAT_EOF_CLUSTER)) {
|
if (exfat_ent_set(sb, new_clu, EXFAT_EOF_CLUSTER)) {
|
||||||
@@ -389,13 +387,14 @@ int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
|
|||||||
goto free_cluster;
|
goto free_cluster;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
p_chain->size++;
|
||||||
|
|
||||||
last_clu = new_clu;
|
last_clu = new_clu;
|
||||||
|
|
||||||
if (--num_alloc == 0) {
|
if (p_chain->size == num_alloc) {
|
||||||
sbi->clu_srch_ptr = hint_clu;
|
sbi->clu_srch_ptr = hint_clu;
|
||||||
sbi->used_clusters += num_clusters;
|
sbi->used_clusters += num_alloc;
|
||||||
|
|
||||||
p_chain->size += num_clusters;
|
|
||||||
mutex_unlock(&sbi->bitmap_lock);
|
mutex_unlock(&sbi->bitmap_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -406,7 +405,7 @@ int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
|
|||||||
|
|
||||||
if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
|
if (p_chain->flags == ALLOC_NO_FAT_CHAIN) {
|
||||||
if (exfat_chain_cont_cluster(sb, p_chain->dir,
|
if (exfat_chain_cont_cluster(sb, p_chain->dir,
|
||||||
num_clusters)) {
|
p_chain->size)) {
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto free_cluster;
|
goto free_cluster;
|
||||||
}
|
}
|
||||||
@@ -415,8 +414,7 @@ int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
free_cluster:
|
free_cluster:
|
||||||
if (num_clusters)
|
__exfat_free_cluster(inode, p_chain);
|
||||||
__exfat_free_cluster(inode, p_chain);
|
|
||||||
unlock:
|
unlock:
|
||||||
mutex_unlock(&sbi->bitmap_lock);
|
mutex_unlock(&sbi->bitmap_lock);
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
Reference in New Issue
Block a user