]> Git Repo - linux.git/commitdiff
exfat: support create zero-size directory
authorYuezhang Mo <[email protected]>
Thu, 20 Jul 2023 06:40:08 +0000 (14:40 +0800)
committerNamjae Jeon <[email protected]>
Tue, 31 Oct 2023 01:01:45 +0000 (10:01 +0900)
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]>
fs/exfat/dir.c
fs/exfat/exfat_fs.h
fs/exfat/namei.c
fs/exfat/super.c

index fdd46aa466e1295b6603744741b19f6b7d2e0668..9f9295847a4e6ecfd02fe3662b82e9f80479ada8 100644 (file)
@@ -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);
 
index 99208902883bad4dcadc445e457e9c328d3e6993..a7a2c35d74fbd70ac5980e780840cadd43385316 100644 (file)
@@ -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;
 };
 
 /*
index 1e9c945130f4c0304e461503d37f0fa3b8b7d83e..5d737e0b639a14747ac6ba15f1cdd72163818c2a 100644 (file)
@@ -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,7 +551,10 @@ static int exfat_add_entry(struct inode *inode, const char *path,
                info->num_subdirs = 0;
        } else {
                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->num_subdirs = EXFAT_MIN_SUBDIR;
        }
index ecee1664ab7f650ec34ef184d078ab4708b7442c..d9d4fa91010bb1d226b1d00afdbb841e73911d33 100644 (file)
@@ -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:
This page took 0.0638 seconds and 4 git commands to generate.