Commit ee785c15 authored by Yuezhang Mo's avatar Yuezhang Mo Committed by Namjae Jeon
Browse files

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: default avatarYuezhang Mo <Yuezhang.Mo@sony.com>
Reviewed-by: default avatarAndy Wu <Andy.Wu@sony.com>
Reviewed-by: default avatarAoyama Wataru <wataru.aoyama@sony.com>
Signed-off-by: default avatarNamjae Jeon <linkinjeon@kernel.org>
parent dab48b8f
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -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,
		unsigned char flags, unsigned int start_clu,
		unsigned long long size)
		unsigned int start_clu, unsigned long long size)
{
	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.valid_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)
		return -EIO;

	exfat_init_stream_entry(ep,
		(type == TYPE_FILE) ? ALLOC_FAT_CHAIN : ALLOC_NO_FAT_CHAIN,
		start_clu, size);
	exfat_init_stream_entry(ep, start_clu, size);
	exfat_update_bh(bh, IS_DIRSYNC(inode));
	brelse(bh);

+2 −0
Original line number Diff line number Diff line
@@ -234,6 +234,8 @@ struct exfat_mount_options {
		 discard:1, /* Issue discard requests on deletions */
		 keep_last_dots:1; /* Keep trailing periods in paths */
	int time_offset; /* Offset of timestamps from UTC (in minutes) */
	/* Support creating zero-size directory, default: false */
	bool zero_size_dir;
};

/*
+5 −2
Original line number Diff line number Diff line
@@ -518,7 +518,7 @@ static int exfat_add_entry(struct inode *inode, const char *path,
		goto out;
	}

	if (type == TYPE_DIR) {
	if (type == TYPE_DIR && !sbi->options.zero_size_dir) {
		ret = exfat_alloc_new_dir(inode, &clu);
		if (ret)
			goto out;
@@ -551,6 +551,9 @@ static int exfat_add_entry(struct inode *inode, const char *path,
		info->num_subdirs = 0;
	} else {
		info->attr = EXFAT_ATTR_SUBDIR;
		if (sbi->options.zero_size_dir)
			info->start_clu = EXFAT_EOF_CLUSTER;
		else
			info->start_clu = start_clu;
		info->size = clu_size;
		info->num_subdirs = EXFAT_MIN_SUBDIR;
+7 −0
Original line number Diff line number Diff line
@@ -165,6 +165,8 @@ static int exfat_show_options(struct seq_file *m, struct dentry *root)
		seq_puts(m, ",sys_tz");
	else if (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;
}

@@ -209,6 +211,7 @@ enum {
	Opt_keep_last_dots,
	Opt_sys_tz,
	Opt_time_offset,
	Opt_zero_size_dir,

	/* Deprecated options */
	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("sys_tz",			Opt_sys_tz),
	fsparam_s32("time_offset",		Opt_time_offset),
	fsparam_flag("zero_size_dir",		Opt_zero_size_dir),
	__fsparam(NULL, "utf8",			Opt_utf8, fs_param_deprecated,
		  NULL),
	__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;
		opts->time_offset = result.int_32;
		break;
	case Opt_zero_size_dir:
		opts->zero_size_dir = true;
		break;
	case Opt_utf8:
	case Opt_debug:
	case Opt_namecase: