Whamcloud - gitweb
e2fsck: track errors/badness found for each inode
[tools/e2fsprogs.git] / misc / mke2fs.c
index ff5d54b..7ec8cc2 100644 (file)
@@ -18,6 +18,7 @@
 
 #define _XOPEN_SOURCE 600 /* for inclusion of PATH_MAX in Solaris */
 
+#include "config.h"
 #include <stdio.h>
 #include <string.h>
 #include <strings.h>
@@ -42,9 +43,6 @@ extern int optind;
 #ifdef HAVE_ERRNO_H
 #include <errno.h>
 #endif
-#ifdef HAVE_MNTENT_H
-#include <mntent.h>
-#endif
 #include <sys/ioctl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -87,6 +85,7 @@ int   verbose;
 int    quiet;
 int    super_only;
 int    discard = 1;    /* attempt to discard device before fs creation */
+int    direct_io;
 int    force;
 int    noaction;
 int    journal_size;
@@ -94,6 +93,7 @@ int   journal_flags;
 int    lazy_itable_init;
 char   *bad_blocks_filename;
 __u32  fs_stride;
+int    quotatype = -1;  /* Initialize both user and group quotas by default */
 
 struct ext2_super_block fs_param;
 char *fs_uuid = NULL;
@@ -112,14 +112,15 @@ int linux_version_code = 0;
 static void usage(void)
 {
        fprintf(stderr, _("Usage: %s [-c|-l filename] [-b block-size] "
-       "[-f fragment-size]\n\t[-i bytes-per-inode] [-I inode-size] "
+       "[-C cluster-size]\n\t[-i bytes-per-inode] [-I inode-size] "
        "[-J journal-options]\n"
-       "\t[-G meta group size] [-N number-of-inodes]\n"
+       "\t[-G flex-group-size] [-N number-of-inodes]\n"
        "\t[-m reserved-blocks-percentage] [-o creator-os]\n"
        "\t[-g blocks-per-group] [-L volume-label] "
        "[-M last-mounted-directory]\n\t[-O feature[,...]] "
        "[-r fs-revision] [-E extended-option[,...]]\n"
-       "\t[-T fs-type] [-U UUID] [-jnqvFKSV] device [blocks-count]\n"),
+       "\t[-t fs-type] [-T usage-type ] [-U UUID] "
+       "[-jnqvDFKSV] device [blocks-count]\n"),
                program_name);
        exit(1);
 }
@@ -674,7 +675,21 @@ static void parse_extended_opts(struct ext2_super_block *param,
                        *arg = 0;
                        arg++;
                }
-               if (strcmp(token, "stride") == 0) {
+               if (strcmp(token, "mmp_update_interval") == 0) {
+                       if (!arg) {
+                               r_usage++;
+                               badopt = token;
+                               continue;
+                       }
+                       param->s_mmp_update_interval = strtoul(arg, &p, 0);
+                       if (*p) {
+                               fprintf(stderr,
+                                       _("Invalid mmp_update_interval: %s\n"),
+                                       arg);
+                               r_usage++;
+                               continue;
+                       }
+               } else if (strcmp(token, "stride") == 0) {
                        if (!arg) {
                                r_usage++;
                                badopt = token;
@@ -778,6 +793,23 @@ static void parse_extended_opts(struct ext2_super_block *param,
                        discard = 1;
                } else if (!strcmp(token, "nodiscard")) {
                        discard = 0;
+               } else if (!strcmp(token, "quotatype")) {
+                       if (!arg) {
+                               r_usage++;
+                               badopt = token;
+                               continue;
+                       }
+                       if (!strncmp(arg, "usr", 3)) {
+                               quotatype = 0;
+                       } else if (!strncmp(arg, "grp", 3)) {
+                               quotatype = 1;
+                       } else {
+                               fprintf(stderr,
+                                       _("Invalid quotatype parameter: %s\n"),
+                                       arg);
+                               r_usage++;
+                               continue;
+                       }
                } else {
                        r_usage++;
                        badopt = token;
@@ -796,7 +828,8 @@ static void parse_extended_opts(struct ext2_super_block *param,
                        "\tlazy_journal_init=<0 to disable, 1 to enable>\n"
                        "\ttest_fs\n"
                        "\tdiscard\n"
-                       "\tnodiscard\n\n"),
+                       "\tnodiscard\n"
+                       "\tquotatype=<usr OR grp>\n\n"),
                        badopt ? badopt : "");
                free(buf);
                exit(1);
@@ -822,6 +855,7 @@ static __u32 ok_features[3] = {
                EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|
                EXT2_FEATURE_INCOMPAT_META_BG|
                EXT4_FEATURE_INCOMPAT_FLEX_BG|
+               EXT4_FEATURE_INCOMPAT_MMP |
                EXT4_FEATURE_INCOMPAT_64BIT,
        /* R/O compat */
        EXT2_FEATURE_RO_COMPAT_LARGE_FILE|
@@ -831,7 +865,10 @@ static __u32 ok_features[3] = {
                EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|
                EXT4_FEATURE_RO_COMPAT_GDT_CSUM|
                EXT4_FEATURE_RO_COMPAT_BIGALLOC|
-               EXT4_FEATURE_RO_COMPAT_QUOTA
+#ifdef CONFIG_QUOTA
+               EXT4_FEATURE_RO_COMPAT_QUOTA|
+#endif
+               0
 };
 
 
@@ -975,6 +1012,8 @@ static char **parse_fs_type(const char *fs_type,
                ext_type = "ext2";
        else if (!strcmp(program_name, "mke3fs"))
                ext_type = "ext3";
+       else if (!strcmp(program_name, "mke4fs"))
+               ext_type = "ext4";
        else if (progname) {
                ext_type = strrchr(progname, '/');
                if (ext_type)
@@ -1280,7 +1319,7 @@ profile_error:
        }
 
        while ((c = getopt (argc, argv,
-                   "b:cg:i:jl:m:no:qr:s:t:vC:E:FG:I:J:KL:M:N:O:R:ST:U:V")) != EOF) {
+                   "b:cg:i:jl:m:no:qr:s:t:vC:DE:FG:I:J:KL:M:N:O:R:ST:U:V")) != EOF) {
                switch (c) {
                case 'b':
                        blocksize = strtol(optarg, &tmp, 0);
@@ -1308,11 +1347,14 @@ profile_error:
                        if (cluster_size < EXT2_MIN_CLUSTER_SIZE ||
                            cluster_size > EXT2_MAX_CLUSTER_SIZE || *tmp) {
                                com_err(program_name, 0,
-                                       _("invalid fragment size - %s"),
+                                       _("invalid cluster size - %s"),
                                        optarg);
                                exit(1);
                        }
                        break;
+               case 'D':
+                       direct_io = 1;
+                       break;
                case 'g':
                        fs_param.s_blocks_per_group = strtoul(optarg, &tmp, 0);
                        if (*tmp) {
@@ -1855,6 +1897,7 @@ profile_error:
        journal_flags |= get_bool_from_profile(fs_types,
                                               "lazy_journal_init", 0) ?
                                               EXT2_MKJOURNAL_LAZYINIT : 0;
+       journal_flags |= EXT2_MKJOURNAL_NO_MNT_CHECK;
 
        /* Get options from profile */
        for (cpp = fs_types; *cpp; cpp++) {
@@ -1928,7 +1971,7 @@ profile_error:
                                num_inodes = MAX_32_NUM;
                        else {
                                com_err(program_name, 0,
-                                       _("too many inodes (%llu), raise"
+                                       _("too many inodes (%llu), raise "
                                          "inode ratio?"), n);
                                exit(1);
                        }
@@ -2024,18 +2067,21 @@ open_err_out:
 static int mke2fs_setup_tdb(const char *name, io_manager *io_ptr)
 {
        errcode_t retval = ENOMEM;
-       char *tdb_dir, *tdb_file = NULL;
+       char *tdb_dir = NULL, *tdb_file = NULL;
        char *device_name, *tmp_name;
+       int free_tdb_dir = 0;
 
        /*
         * Configuration via a conf file would be
         * nice
         */
        tdb_dir = getenv("E2FSPROGS_UNDO_DIR");
-       if (!tdb_dir)
+       if (!tdb_dir) {
                profile_get_string(profile, "defaults",
                                   "undo_dir", 0, "/var/lib/e2fsprogs",
                                   &tdb_dir);
+               free_tdb_dir = 1;
+       }
 
        if (!strcmp(tdb_dir, "none") || (tdb_dir[0] == 0) ||
            access(tdb_dir, W_OK))
@@ -2069,10 +2115,14 @@ static int mke2fs_setup_tdb(const char *name, io_manager *io_ptr)
                 "using the command:\n"
                 "    e2undo %s %s\n\n"), tdb_file, name);
 
+       if (free_tdb_dir)
+               free(tdb_dir);
        free(tdb_file);
        return 0;
 
 errout:
+       if (free_tdb_dir)
+               free(tdb_dir);
        free(tdb_file);
        com_err(program_name, retval,
                _("while trying to setup undo file\n"));
@@ -2158,13 +2208,12 @@ static int create_quota_inodes(ext2_filsys fs)
 {
        quota_ctx_t qctx;
 
-       init_quota_context(&qctx, fs, -1);
-       compute_quota(qctx, -1);
-       write_quota_inode(qctx, USRQUOTA);
-       write_quota_inode(qctx, GRPQUOTA);
-       release_quota_context(&qctx);
+       quota_init_context(&qctx, fs, -1);
+       quota_compute_usage(qctx);
+       quota_write_inode(qctx, quotatype);
+       quota_release_context(&qctx);
 
-       return;
+       return 0;
 }
 
 int main (int argc, char *argv[])
@@ -2173,7 +2222,8 @@ int main (int argc, char *argv[])
        ext2_filsys     fs;
        badblocks_list  bb_list = 0;
        unsigned int    journal_blocks;
-       unsigned int    i, max_mnt_count, checkinterval;
+       unsigned int    i, checkinterval;
+       int             max_mnt_count;
        int             val, hash_alg;
        int             flags;
        int             old_bitmaps;
@@ -2187,6 +2237,7 @@ int main (int argc, char *argv[])
        setlocale(LC_CTYPE, "");
        bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
        textdomain(NLS_CAT_NAME);
+       set_com_err_gettext(gettext);
 #endif
        PRS(argc, argv);
 
@@ -2208,6 +2259,8 @@ int main (int argc, char *argv[])
         * Initialize the superblock....
         */
        flags = EXT2_FLAG_EXCLUSIVE;
+       if (direct_io)
+               flags |= EXT2_FLAG_DIRECT_IO;
        profile_get_boolean(profile, "options", "old_bitmaps", 0, 0,
                            &old_bitmaps);
        if (!old_bitmaps)
@@ -2306,7 +2359,8 @@ int main (int argc, char *argv[])
                for (i = 0, val = 0 ; i < sizeof(fs->super->s_uuid); i++)
                        val += fs->super->s_uuid[i];
                fs->super->s_max_mnt_count += val % EXT2_DFL_MAX_MNT_COUNT;
-       }
+       } else
+               fs->super->s_max_mnt_count = -1;
 
        /*
         * Override the creator OS, if applicable
@@ -2384,6 +2438,17 @@ int main (int argc, char *argv[])
        if (super_only) {
                fs->super->s_state |= EXT2_ERROR_FS;
                fs->flags &= ~(EXT2_FLAG_IB_DIRTY|EXT2_FLAG_BB_DIRTY);
+               /* 
+                * The command "mke2fs -S" is used to recover
+                * corrupted file systems, so do not mark any of the
+                * inodes as unused; we want e2fsck to consider all
+                * inodes as potentially containing recoverable data.
+                */
+               if (fs->super->s_feature_ro_compat &
+                   EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
+                       for (i = 0; i < fs->group_desc_count; i++)
+                               ext2fs_bg_itable_unused_set(fs, i, 0);
+               }
        } else {
                /* rsv must be a power of two (64kB is MD RAID sb alignment) */
                blk64_t rsv = 65536 / fs->blocksize;
@@ -2492,6 +2557,19 @@ int main (int argc, char *argv[])
                        printf(_("done\n"));
        }
 no_journal:
+       if (!super_only &&
+           fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) {
+               retval = ext2fs_mmp_init(fs);
+               if (retval) {
+                       fprintf(stderr, _("\nError while enabling multiple "
+                                         "mount protection feature."));
+                       exit(1);
+               }
+               if (!quiet)
+                       printf(_("Multiple mount protection is enabled "
+                                "with update interval %d seconds.\n"),
+                              fs->super->s_mmp_update_interval);
+       }
 
        if (EXT2_HAS_RO_COMPAT_FEATURE(&fs_param,
                                       EXT4_FEATURE_RO_COMPAT_BIGALLOC))