Skip to content

Commit dab48b8

Browse files
YuezhangMonamjaejeon
authored andcommitted
exfat: support handle zero-size directory
After repairing a corrupted file system with exfatprogs' fsck.exfat, zero-size directories may result. It is also possible to create zero-size directories in other exFAT implementation, such as Paragon ufsd dirver. As described in the specification, the lower directory size limits is 0 bytes. Without this commit, sub-directories and files cannot be created under a zero-size directory, and it cannot be removed. Signed-off-by: Yuezhang Mo <[email protected]> Reviewed-by: Andy Wu <[email protected]> Reviewed-by: Aoyama Wataru <[email protected]> Signed-off-by: Namjae Jeon <[email protected]>
1 parent 0ab8ba7 commit dab48b8

File tree

1 file changed

+22
-7
lines changed

1 file changed

+22
-7
lines changed

fs/exfat/namei.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -351,14 +351,20 @@ static int exfat_find_empty_entry(struct inode *inode,
351351
if (exfat_check_max_dentries(inode))
352352
return -ENOSPC;
353353

354-
/* we trust p_dir->size regardless of FAT type */
355-
if (exfat_find_last_cluster(sb, p_dir, &last_clu))
356-
return -EIO;
357-
358354
/*
359355
* Allocate new cluster to this directory
360356
*/
361-
exfat_chain_set(&clu, last_clu + 1, 0, p_dir->flags);
357+
if (ei->start_clu != EXFAT_EOF_CLUSTER) {
358+
/* we trust p_dir->size regardless of FAT type */
359+
if (exfat_find_last_cluster(sb, p_dir, &last_clu))
360+
return -EIO;
361+
362+
exfat_chain_set(&clu, last_clu + 1, 0, p_dir->flags);
363+
} else {
364+
/* This directory is empty */
365+
exfat_chain_set(&clu, EXFAT_EOF_CLUSTER, 0,
366+
ALLOC_NO_FAT_CHAIN);
367+
}
362368

363369
/* allocate a cluster */
364370
ret = exfat_alloc_cluster(inode, 1, &clu, IS_DIRSYNC(inode));
@@ -368,6 +374,11 @@ static int exfat_find_empty_entry(struct inode *inode,
368374
if (exfat_zeroed_cluster(inode, clu.dir))
369375
return -EIO;
370376

377+
if (ei->start_clu == EXFAT_EOF_CLUSTER) {
378+
ei->start_clu = clu.dir;
379+
p_dir->dir = clu.dir;
380+
}
381+
371382
/* append to the FAT chain */
372383
if (clu.flags != p_dir->flags) {
373384
/* no-fat-chain bit is disabled,
@@ -646,7 +657,7 @@ static int exfat_find(struct inode *dir, struct qstr *qname,
646657
info->type = exfat_get_entry_type(ep);
647658
info->attr = le16_to_cpu(ep->dentry.file.attr);
648659
info->size = le64_to_cpu(ep2->dentry.stream.valid_size);
649-
if ((info->type == TYPE_FILE) && (info->size == 0)) {
660+
if (info->size == 0) {
650661
info->flags = ALLOC_NO_FAT_CHAIN;
651662
info->start_clu = EXFAT_EOF_CLUSTER;
652663
} else {
@@ -889,6 +900,9 @@ static int exfat_check_dir_empty(struct super_block *sb,
889900

890901
dentries_per_clu = sbi->dentries_per_clu;
891902

903+
if (p_dir->dir == EXFAT_EOF_CLUSTER)
904+
return 0;
905+
892906
exfat_chain_dup(&clu, p_dir);
893907

894908
while (clu.dir != EXFAT_EOF_CLUSTER) {
@@ -1256,7 +1270,8 @@ static int __exfat_rename(struct inode *old_parent_inode,
12561270
}
12571271

12581272
/* Free the clusters if new_inode is a dir(as if exfat_rmdir) */
1259-
if (new_entry_type == TYPE_DIR) {
1273+
if (new_entry_type == TYPE_DIR &&
1274+
new_ei->start_clu != EXFAT_EOF_CLUSTER) {
12601275
/* new_ei, new_clu_to_free */
12611276
struct exfat_chain new_clu_to_free;
12621277

0 commit comments

Comments
 (0)