]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
New mke2fs filesystem and usage types support
authorTheodore Ts'o <tytso@mit.edu>
Tue, 19 Feb 2008 13:32:58 +0000 (08:32 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Sun, 6 Apr 2008 21:15:38 +0000 (17:15 -0400)
Provide mke2fs with a much more sophisticated system for controlling
configuration parameters of a newly created filesystem based on a
split filesystem and usage type system.  The -t option to mke2fs was a
deprecated alias to -c; it now specifies a filesystem type (ext2,
ext3, ext4, etc.), while the -T option can now be a comma separated
usage list.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
misc/mke2fs.8.in
misc/mke2fs.c
misc/mke2fs.conf
misc/mke2fs.conf.5.in
tests/Makefile.in
tests/test_config

index 6cd10b1da7f3c3cf3065867b8af75ca3dbd584f5..4f60bb2eab1c399d1b055ac2462f8be59aebe4dd 100644 (file)
@@ -88,8 +88,12 @@ mke2fs \- create an ext2/ext3 filesystem
 .B \-S
 ]
 [
+.B \-t
+.I fs-type
+]
+[
 .B \-T
-.I filesystem-type
+.I usage-type
 ]
 [
 .B \-V
@@ -384,19 +388,26 @@ executable.
 .TP
 .B "\-O \fIfeature\fR[,...]"
 Create filesystem with given features (filesystem options), overriding 
-the default filesystem options.  The default features which are 
+the default filesystem options.  The default features which are
 enabled by default are specified by the
 .I base_features
 relation, either in the
 .I [libdefaults]
 section in the
 .B /etc/mke2fs.conf
-configuration file, or in the subsection of the 
+configuration file,
+or in the subsection of the
 .I [fs_types]
-section for the filesystem type as specified by the
+section for the usage types as specified by the
 .B -T
-option.  The filesystem type-specific configuration setting found in
-the 
+option, further modified by the
+.I features
+relation found in the
+.I [fs_types] section
+based on the filesystem and usage types.  See the
+.BR mke2fs.conf (5)
+manual page for more details.
+The filesystem type-specific configuration setting found in the
 .I [fs_types]
 section will override the global default found in
 .IR [libdefaults] .
@@ -490,14 +501,40 @@ or there is no chance of recovery.
 .\" Check the device for bad blocks before creating the file system
 .\" using the specified test.
 .TP
-.BI \-T " fs-type"
+.BI
+.BI \-t " fs-type"
+Specify the filesystem (i.e., ext2, ext3, ext4, etc., is to be created.
+If this option is not specified mke2fs will pick a default either how
+the command was run (if it was run using a name of the form mkfs.ext2,
+mkfs.ext3, etc.) or via a default as defined by the
+.BR /etc/mke2fs.conf (5)
+file.
+.TP
+.BI \-T " usage-type[,...]"
 Specify how the filesystem is going to be used, so that 
 .B mke2fs 
-can choose optimal filesystem parameters for that use.  The filesystem
-types that are can be supported are defined in the configuration file 
+can choose optimal filesystem parameters for that use.  The usage
+types that are supported are defined in the configuration file
 .BR /etc/mke2fs.conf (5).
-The default configuration file contains definitions for the filesystem
-types: small, floppy, news, largefile, and largefile4.  
+The user may specify one or more usage types
+using a comma separated list.
+.sp
+If this option is is not specified,
+.B mke2fs
+will pick a single default usage type based on the size of the filesystem to
+be created.  If the filesystem size is less than or equal to 3 megabytes,
+.BR mke2fs (8)
+will use the filesystem type
+.IR floppy .
+If the filesystem size is greater than 3 but less than or equal to
+512 megabytes,
+.BR mke2fs (8)
+will use the filesystem
+.IR small .
+Otherwise,
+.BR mke2fs (8)
+will use the default filesystem type
+.IR default .
 .TP
 .B \-v
 Verbose execution.
index fd48b83563b2980990534e617ff615409ac971d1..a58b1165206e870628ff40f1c3e8f74a91c79dba 100644 (file)
@@ -956,6 +956,171 @@ static void edit_feature(const char *str, __u32 *compat_array)
        }
 }
 
+struct str_list {
+       char **list;
+       int num;
+       int max;
+};
+
+static errcode_t init_list(struct str_list *sl)
+{
+       sl->num = 0;
+       sl->max = 0;
+       sl->list = malloc((sl->max+1) * sizeof(char *));
+       if (!sl->list)
+               return ENOMEM;
+       sl->list[0] = 0;
+       return 0;
+}
+
+static errcode_t push_string(struct str_list *sl, const char *str)
+{
+       char **new_list;
+
+       if (sl->num >= sl->max) {
+               sl->max += 2;
+               new_list = realloc(sl->list, (sl->max+1) * sizeof(char *));
+               if (!new_list)
+                       return ENOMEM;
+               sl->list = new_list;
+       }
+       sl->list[sl->num] = malloc(strlen(str)+1);
+       if (sl->list[sl->num] == 0)
+               return ENOMEM;
+       strcpy(sl->list[sl->num], str);
+       sl->num++;
+       sl->list[sl->num] = 0;
+       return 0;
+}
+
+static void print_str_list(char **list)
+{
+       char **cpp;
+
+       for (cpp = list; *cpp; cpp++) {
+               printf("'%s'", *cpp);
+               if (cpp[1])
+                       fputs(", ", stdout);
+       }
+       fputc('\n', stdout);
+}
+
+static char **parse_fs_type(const char *fs_type,
+                           const char *usage_types,
+                           struct ext2_super_block *fs_param,
+                           char *progname)
+{
+       const char      *ext_type = 0;
+       char            *parse_str;
+       char            *profile_type = 0;
+       char            *cp, *t;
+       const char      *size_type;
+       struct str_list list;
+       int             state = 0;
+       unsigned long   meg;
+
+       if (init_list(&list))
+               return 0;
+
+       if (fs_type)
+               ext_type = fs_type;
+       else if (progname) {
+               ext_type = strrchr(progname, '/');
+               if (ext_type)
+                       ext_type++;
+               else
+                       ext_type = progname;
+
+               if (!strncmp(ext_type, "mkfs.", 5)) {
+                       ext_type += 5;
+                       if (ext_type[0] == 0)
+                               ext_type = 0;
+               } else
+                       ext_type = 0;
+       }
+
+       if (!ext_type) {
+               profile_get_string(profile, "defaults", "fs_type", 0,
+                                  "ext2", &profile_type);
+               ext_type = profile_type;
+               if (!strcmp(ext_type, "ext2") && (journal_size != 0))
+                       ext_type = "ext3";
+       }
+
+       meg = (1024 * 1024) / EXT2_BLOCK_SIZE(fs_param);
+       if (fs_param->s_blocks_count < 3 * meg)
+               size_type = "floppy";
+       else if (fs_param->s_blocks_count < 512 * meg)
+               size_type = "small";
+       else
+               size_type = "default";
+
+       if (!usage_types)
+               usage_types = size_type;
+
+       parse_str = malloc(usage_types ? strlen(usage_types)+1 : 1);
+       if (!parse_str) {
+               free(list.list);
+               return 0;
+       }
+       if (usage_types)
+               strcpy(parse_str, usage_types);
+       else
+               *parse_str = '\0';
+
+       if (ext_type)
+               push_string(&list, ext_type);
+       cp = parse_str;
+       while (1) {
+               t = strchr(cp, ',');
+               if (t)
+                       *t = '\0';
+
+               if (*cp)
+                       push_string(&list, cp);
+               if (t)
+                       cp = t+1;
+               else {
+                       cp = "";
+                       break;
+               }
+       }
+       free(parse_str);
+       if (profile_type)
+               free(profile_type);
+       return (list.list);
+}
+
+static char *get_string_from_profile(char **fs_types, const char *opt,
+                                    const char *def_val)
+{
+       char *ret = 0;
+       char **cpp;
+       int i;
+
+       for (i=0; fs_types[i]; i++);
+       for (i-=1; i >=0 ; i--) {
+               profile_get_string(profile, "fs_types", fs_types[i],
+                                  opt, 0, &ret);
+               if (ret)
+                       return ret;
+       }
+       profile_get_string(profile, "defaults", opt, 0, def_val, &ret);
+       return (ret);
+}
+
+static int get_int_from_profile(char **fs_types, const char *opt, int def_val)
+{
+       int ret;
+       char **cpp;
+
+       profile_get_integer(profile, "defaults", opt, 0, def_val, &ret);
+       for (cpp = fs_types; *cpp; cpp++)
+               profile_get_integer(profile, "fs_types", *cpp, opt, ret, &ret);
+       return ret;
+}
+
+
 extern const char *mke2fs_default_profile;
 static const char *default_files[] = { "<default>", 0 };
 
@@ -975,6 +1140,8 @@ static void PRS(int argc, char *argv[])
        char *          oldpath = getenv("PATH");
        char *          extended_opts = 0;
        const char *    fs_type = 0;
+       const char *    usage_types = 0;
+       char            **fs_types;
        blk_t           dev_size;
 #ifdef __linux__
        struct          utsname ut;
@@ -1049,7 +1216,7 @@ static void PRS(int argc, char *argv[])
        }
 
        while ((c = getopt (argc, argv,
-                   "b:cf:g:i:jl:m:no:qr:s:tvE:FI:J:L:M:N:O:R:ST:V")) != EOF) {
+                   "b:cf:g:i:jl:m:no:qr:s:t:vE:FI:J:L:M:N:O:R:ST:V")) != EOF) {
                switch (c) {
                case 'b':
                        blocksize = strtol(optarg, &tmp, 0);
@@ -1070,7 +1237,6 @@ static void PRS(int argc, char *argv[])
                                                 EXT2_MIN_BLOCK_LOG_SIZE);
                        break;
                case 'c':       /* Check for bad blocks */
-               case 't':       /* deprecated */
                        cflag++;
                        break;
                case 'f':
@@ -1196,9 +1362,12 @@ static void PRS(int argc, char *argv[])
                case 'S':
                        super_only = 1;
                        break;
-               case 'T':
+               case 't':
                        fs_type = optarg;
                        break;
+               case 'T':
+                       usage_types = optarg;
+                       break;
                case 'V':
                        /* Print version number and exit */
                        show_version_only++;
@@ -1340,6 +1509,16 @@ static void PRS(int argc, char *argv[])
                proceed_question();
        }
 
+       fs_types = parse_fs_type(fs_type, usage_types, &fs_param, argv[0]);
+       if (!fs_types) {
+               fprintf(stderr, _("Failed to parse fs types list\n"));
+               exit(1);
+       }
+       if (verbose) {
+               fputs("Fs_types for mke2fs.conf resolution: ", stdout);
+               print_str_list(fs_types);
+       }
+
        if (!fs_type) {
                int megs = (__u64)fs_param.s_blocks_count *
                        (EXT2_BLOCK_SIZE(&fs_param) / 1024) / 1024;
@@ -1357,29 +1536,31 @@ static void PRS(int argc, char *argv[])
 
        /* Figure out what features should be enabled */
 
-       tmp = tmp2 = NULL;
+       tmp = NULL;
        if (fs_param.s_rev_level != EXT2_GOOD_OLD_REV) {
-               profile_get_string(profile, "defaults", "base_features", 0,
-                                  "sparse_super,filetype,resize_inode,dir_index",
-                                  &tmp);
-               profile_get_string(profile, "fs_types", fs_type, 
-                                  "base_features", tmp, &tmp2);
-               edit_feature(tmp2, &fs_param.s_feature_compat);
+               char **cpp;
+
+               tmp = get_string_from_profile(fs_types, "base_features",
+                     "sparse_super,filetype,resize_inode,dir_index");
+               edit_feature(tmp, &fs_param.s_feature_compat);
                free(tmp);
-               free(tmp2);
 
-               tmp = tmp2 = NULL;
-               profile_get_string(profile, "defaults", "default_features", 0,
-                                  "", &tmp);
-               profile_get_string(profile, "fs_types", fs_type, 
-                                  "default_features", tmp, &tmp2);
+               for (cpp = fs_types; *cpp; cpp++) {
+                       tmp = NULL;
+                       profile_get_string(profile, "fs_types", *cpp,
+                                          "features", "", &tmp);
+                       if (tmp && *tmp)
+                               edit_feature(tmp, &fs_param.s_feature_compat);
+                       if (tmp)
+                               free(tmp);
+               }
+               tmp = get_string_from_profile(fs_types, "default_features",
+                                             "");
        }
-       edit_feature(fs_features ? fs_features : tmp2, 
+       edit_feature(fs_features ? fs_features : tmp,
                     &fs_param.s_feature_compat);
        if (tmp)
                free(tmp);
-       if (tmp2)
-               free(tmp2);
 
        if (r_opt == EXT2_GOOD_OLD_REV && 
            (fs_param.s_feature_compat || fs_param.s_feature_incompat ||
@@ -1437,10 +1618,7 @@ static void PRS(int argc, char *argv[])
                sector_size = atoi(tmp);
        
        if (blocksize <= 0) {
-               profile_get_integer(profile, "defaults", "blocksize", 0,
-                                   4096, &use_bsize);
-               profile_get_integer(profile, "fs_types", fs_type, 
-                                   "blocksize", use_bsize, &use_bsize);
+               use_bsize = get_int_from_profile(fs_types, "blocksize", 4096);
 
                if (use_bsize == -1) {
                        use_bsize = sys_page_size;
@@ -1457,12 +1635,8 @@ static void PRS(int argc, char *argv[])
        }
 
        if (inode_ratio == 0) {
-               profile_get_integer(profile, "defaults", "inode_ratio", 0,
-                                   8192, &inode_ratio);
-               profile_get_integer(profile, "fs_types", fs_type, 
-                                   "inode_ratio", inode_ratio, 
-                                   &inode_ratio);
-
+               inode_ratio = get_int_from_profile(fs_types, "inode_ratio",
+                                                  8192);
                if (inode_ratio < blocksize)
                        inode_ratio = blocksize;
        }
@@ -1495,13 +1669,8 @@ static void PRS(int argc, char *argv[])
                }
        }
 
-       if (inode_size == 0) {
-               profile_get_integer(profile, "defaults", "inode_size", NULL,
-                                   0, &inode_size);
-               profile_get_integer(profile, "fs_types", fs_type,
-                                   "inode_size", inode_size,
-                                   &inode_size);
-       }
+       if (inode_size == 0)
+               inode_size = get_int_from_profile(fs_types, "inode_size", 0);
 
        if (inode_size && fs_param.s_rev_level >= EXT2_DYNAMIC_REV) {
                if (inode_size < EXT2_GOOD_OLD_INODE_SIZE ||
@@ -1816,5 +1985,6 @@ no_journal:
        val = ext2fs_close(fs);
        remove_error_table(&et_ext2_error_table);
        remove_error_table(&et_prof_error_table);
+       profile_release(profile);
        return (retval || val) ? 1 : 0;
 }
index d67593a07f00f25e121203d7812623176413e231..b5df30efd9f9d4fc9a2b82d05c1bf8ffa19de2d3 100644 (file)
@@ -5,6 +5,13 @@
        inode_ratio = 16384
 
 [fs_types]
+       ext3 = {
+               features = has_journal
+       }
+       ext4 = {
+               features = has_journal,extents,flex_bg
+               inode_size = 256
+       }
        small = {
                blocksize = 1024
                inode_size = 128
@@ -20,7 +27,9 @@
        }
        largefile = {
                inode_ratio = 1048576
+               blocksize = -1
        }
        largefile4 = {
                inode_ratio = 4194304
+               blocksize = -1
        }
index 608903130baf841ad677ba652fb05c8105474e1b..1fc16e720c1cd2ee524556f8535a1d5f36dec5bb 100644 (file)
@@ -79,20 +79,6 @@ the
 .B -T
 option to
 .BR mke2fs (8).
-If no filesystem type is specified, 
-.BR mke2fs (8)
-will use the filesystem type 
-.I floppy
-if the filesystem size is less than or equal to 3 megabytes.  
-If the filesystem size is greater than 3 but less than or equal to 
-512 megabytes, 
-.BR mke2fs (8)
-will use the filesystem
-.IR small .
-Otherwise, 
-.BR mke2fs (8)
-will use the default filesystem type
-.IR default .
 .SH THE [defaults] STANZA
 The following relations are defined in the 
 .I [defaults]
@@ -102,7 +88,7 @@ stanza.
 This relation specifies the filesystems features which are enabled in
 newly created filesystems.  It may be overridden by the
 .I base_features
-relation found in the filesystem-type-specific subsection of
+relation found in the filesystem or usage type subsection of
 the
 .I [fs_types] 
 stanza.
@@ -113,7 +99,7 @@ removed to the features listed in the
 .I base_features
 relation.  It may be overridden by the filesystem-specific 
 .I default_features
-in the filesystem-type subsection of
+in the filesystem or usage type subsection of
 .IR [fs_types] ,
 and by the 
 .B -O
@@ -121,6 +107,23 @@ command-line option
 to 
 .BR mke2fs (8).
 .TP
+.I fs_type
+This relation specifies the default filesystem type if the user does not
+specify it via the
+.B \-t
+option, or if
+.B mke2fs
+is not started using a program name of the form
+.BI mkfs. fs-type\fR.
+If both the user and the
+.B mke2fs.conf
+file does not specify a default filesystem type, mke2fs will use a
+default filesystem type of
+.IR ext3
+if a journal was requested via a command-line option, or
+.I ext2
+if not.
+.TP
 .I blocksize
 This relation specifies the default blocksize if the user does not
 specify a blocksize on the command line, and the filesystem-type
@@ -140,15 +143,56 @@ inode size.
 .SH THE [fs_types] STANZA
 Each tag in the
 .I [fs_types] 
-stanza names a filesystem type which can be specified via the 
-.B -T
-option to
-.BR mke2fs (8).
-The value of the tag is a subsection where the relations in that
-subsection define the defaults for that filesystem type. For
-example:
+stanza names a filesystem type or usage type which can be specified via the
+.B \-t
+or
+.B \-T
+options to
+.BR mke2fs (8),
+respectively.
+.P
+The
+.B mke2fs
+program constructs a list of fs_types by concatenating the filesystem
+type (i.e., ext2, ext3, etc.) with the usage type list.  For most
+configuration options,
+.B mke2fs
+will look for a subsection in the
+.I [fs_types]
+stanza corresponding with each entry in the constructed list, with later
+entries overriding earlier filesystem or usage types.
+For
+example, consider the following
+.B mke2fs.conf
+fragment:
 .P
+[defaults]
+.br
+       base_features = sparse_super,filetype,resize_inode,dir_index
+.br
+       blocksize = 4096
+.br
+       inode_size = 256
+.br
+       inode_ratio = 16384
+.br
+
+.br
 [fs_types]
+.br
+       ext3 = {
+.br
+               features = has_journal
+.br
+       }
+.br
+       ext4 = {
+.br
+               features = extents,flex_bg
+.br
+               inode_size = 256
+.br
+       }
 .br
        small = {
 .br
@@ -159,23 +203,77 @@ example:
        }
 .br
        floppy = {
+.br
+               features = ^resize_inode
 .br
                blocksize = 1024
+.br
+               inode_size = 128
 .br
        }
 .P
+If mke2fs started with a program name of
+.BR mke2fs.ext4 ,
+then the filesystem type of ext4 will be used.  If the filesystem is
+smaller than 3 megabytes, and no usage type is specified, then
+.B mke2fs
+will use a default
+usage type of
+.IR floppy .
+This results in an fs_types list of "ext4, floppy".   Both the ext4
+subsection and the floppy subsection define an
+.I inode_size
+relation, but since the later entries in the fs_types list supercede
+earlier ones, the configuration parameter for fs_types.floppy.inode_size
+will be used, so the filesystem  will have an inode size of 128.
+.P
+The exception to this resolution is the
+.I features
+tag, which is specifies a set of changes to the features used by the
+filesystem, and which is cumulative.  So in the above example, first
+the configuration relation defaults.base_features would enable an
+initial feature set with the sparse_super, filetype, resize_inode, and
+dir_index features enabled.  Then configuration relation
+fs_types.ext4.features would enable the extents and flex_bg
+features, and finally the configuration relation
+fs_types.floppy.features would remove
+the resize_inode feature, resulting in a filesystem feature set
+consisting of the sparse_super, filetype, resize_inode, dir_index,
+extents_and flex_bg features.
+.P
 For each filesystem type, the following tags may be used in that 
 fs_type's subsection:
 .TP
 .I base_features
-This relation specifies the features which are enabled for this
-filesystem type.
+This relation specifies the features which are initially enabled for this
+filesystem type.  Only one
+.I base_features
+will be used, so if there are multiple entries in the fs_types list
+whose subsections define the
+.I base_features
+relation, only the last will be used by
+.BR mke2fs (8).
+.TP
+.I features
+This relation specifies a comma-separated list of features edit
+requests which modify the feature set
+used by the newly constructed filesystem.  The syntax is the same as the
+.B -O
+command-line option to
+.BR mke2fs (8);
+that is, a feature can be prefixed by a caret ('^') symbol to disable
+a named feature.  Each
+.I feature
+relation specified in the fs_types list will be applied in the order
+found in the fs_types list.
 .TP
 .I default_features
 This relation specifies set of features which should be enabled or 
-disabled to the features listed in the
+disabled after applying the features listed in the
 .I base_features
-relation.  It may be overridden by the 
+and
+.I features
+relations.  It may be overridden by the
 .B -O
 command-line option to
 .BR mke2fs (8).
index f9d5d781c98359379ab0eefbed4f514ea07b8aeb..2c3ac76e6e7bbc28ec4ee5791d130cabd98cb290 100644 (file)
@@ -13,7 +13,7 @@ INSTALL = @INSTALL@
 
 all:: @DO_TEST_SUITE@
 
-test_script: test_script.in Makefile
+test_script: test_script.in Makefile mke2fs.conf
        @echo "Creating test_script..."
        @echo "#!/bin/sh" > test_script
 @HTREE_CMT@    @echo "HTREE=y" >> test_script
@@ -23,6 +23,9 @@ test_script: test_script.in Makefile
        @cat $(srcdir)/test_script.in >> test_script
        @chmod +x test_script
 
+mke2fs.conf: $(srcdir)/../misc/mke2fs.conf
+       sed -e 's/blocksize = -1/blocksize = 4096/' $< >mke2fs.conf
+
 check:: test_script
        @echo "Running e2fsprogs test suite..."
        @echo " "
@@ -63,7 +66,7 @@ testend: test_script ${TDIR}/image
        @echo "If all is well, edit ${TDIR}/name and rename ${TDIR}."
 
 clean::
-       $(RM) -f *~ *.log *.new *.failed *.ok test.img test_script
+       $(RM) -f *~ *.log *.new *.failed *.ok test.img test_script mke2fs.conf
 
 distclean:: clean
        $(RM) -f Makefile
index f5ae0fe7f9f572ce7a2698a53855e995f60af318..73137249727e462577b267c6aad3c9d37aa71f47 100644 (file)
@@ -26,6 +26,6 @@ LC_ALL=C
 export LC_ALL
 E2FSCK_CONFIG=/dev/null
 export E2FSCK_CONFIG
-MKE2FS_CONFIG=$SRCDIR/../misc/mke2fs.conf
+MKE2FS_CONFIG=./mke2fs.conf
 export MKE2FS_CONFIG