Whamcloud - gitweb
misc: fix compile warnings on master branch
[tools/e2fsprogs.git] / misc / mke2fs.c
index 527f25b..dd4d213 100644 (file)
  * enforced (but it's not much fun on a character device :-).
  */
 
-#define _XOPEN_SOURCE 600 /* for inclusion of PATH_MAX in Solaris */
+#define _XOPEN_SOURCE 600 /* for inclusion of PATH_MAX */
 
 #include "config.h"
 #include <stdio.h>
 #include <string.h>
 #include <strings.h>
-#include <fcntl.h>
 #include <ctype.h>
 #include <time.h>
 #ifdef __linux__
 #include <sys/utsname.h>
+#include <linux/version.h>
 #endif
 #ifdef HAVE_GETOPT_H
 #include <getopt.h>
@@ -44,24 +44,20 @@ extern int optind;
 #include <errno.h>
 #endif
 #include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
 #include <libgen.h>
 #include <limits.h>
 #include <blkid/blkid.h>
 
 #include "ext2fs/ext2_fs.h"
 #include "ext2fs/ext2fsP.h"
-#include "et/com_err.h"
 #include "uuid/uuid.h"
-#include "e2p/e2p.h"
-#include "ext2fs/ext2fs.h"
 #include "util.h"
 #include "profile.h"
 #include "prof_err.h"
 #include "../version.h"
-#include "nls-enable.h"
-#include "quota/mkquota.h"
+#include "quota/quotaio.h"
+#include "mke2fs.h"
+#include "create_inode.h"
 
 #define STRIDE_LENGTH 8
 
@@ -76,27 +72,32 @@ extern int optind;
 extern int isatty(int);
 extern FILE *fpopen(const char *cmd, const char *mode);
 
-static const char * program_name = "mke2fs";
+const char * program_name = "mke2fs";
 static const char * device_name /* = NULL */;
 
 /* Command line options */
 static int     cflag;
-static int     verbose;
-static int     quiet;
+int    verbose;
+int    quiet;
 static int     super_only;
 static int     discard = 1;    /* attempt to discard device before fs creation */
 static int     direct_io;
 static int     force;
 static int     noaction;
+static int     num_backups = 2; /* number of backup bg's for sparse_super2 */
 static uid_t   root_uid;
 static gid_t   root_gid;
 int    journal_size;
 int    journal_flags;
 static int     lazy_itable_init;
+static int     packed_meta_blocks;
 static char    *bad_blocks_filename = NULL;
 static __u32   fs_stride;
 static int     quotatype = -1;  /* Initialize both user and group quotas by default */
 static __u64   offset;
+static blk64_t journal_location = ~0LL;
+static int     proceed_delay = -1;
+static blk64_t dev_size;
 
 static struct ext2_super_block fs_param;
 static char *fs_uuid = NULL;
@@ -105,19 +106,20 @@ static char *volume_label;
 static char *mount_dir;
 char *journal_device;
 static int sync_kludge;        /* Set using the MKE2FS_SYNC env. option */
-static char **fs_types;
+char **fs_types;
+const char *root_dir;  /* Copy files from the specified directory */
 
 static profile_t       profile;
 
 static int sys_page_size = 4096;
-static int linux_version_code = 0;
 
 static void usage(void)
 {
        fprintf(stderr, _("Usage: %s [-c|-l filename] [-b block-size] "
        "[-C cluster-size]\n\t[-i bytes-per-inode] [-I inode-size] "
        "[-J journal-options]\n"
-       "\t[-G flex-group-size] [-N number-of-inodes]\n"
+       "\t[-G flex-group-size] [-N number-of-inodes] "
+       "[-d root-directory]\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[,...]] "
@@ -140,7 +142,7 @@ static int int_log2(unsigned long long arg)
        return l;
 }
 
-static int int_log10(unsigned long long arg)
+int int_log10(unsigned long long arg)
 {
        int     l;
 
@@ -169,7 +171,29 @@ static int parse_version_number(const char *s)
        rev = strtol(cp, &endptr, 10);
        if (cp == endptr)
                return 0;
-       return ((((major * 256) + minor) * 256) + rev);
+       return KERNEL_VERSION(major, minor, rev);
+}
+
+static int is_before_linux_ver(unsigned int major, unsigned int minor)
+{
+       struct          utsname ut;
+       static int      linux_version_code = -1;
+
+       if (uname(&ut)) {
+               perror("uname");
+               exit(1);
+       }
+       if (linux_version_code < 0)
+               linux_version_code = parse_version_number(ut.release);
+       if (linux_version_code == 0)
+               return 0;
+
+       return linux_version_code < KERNEL_VERSION(major, minor, 0);
+}
+#else
+static int is_before_linux_ver(unsigned int major, unsigned int minor)
+{
+       return 0;
 }
 #endif
 
@@ -315,13 +339,11 @@ static void write_reserved_inodes(ext2_filsys fs)
        ext2_ino_t      ino;
        struct ext2_inode *inode;
 
-       retval = ext2fs_get_mem(EXT2_INODE_SIZE(fs->super), &inode);
+       retval = ext2fs_get_memzero(EXT2_INODE_SIZE(fs->super), &inode);
        if (retval) {
-               com_err("inode_init", retval,
-                       "while allocating memory");
+               com_err("inode_init", retval, "while allocating memory");
                exit(1);
        }
-       bzero(inode, EXT2_INODE_SIZE(fs->super));
 
        for (ino = 1; ino < EXT2_FIRST_INO(fs->super); ino++)
                ext2fs_write_inode_full(fs, ino, inode,
@@ -330,6 +352,41 @@ static void write_reserved_inodes(ext2_filsys fs)
        ext2fs_free_mem(&inode);
 }
 
+static errcode_t packed_allocate_tables(ext2_filsys fs)
+{
+       errcode_t       retval;
+       dgrp_t          i;
+       blk64_t         goal = 0;
+
+       for (i = 0; i < fs->group_desc_count; i++) {
+               retval = ext2fs_new_block2(fs, goal, NULL, &goal);
+               if (retval)
+                       return retval;
+               ext2fs_block_alloc_stats2(fs, goal, +1);
+               ext2fs_block_bitmap_loc_set(fs, i, goal);
+       }
+       for (i = 0; i < fs->group_desc_count; i++) {
+               retval = ext2fs_new_block2(fs, goal, NULL, &goal);
+               if (retval)
+                       return retval;
+               ext2fs_block_alloc_stats2(fs, goal, +1);
+               ext2fs_inode_bitmap_loc_set(fs, i, goal);
+       }
+       for (i = 0; i < fs->group_desc_count; i++) {
+               blk64_t end = ext2fs_blocks_count(fs->super) - 1;
+               retval = ext2fs_get_free_blocks2(fs, goal, end,
+                                                fs->inode_blocks_per_group,
+                                                fs->block_map, &goal);
+               if (retval)
+                       return retval;
+               ext2fs_block_alloc_stats_range(fs, goal,
+                                              fs->inode_blocks_per_group, +1);
+               ext2fs_inode_table_loc_set(fs, i, goal);
+               ext2fs_group_desc_csum_set(fs, i);
+       }
+       return 0;
+}
+
 static void write_inode_tables(ext2_filsys fs, int lazy_flag, int itable_zeroed)
 {
        errcode_t       retval;
@@ -584,6 +641,14 @@ static void show_stats(ext2_filsys fs)
        dgrp_t                  i;
        int                     need, col_left;
 
+       if (!verbose) {
+               printf(_("Creating filesystem with %llu %dk blocks and "
+                        "%u inodes\n"),
+                      ext2fs_blocks_count(s), fs->blocksize >> 10,
+                      s->s_inodes_count);
+               goto skip_details;
+       }
+
        if (ext2fs_blocks_count(&fs_param) != ext2fs_blocks_count(s))
                fprintf(stderr, _("warning: %llu blocks unused.\n\n"),
                       ext2fs_blocks_count(&fs_param) - ext2fs_blocks_count(s));
@@ -632,11 +697,14 @@ static void show_stats(ext2_filsys fs)
                       s->s_blocks_per_group, s->s_clusters_per_group);
        printf(_("%u inodes per group\n"), s->s_inodes_per_group);
 
+skip_details:
        if (fs->group_desc_count == 1) {
                printf("\n");
                return;
        }
 
+       if (!e2p_is_null_uuid(s->s_uuid))
+               printf(_("Filesystem UUID: %s\n"), e2p_uuid2str(s->s_uuid));
        printf("%s", _("Superblock backups stored on blocks: "));
        group_block = s->s_first_data_block;
        col_left = 0;
@@ -782,6 +850,28 @@ static void parse_extended_opts(struct ext2_super_block *param,
                                r_usage++;
                                continue;
                        }
+               } else if (strcmp(token, "num_backup_sb") == 0) {
+                       if (!arg) {
+                               r_usage++;
+                               badopt = token;
+                               continue;
+                       }
+                       num_backups = strtoul(arg, &p, 0);
+                       if (*p || num_backups > 2) {
+                               fprintf(stderr,
+                                       _("Invalid # of backup "
+                                         "superbocks: %s\n"),
+                                       arg);
+                               r_usage++;
+                               continue;
+                       }
+               } else if (strcmp(token, "packed_meta_blocks") == 0) {
+                       if (arg)
+                               packed_meta_blocks = strtoul(arg, &p, 0);
+                       else
+                               packed_meta_blocks = 1;
+                       if (packed_meta_blocks)
+                               journal_location = 0;
                } else if (strcmp(token, "stride") == 0) {
                        if (!arg) {
                                r_usage++;
@@ -938,10 +1028,12 @@ static void parse_extended_opts(struct ext2_super_block *param,
                        "\tis set off by an equals ('=') sign.\n\n"
                        "Valid extended options are:\n"
                        "\tmmp_update_interval=<interval>\n"
+                       "\tnum_backup_sb=<0|1|2>\n"
                        "\tstride=<RAID per-disk data chunk in blocks>\n"
                        "\tstripe-width=<RAID stride * data disks in blocks>\n"
                        "\toffset=<offset to create the file system>\n"
                        "\tresize=<resize maximum size in blocks>\n"
+                       "\tpacked_meta_blocks=<0 to disable, 1 to enable>\n"
                        "\tlazy_itable_init=<0 to disable, 1 to enable>\n"
                        "\tlazy_journal_init=<0 to disable, 1 to enable>\n"
                        "\troot_uid=<uid of root directory>\n"
@@ -968,7 +1060,8 @@ static __u32 ok_features[3] = {
        EXT3_FEATURE_COMPAT_HAS_JOURNAL |
                EXT2_FEATURE_COMPAT_RESIZE_INODE |
                EXT2_FEATURE_COMPAT_DIR_INDEX |
-               EXT2_FEATURE_COMPAT_EXT_ATTR,
+               EXT2_FEATURE_COMPAT_EXT_ATTR |
+               EXT4_FEATURE_COMPAT_SPARSE_SUPER2,
        /* Incompat */
        EXT2_FEATURE_INCOMPAT_FILETYPE|
                EXT3_FEATURE_INCOMPAT_EXTENTS|
@@ -976,7 +1069,8 @@ static __u32 ok_features[3] = {
                EXT2_FEATURE_INCOMPAT_META_BG|
                EXT4_FEATURE_INCOMPAT_FLEX_BG|
                EXT4_FEATURE_INCOMPAT_MMP |
-               EXT4_FEATURE_INCOMPAT_64BIT,
+               EXT4_FEATURE_INCOMPAT_64BIT|
+               EXT4_FEATURE_INCOMPAT_INLINE_DATA,
        /* R/O compat */
        EXT2_FEATURE_RO_COMPAT_LARGE_FILE|
                EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
@@ -1221,7 +1315,7 @@ static char **parse_fs_type(const char *fs_type,
        return (list.list);
 }
 
-static char *get_string_from_profile(char **types, const char *opt,
+char *get_string_from_profile(char **types, const char *opt,
                                     const char *def_val)
 {
        char *ret = 0;
@@ -1238,7 +1332,7 @@ static char *get_string_from_profile(char **types, const char *opt,
        return (ret);
 }
 
-static int get_int_from_profile(char **types, const char *opt, int def_val)
+int get_int_from_profile(char **types, const char *opt, int def_val)
 {
        int ret;
        char **cpp;
@@ -1261,7 +1355,7 @@ static double get_double_from_profile(char **types, const char *opt,
        return ret;
 }
 
-static int get_bool_from_profile(char **types, const char *opt, int def_val)
+int get_bool_from_profile(char **types, const char *opt, int def_val)
 {
        int ret;
        char **cpp;
@@ -1329,7 +1423,7 @@ out:
 
 static void PRS(int argc, char *argv[])
 {
-       int             b, c;
+       int             b, c, flags;
        int             cluster_size = 0;
        char            *tmp, **cpp;
        int             blocksize = 0;
@@ -1338,14 +1432,13 @@ static void PRS(int argc, char *argv[])
        unsigned long   flex_bg_size = 0;
        double          reserved_ratio = -1.0;
        int             lsector_size = 0, psector_size = 0;
-       int             show_version_only = 0;
+       int             show_version_only = 0, is_device = 0;
        unsigned long long num_inodes = 0; /* unsigned long long to catch too-large input */
        errcode_t       retval;
        char *          oldpath = getenv("PATH");
        char *          extended_opts = 0;
        char *          fs_type = 0;
        char *          usage_types = 0;
-       blk64_t         dev_size;
        /*
         * NOTE: A few words about fs_blocks_count and blocksize:
         *
@@ -1362,9 +1455,6 @@ static void PRS(int argc, char *argv[])
         * Finally, we complain about fs_blocks_count > 2^32 on a non-64bit fs.
         */
        blk64_t         fs_blocks_count = 0;
-#ifdef __linux__
-       struct          utsname ut;
-#endif
        long            sysval;
        int             s_opt = -1, r_opt = -1;
        char            *fs_features = 0;
@@ -1430,15 +1520,8 @@ profile_error:
        memset(&fs_param, 0, sizeof(struct ext2_super_block));
        fs_param.s_rev_level = 1;  /* Create revision 1 filesystems now */
 
-#ifdef __linux__
-       if (uname(&ut)) {
-               perror("uname");
-               exit(1);
-       }
-       linux_version_code = parse_version_number(ut.release);
-       if (linux_version_code && linux_version_code < (2*65536 + 2*256))
+       if (is_before_linux_ver(2, 2))
                fs_param.s_rev_level = 0;
-#endif
 
        if (argc && *argv) {
                program_name = get_progname(*argv);
@@ -1450,7 +1533,7 @@ profile_error:
        }
 
        while ((c = getopt (argc, argv,
-                   "b:cg:i:jl:m:no:qr:s:t:vC:DE:FG:I:J:KL:M:N:O:R:ST:U:V")) != EOF) {
+                   "b:cg:i:jl:m:no:qr:s:t:d:vC:DE:FG:I:J:KL:M:N:O:R:ST:U:V")) != EOF) {
                switch (c) {
                case 'b':
                        blocksize = parse_num_blocks2(optarg, -1);
@@ -1638,6 +1721,9 @@ profile_error:
                case 'U':
                        fs_uuid = optarg;
                        break;
+               case 'd':
+                       root_dir = optarg;
+                       break;
                case 'v':
                        verbose = 1;
                        break;
@@ -1714,8 +1800,18 @@ profile_error:
        if (optind < argc)
                usage();
 
-       if (!force)
-               check_plausibility(device_name);
+       profile_get_integer(profile, "options", "proceed_delay", 0, 0,
+                           &proceed_delay);
+
+       /* The isatty() test is so we don't break existing scripts */
+       flags = CREATE_FILE;
+       if (isatty(0) && isatty(1))
+               flags |= CHECK_FS_EXIST;
+       if (!quiet)
+               flags |= VERBOSE_CREATE;
+       if (!check_plausibility(device_name, flags, &is_device) && !force)
+               proceed_question(proceed_delay);
+
        check_mount(device_name, force, _("filesystem"));
 
        /* Determine the size of the device (if possible) */
@@ -1757,10 +1853,10 @@ profile_error:
                                fs_blocks_count &= ~((blk64_t) ((sys_page_size /
                                             EXT2_BLOCK_SIZE(&fs_param))-1));
                }
-       } else if (!force && (fs_blocks_count > dev_size)) {
+       } else if (!force && is_device && (fs_blocks_count > dev_size)) {
                com_err(program_name, 0, "%s",
                        _("Filesystem larger than apparent device size."));
-               proceed_question();
+               proceed_question(proceed_delay);
        }
 
        if (!fs_type)
@@ -1828,20 +1924,20 @@ profile_error:
        if (for_hurd(creator_os)) {
                if (fs_param.s_feature_incompat &
                    EXT2_FEATURE_INCOMPAT_FILETYPE) {
-                       fprintf(stderr, _("The HURD does not support the "
-                                         "filetype feature.\n"));
+                       fprintf(stderr, "%s", _("The HURD does not support the "
+                                               "filetype feature.\n"));
                        exit(1);
                }
                if (fs_param.s_feature_ro_compat &
                    EXT4_FEATURE_RO_COMPAT_HUGE_FILE) {
-                       fprintf(stderr, _("The HURD does not support the "
-                                         "huge_file feature.\n"));
+                       fprintf(stderr, "%s", _("The HURD does not support the "
+                                               "huge_file feature.\n"));
                        exit(1);
                }
                if (fs_param.s_feature_ro_compat &
                    EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) {
-                       fprintf(stderr, _("The HURD does not support the "
-                                         "metadata_csum feature.\n"));
+                       fprintf(stderr, "%s", _("The HURD does not support the "
+                                               "metadata_csum feature.\n"));
                        exit(1);
                }
        }
@@ -1876,8 +1972,7 @@ profile_error:
 
                if (use_bsize == -1) {
                        use_bsize = sys_page_size;
-                       if ((linux_version_code < (2*65536 + 6*256)) &&
-                           (use_bsize > 4096))
+                       if (is_before_linux_ver(2, 6) && use_bsize > 4096)
                                use_bsize = 4096;
                }
                if (lsector_size && use_bsize < lsector_size)
@@ -1908,6 +2003,9 @@ profile_error:
         * 32-bit vs 64-bit block number support.
         */
        if ((fs_blocks_count > MAX_32_NUM) &&
+           (fs_param.s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT))
+               fs_param.s_feature_compat &= ~EXT2_FEATURE_COMPAT_RESIZE_INODE;
+       if ((fs_blocks_count > MAX_32_NUM) &&
            !(fs_param.s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) &&
            get_bool_from_profile(fs_types, "auto_64-bit_support", 0)) {
                fs_param.s_feature_incompat |= EXT4_FEATURE_INCOMPAT_64BIT;
@@ -2044,6 +2142,8 @@ profile_error:
        }
 #endif
 
+       num_backups = get_int_from_profile(fs_types, "num_backup_sb", 2);
+
        blocksize = EXT2_BLOCK_SIZE(&fs_param);
 
        /*
@@ -2060,7 +2160,7 @@ profile_error:
                        com_err(program_name, 0,
                                _("%d-byte blocks too big for system (max %d)"),
                                blocksize, sys_page_size);
-                       proceed_question();
+                       proceed_question(proceed_delay);
                }
                fprintf(stderr, _("Warning: %d-byte blocks too big for system "
                                  "(max %d), forced to continue\n"),
@@ -2080,6 +2180,20 @@ profile_error:
                                               EXT2_MKJOURNAL_LAZYINIT : 0;
        journal_flags |= EXT2_MKJOURNAL_NO_MNT_CHECK;
 
+       if (!journal_location_string)
+               journal_location_string = get_string_from_profile(fs_types,
+                                               "journal_location", "");
+       if ((journal_location == ~0ULL) && journal_location_string &&
+           *journal_location_string)
+               journal_location = parse_num_blocks2(journal_location_string,
+                                               fs_param.s_log_block_size);
+       free(journal_location_string);
+
+       packed_meta_blocks = get_bool_from_profile(fs_types,
+                                                  "packed_meta_blocks", 0);
+       if (packed_meta_blocks)
+               journal_location = 0;
+
        /* Get options from profile */
        for (cpp = fs_types; *cpp; cpp++) {
                tmp = NULL;
@@ -2124,14 +2238,8 @@ profile_error:
                                  "See https://ext4.wiki.kernel.org/"
                                  "index.php/Bigalloc for more information\n\n"));
 
-       if (!quiet &&
-           (fs_param.s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_QUOTA))
-               fprintf(stderr, "%s", _("\nWarning: the quota feature is "
-                                 "still under development\n"
-                                 "See https://ext4.wiki.kernel.org/"
-                                 "index.php/Quota for more information\n\n"));
-
-       /* Since sparse_super is the default, we would only have a problem
+       /*
+        * Since sparse_super is the default, we would only have a problem
         * here if it was explicitly disabled.
         */
        if ((fs_param.s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INODE) &&
@@ -2190,6 +2298,19 @@ profile_error:
                fs_param.s_inode_size = inode_size;
        }
 
+       /*
+        * If inode size is 128 and inline data is enabled, we need
+        * to notify users that inline data will never be useful.
+        */
+       if ((fs_param.s_feature_incompat &
+            EXT4_FEATURE_INCOMPAT_INLINE_DATA) &&
+           fs_param.s_inode_size == EXT2_GOOD_OLD_INODE_SIZE) {
+               com_err(program_name, 0,
+                       _("inode size is %d, inline data is useless"),
+                       fs_param.s_inode_size);
+               exit(1);
+       }
+
        /* Make sure number of inodes specified will fit in 32 bits */
        if (num_inodes == 0) {
                unsigned long long n;
@@ -2238,6 +2359,13 @@ profile_error:
        ext2fs_r_blocks_count_set(&fs_param, reserved_ratio *
                                  ext2fs_blocks_count(&fs_param) / 100.0);
 
+       if (fs_param.s_feature_compat & EXT4_FEATURE_COMPAT_SPARSE_SUPER2) {
+               if (num_backups >= 1)
+                       fs_param.s_backup_bgs[0] = 1;
+               if (num_backups >= 2)
+                       fs_param.s_backup_bgs[1] = ~0;
+       }
+
        free(fs_type);
        free(usage_types);
 }
@@ -2410,30 +2538,43 @@ static int mke2fs_discard_device(ext2_filsys fs)
 
 static void fix_cluster_bg_counts(ext2_filsys fs)
 {
-       blk64_t cluster, num_clusters, tot_free;
-       unsigned num = 0;
-       int     grp_free, num_free, group;
-
-       num_clusters = EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super));
-       tot_free = num_free = group = grp_free = 0;
-       for (cluster = EXT2FS_B2C(fs, fs->super->s_first_data_block);
-            cluster < num_clusters; cluster++) {
-               if (!ext2fs_test_block_bitmap2(fs->block_map,
-                                              EXT2FS_C2B(fs, cluster))) {
-                       grp_free++;
-                       tot_free++;
+       blk64_t         block, num_blocks, last_block, next;
+       blk64_t         tot_free = 0;
+       errcode_t       retval;
+       dgrp_t          group = 0;
+       int             grp_free = 0;
+
+       num_blocks = ext2fs_blocks_count(fs->super);
+       last_block = ext2fs_group_last_block2(fs, group);
+       block = fs->super->s_first_data_block;
+       while (block < num_blocks) {
+               retval = ext2fs_find_first_zero_block_bitmap2(fs->block_map,
+                                               block, last_block, &next);
+               if (retval == 0)
+                       block = next;
+               else {
+                       block = last_block + 1;
+                       goto next_bg;
                }
-               num++;
-               if ((num == fs->super->s_clusters_per_group) ||
-                   (cluster == num_clusters-1)) {
+
+               retval = ext2fs_find_first_set_block_bitmap2(fs->block_map,
+                                               block, last_block, &next);
+               if (retval)
+                       next = last_block + 1;
+               grp_free += EXT2FS_NUM_B2C(fs, next - block);
+               tot_free += next - block;
+               block = next;
+
+               if (block > last_block) {
+               next_bg:
                        ext2fs_bg_free_blocks_count_set(fs, group, grp_free);
                        ext2fs_group_desc_csum_set(fs, group);
-                       num = 0;
                        grp_free = 0;
                        group++;
+                       last_block = ext2fs_group_last_block2(fs, group);
                }
        }
-       ext2fs_free_blocks_count_set(fs->super, EXT2FS_C2B(fs, tot_free));
+       ext2fs_free_blocks_count_set(fs->super, tot_free);
 }
 
 static int create_quota_inodes(ext2_filsys fs)
@@ -2453,7 +2594,7 @@ int main (int argc, char *argv[])
        errcode_t       retval = 0;
        ext2_filsys     fs;
        badblocks_list  bb_list = 0;
-       unsigned int    journal_blocks;
+       unsigned int    journal_blocks = 0;
        unsigned int    i, checkinterval;
        int             max_mnt_count;
        int             val, hash_alg;
@@ -2518,17 +2659,19 @@ int main (int argc, char *argv[])
                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
                if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
                                EXT3_FEATURE_INCOMPAT_EXTENTS))
-                       printf(_("Extents are not enabled.  The file extent "
+                       printf("%s",
+                              _("Extents are not enabled.  The file extent "
                                 "tree can be checksummed, whereas block maps "
                                 "cannot.  Not enabling extents reduces the "
                                 "coverage of metadata checksumming.  "
                                 "Pass -O extents to rectify.\n"));
                if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
                                EXT4_FEATURE_INCOMPAT_64BIT))
-                       printf(_("64-bit filesystem support is not "
-                                "enabled.  The larger fields afforded by "
-                                "this feature enable full-strength "
-                                "checksumming.  Pass -O 64bit to rectify.\n"));
+                       printf("%s",
+                              _("64-bit filesystem support is not enabled.  "
+                                "The larger fields afforded by this feature "
+                                "enable full-strength checksumming.  "
+                                "Pass -O 64bit to rectify.\n"));
        }
 
        /* Calculate journal blocks */
@@ -2538,7 +2681,7 @@ int main (int argc, char *argv[])
                journal_blocks = figure_journal_size(journal_size, fs);
 
        /* Can't undo discard ... */
-       if (!noaction && discard && (io_ptr != undo_io_manager)) {
+       if (!noaction && discard && dev_size && (io_ptr != undo_io_manager)) {
                retval = mke2fs_discard_device(fs);
                if (!retval && io_channel_discard_zeroes_data(fs->io)) {
                        if (verbose)
@@ -2547,6 +2690,7 @@ int main (int argc, char *argv[])
                                         "0s - skipping inode table wipe\n"));
                        lazy_itable_init = 1;
                        itable_zeroed = 1;
+                       zero_hugefile = 0;
                }
        }
 
@@ -2684,12 +2828,16 @@ int main (int argc, char *argv[])
                read_bb_file(fs, &bb_list, bad_blocks_filename);
        if (cflag)
                test_disk(fs, &bb_list);
-
        handle_bad_blocks(fs, bb_list);
+
        fs->stride = fs_stride = fs->super->s_raid_stride;
        if (!quiet)
                printf("%s", _("Allocating group tables: "));
-       retval = ext2fs_allocate_tables(fs);
+       if ((fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) &&
+           packed_meta_blocks)
+               retval = packed_allocate_tables(fs);
+       else
+               retval = ext2fs_allocate_tables(fs);
        if (retval) {
                com_err(program_name, retval, "%s",
                        _("while trying to allocate filesystem tables"));
@@ -2766,8 +2914,9 @@ int main (int argc, char *argv[])
        if (journal_device) {
                ext2_filsys     jfs;
 
-               if (!force)
-                       check_plausibility(journal_device);
+               if (!check_plausibility(journal_device, CHECK_BLOCK_DEV,
+                                       NULL) && !force)
+                       proceed_question(proceed_delay);
                check_mount(journal_device, force, _("journal"));
 
                retval = ext2fs_open(journal_device, EXT2_FLAG_RW|
@@ -2814,8 +2963,9 @@ int main (int argc, char *argv[])
                               journal_blocks);
                        fflush(stdout);
                }
-               retval = ext2fs_add_journal_inode(fs, journal_blocks,
-                                                 journal_flags);
+               retval = ext2fs_add_journal_inode2(fs, journal_blocks,
+                                                  journal_location,
+                                                  journal_flags);
                if (retval) {
                        com_err(program_name, retval, "%s",
                                _("\n\twhile trying to create journal"));
@@ -2847,6 +2997,24 @@ no_journal:
                                       EXT4_FEATURE_RO_COMPAT_QUOTA))
                create_quota_inodes(fs);
 
+       retval = mk_hugefiles(fs);
+       if (retval)
+               com_err(program_name, retval, "while creating huge files");
+       /* Copy files from the specified directory */
+       if (root_dir) {
+               if (!quiet)
+                       printf("%s", _("Copying files into the device: "));
+
+               retval = populate_fs(fs, EXT2_ROOT_INO, root_dir,
+                                    EXT2_ROOT_INO);
+               if (retval) {
+                       com_err(program_name, retval, "%s",
+                               _("\nError while populating file system\n"));
+                       exit(1);
+               } else if (!quiet)
+                       printf("%s", _("done\n"));
+       }
+
        if (!quiet)
                printf("%s", _("Writing superblocks and "
                       "filesystem accounting information: "));