mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 05:04:02 +02:00
exfat: clean up new entry on add entry failure
exfat_add_entry() initializes a new directory entry set before writing it with exfat_put_dentry_set(). If the write fails, mkdir/create returns an error but a partially written entry may be left behind. For non-zero-size directories, the failure also happens after a cluster has been allocated for the new directory. Clean up the new entry best-effort, and free the newly allocated directory cluster only when the cleanup writeback succeeds. This avoids freeing a cluster that may still be referenced by an on-disk entry if the cleanup fails. Signed-off-by: Yichong Chen <chenyichong@uniontech.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
parent
ce12a39bed
commit
0901a71e8c
|
|
@ -471,6 +471,7 @@ static int exfat_add_entry(struct inode *inode, const char *path,
|
|||
struct exfat_entry_set_cache es;
|
||||
int clu_size = 0;
|
||||
unsigned int start_clu = EXFAT_FREE_CLUSTER;
|
||||
bool dir_allocated = false;
|
||||
|
||||
ret = exfat_resolve_path(inode, path, &uniname);
|
||||
if (ret)
|
||||
|
|
@ -497,6 +498,7 @@ static int exfat_add_entry(struct inode *inode, const char *path,
|
|||
}
|
||||
start_clu = clu.dir;
|
||||
clu_size = sbi->cluster_size;
|
||||
dir_allocated = true;
|
||||
}
|
||||
|
||||
/* update the directory entry */
|
||||
|
|
@ -507,8 +509,21 @@ static int exfat_add_entry(struct inode *inode, const char *path,
|
|||
exfat_init_ext_entry(&es, num_entries, &uniname, NULL, 0);
|
||||
|
||||
ret = exfat_put_dentry_set(&es, IS_DIRSYNC(inode));
|
||||
if (ret)
|
||||
if (ret) {
|
||||
int cleanup_ret;
|
||||
|
||||
cleanup_ret = exfat_get_dentry_set(&es, sb, &info->dir,
|
||||
dentry, ES_ALL_ENTRIES);
|
||||
if (!cleanup_ret) {
|
||||
exfat_remove_entries(inode, &es, ES_IDX_FILE, false);
|
||||
cleanup_ret = exfat_put_dentry_set(&es,
|
||||
IS_DIRSYNC(inode));
|
||||
}
|
||||
|
||||
if (!cleanup_ret && dir_allocated)
|
||||
exfat_free_cluster(inode, &clu);
|
||||
goto out;
|
||||
}
|
||||
|
||||
info->entry = dentry;
|
||||
info->flags = ALLOC_NO_FAT_CHAIN;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user