mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-06 05:13:18 +00:00
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 <Yuezhang.Mo@sony.com> Reviewed-by: Andy Wu <Andy.Wu@sony.com> Reviewed-by: Aoyama Wataru <wataru.aoyama@sony.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
parent
dab48b8f2f
commit
ee785c15b5
@ -418,11 +418,13 @@ static void exfat_set_entry_type(struct exfat_dentry *ep, unsigned int type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void exfat_init_stream_entry(struct exfat_dentry *ep,
|
static void exfat_init_stream_entry(struct exfat_dentry *ep,
|
||||||
unsigned char flags, unsigned int start_clu,
|
unsigned int start_clu, unsigned long long size)
|
||||||
unsigned long long size)
|
|
||||||
{
|
{
|
||||||
exfat_set_entry_type(ep, TYPE_STREAM);
|
exfat_set_entry_type(ep, TYPE_STREAM);
|
||||||
ep->dentry.stream.flags = flags;
|
if (size == 0)
|
||||||
|
ep->dentry.stream.flags = ALLOC_FAT_CHAIN;
|
||||||
|
else
|
||||||
|
ep->dentry.stream.flags = ALLOC_NO_FAT_CHAIN;
|
||||||
ep->dentry.stream.start_clu = cpu_to_le32(start_clu);
|
ep->dentry.stream.start_clu = cpu_to_le32(start_clu);
|
||||||
ep->dentry.stream.valid_size = cpu_to_le64(size);
|
ep->dentry.stream.valid_size = cpu_to_le64(size);
|
||||||
ep->dentry.stream.size = cpu_to_le64(size);
|
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,
|
|||||||
if (!ep)
|
if (!ep)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
exfat_init_stream_entry(ep,
|
exfat_init_stream_entry(ep, start_clu, size);
|
||||||
(type == TYPE_FILE) ? ALLOC_FAT_CHAIN : ALLOC_NO_FAT_CHAIN,
|
|
||||||
start_clu, size);
|
|
||||||
exfat_update_bh(bh, IS_DIRSYNC(inode));
|
exfat_update_bh(bh, IS_DIRSYNC(inode));
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
|
|
||||||
|
@ -234,6 +234,8 @@ struct exfat_mount_options {
|
|||||||
discard:1, /* Issue discard requests on deletions */
|
discard:1, /* Issue discard requests on deletions */
|
||||||
keep_last_dots:1; /* Keep trailing periods in paths */
|
keep_last_dots:1; /* Keep trailing periods in paths */
|
||||||
int time_offset; /* Offset of timestamps from UTC (in minutes) */
|
int time_offset; /* Offset of timestamps from UTC (in minutes) */
|
||||||
|
/* Support creating zero-size directory, default: false */
|
||||||
|
bool zero_size_dir;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -518,7 +518,7 @@ static int exfat_add_entry(struct inode *inode, const char *path,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == TYPE_DIR) {
|
if (type == TYPE_DIR && !sbi->options.zero_size_dir) {
|
||||||
ret = exfat_alloc_new_dir(inode, &clu);
|
ret = exfat_alloc_new_dir(inode, &clu);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
@ -551,7 +551,10 @@ static int exfat_add_entry(struct inode *inode, const char *path,
|
|||||||
info->num_subdirs = 0;
|
info->num_subdirs = 0;
|
||||||
} else {
|
} else {
|
||||||
info->attr = EXFAT_ATTR_SUBDIR;
|
info->attr = EXFAT_ATTR_SUBDIR;
|
||||||
info->start_clu = start_clu;
|
if (sbi->options.zero_size_dir)
|
||||||
|
info->start_clu = EXFAT_EOF_CLUSTER;
|
||||||
|
else
|
||||||
|
info->start_clu = start_clu;
|
||||||
info->size = clu_size;
|
info->size = clu_size;
|
||||||
info->num_subdirs = EXFAT_MIN_SUBDIR;
|
info->num_subdirs = EXFAT_MIN_SUBDIR;
|
||||||
}
|
}
|
||||||
|
@ -165,6 +165,8 @@ static int exfat_show_options(struct seq_file *m, struct dentry *root)
|
|||||||
seq_puts(m, ",sys_tz");
|
seq_puts(m, ",sys_tz");
|
||||||
else if (opts->time_offset)
|
else if (opts->time_offset)
|
||||||
seq_printf(m, ",time_offset=%d", opts->time_offset);
|
seq_printf(m, ",time_offset=%d", opts->time_offset);
|
||||||
|
if (opts->zero_size_dir)
|
||||||
|
seq_puts(m, ",zero_size_dir");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,6 +211,7 @@ enum {
|
|||||||
Opt_keep_last_dots,
|
Opt_keep_last_dots,
|
||||||
Opt_sys_tz,
|
Opt_sys_tz,
|
||||||
Opt_time_offset,
|
Opt_time_offset,
|
||||||
|
Opt_zero_size_dir,
|
||||||
|
|
||||||
/* Deprecated options */
|
/* Deprecated options */
|
||||||
Opt_utf8,
|
Opt_utf8,
|
||||||
@ -237,6 +240,7 @@ static const struct fs_parameter_spec exfat_parameters[] = {
|
|||||||
fsparam_flag("keep_last_dots", Opt_keep_last_dots),
|
fsparam_flag("keep_last_dots", Opt_keep_last_dots),
|
||||||
fsparam_flag("sys_tz", Opt_sys_tz),
|
fsparam_flag("sys_tz", Opt_sys_tz),
|
||||||
fsparam_s32("time_offset", Opt_time_offset),
|
fsparam_s32("time_offset", Opt_time_offset),
|
||||||
|
fsparam_flag("zero_size_dir", Opt_zero_size_dir),
|
||||||
__fsparam(NULL, "utf8", Opt_utf8, fs_param_deprecated,
|
__fsparam(NULL, "utf8", Opt_utf8, fs_param_deprecated,
|
||||||
NULL),
|
NULL),
|
||||||
__fsparam(NULL, "debug", Opt_debug, fs_param_deprecated,
|
__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)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
opts->time_offset = result.int_32;
|
opts->time_offset = result.int_32;
|
||||||
break;
|
break;
|
||||||
|
case Opt_zero_size_dir:
|
||||||
|
opts->zero_size_dir = true;
|
||||||
|
break;
|
||||||
case Opt_utf8:
|
case Opt_utf8:
|
||||||
case Opt_debug:
|
case Opt_debug:
|
||||||
case Opt_namecase:
|
case Opt_namecase:
|
||||||
|
Loading…
Reference in New Issue
Block a user