Skip to content

Commit ee785c1

Browse files
YuezhangMonamjaejeon
authored andcommitted
exfat: support create zero-size directory
This commit adds mount option 'zero_size_dir'. If this option enabled, don't allocate a cluster to directory when creating it, and set the directory size to 0. On Windows, a cluster is allocated for a directory when it is created, so the mount option is disabled by default. 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 dab48b8 commit ee785c1

File tree

4 files changed

+20
-8
lines changed

4 files changed

+20
-8
lines changed

fs/exfat/dir.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -418,11 +418,13 @@ static void exfat_set_entry_type(struct exfat_dentry *ep, unsigned int type)
418418
}
419419

420420
static void exfat_init_stream_entry(struct exfat_dentry *ep,
421-
unsigned char flags, unsigned int start_clu,
422-
unsigned long long size)
421+
unsigned int start_clu, unsigned long long size)
423422
{
424423
exfat_set_entry_type(ep, TYPE_STREAM);
425-
ep->dentry.stream.flags = flags;
424+
if (size == 0)
425+
ep->dentry.stream.flags = ALLOC_FAT_CHAIN;
426+
else
427+
ep->dentry.stream.flags = ALLOC_NO_FAT_CHAIN;
426428
ep->dentry.stream.start_clu = cpu_to_le32(start_clu);
427429
ep->dentry.stream.valid_size = cpu_to_le64(size);
428430
ep->dentry.stream.size = cpu_to_le64(size);
@@ -488,9 +490,7 @@ int exfat_init_dir_entry(struct inode *inode, struct exfat_chain *p_dir,
488490
if (!ep)
489491
return -EIO;
490492

491-
exfat_init_stream_entry(ep,
492-
(type == TYPE_FILE) ? ALLOC_FAT_CHAIN : ALLOC_NO_FAT_CHAIN,
493-
start_clu, size);
493+
exfat_init_stream_entry(ep, start_clu, size);
494494
exfat_update_bh(bh, IS_DIRSYNC(inode));
495495
brelse(bh);
496496

fs/exfat/exfat_fs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,8 @@ struct exfat_mount_options {
234234
discard:1, /* Issue discard requests on deletions */
235235
keep_last_dots:1; /* Keep trailing periods in paths */
236236
int time_offset; /* Offset of timestamps from UTC (in minutes) */
237+
/* Support creating zero-size directory, default: false */
238+
bool zero_size_dir;
237239
};
238240

239241
/*

fs/exfat/namei.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ static int exfat_add_entry(struct inode *inode, const char *path,
518518
goto out;
519519
}
520520

521-
if (type == TYPE_DIR) {
521+
if (type == TYPE_DIR && !sbi->options.zero_size_dir) {
522522
ret = exfat_alloc_new_dir(inode, &clu);
523523
if (ret)
524524
goto out;
@@ -551,7 +551,10 @@ static int exfat_add_entry(struct inode *inode, const char *path,
551551
info->num_subdirs = 0;
552552
} else {
553553
info->attr = EXFAT_ATTR_SUBDIR;
554-
info->start_clu = start_clu;
554+
if (sbi->options.zero_size_dir)
555+
info->start_clu = EXFAT_EOF_CLUSTER;
556+
else
557+
info->start_clu = start_clu;
555558
info->size = clu_size;
556559
info->num_subdirs = EXFAT_MIN_SUBDIR;
557560
}

fs/exfat/super.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ static int exfat_show_options(struct seq_file *m, struct dentry *root)
165165
seq_puts(m, ",sys_tz");
166166
else if (opts->time_offset)
167167
seq_printf(m, ",time_offset=%d", opts->time_offset);
168+
if (opts->zero_size_dir)
169+
seq_puts(m, ",zero_size_dir");
168170
return 0;
169171
}
170172

@@ -209,6 +211,7 @@ enum {
209211
Opt_keep_last_dots,
210212
Opt_sys_tz,
211213
Opt_time_offset,
214+
Opt_zero_size_dir,
212215

213216
/* Deprecated options */
214217
Opt_utf8,
@@ -237,6 +240,7 @@ static const struct fs_parameter_spec exfat_parameters[] = {
237240
fsparam_flag("keep_last_dots", Opt_keep_last_dots),
238241
fsparam_flag("sys_tz", Opt_sys_tz),
239242
fsparam_s32("time_offset", Opt_time_offset),
243+
fsparam_flag("zero_size_dir", Opt_zero_size_dir),
240244
__fsparam(NULL, "utf8", Opt_utf8, fs_param_deprecated,
241245
NULL),
242246
__fsparam(NULL, "debug", Opt_debug, fs_param_deprecated,
@@ -305,6 +309,9 @@ static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param)
305309
return -EINVAL;
306310
opts->time_offset = result.int_32;
307311
break;
312+
case Opt_zero_size_dir:
313+
opts->zero_size_dir = true;
314+
break;
308315
case Opt_utf8:
309316
case Opt_debug:
310317
case Opt_namecase:

0 commit comments

Comments
 (0)