Whamcloud - gitweb
LU-16750 tune2fs: add "-E iops" to set/clear IOPS groups
[tools/e2fsprogs.git] / misc / mke2fs.c
index 92003e1..b62252a 100644 (file)
 #include <strings.h>
 #include <ctype.h>
 #include <time.h>
-#ifdef __linux__
-#include <sys/utsname.h>
-#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
-#endif
 #ifdef HAVE_GETOPT_H
 #include <getopt.h>
 #else
@@ -71,8 +67,6 @@ extern int optind;
 #define ZAP_BOOTBLOCK
 #endif
 
-#define DISCARD_STEP_MB                (2048)
-
 extern int isatty(int);
 extern FILE *fpopen(const char *cmd, const char *mode);
 
@@ -94,7 +88,9 @@ static gid_t  root_gid;
 int    journal_size;
 int    journal_flags;
 int    journal_fc_size;
+static e2_blkcnt_t     orphan_file_blocks;
 static int     lazy_itable_init;
+static int     assume_storage_prezeroed;
 static int     packed_meta_blocks;
 int            no_copy_xattrs;
 static char    *bad_blocks_filename = NULL;
@@ -105,6 +101,10 @@ static __u64       offset;
 static blk64_t journal_location = ~0LL;
 static int     proceed_delay = -1;
 static blk64_t dev_size;
+blk64_t                iops_array[64];
+unsigned int   iops_size = sizeof(iops_array);
+unsigned int   iops_count = 0;
+blk64_t                *iops_range = iops_array;
 
 static struct ext2_super_block fs_param;
 static __u32 zero_buf[4];
@@ -165,54 +165,6 @@ int int_log10(unsigned long long arg)
        return l;
 }
 
-#ifdef __linux__
-static int parse_version_number(const char *s)
-{
-       int     major, minor, rev;
-       char    *endptr;
-       const char *cp = s;
-
-       if (!s)
-               return 0;
-       major = strtol(cp, &endptr, 10);
-       if (cp == endptr || *endptr != '.')
-               return 0;
-       cp = endptr + 1;
-       minor = strtol(cp, &endptr, 10);
-       if (cp == endptr || *endptr != '.')
-               return 0;
-       cp = endptr + 1;
-       rev = strtol(cp, &endptr, 10);
-       if (cp == endptr)
-               return 0;
-       return KERNEL_VERSION(major, minor, rev);
-}
-
-static int is_before_linux_ver(unsigned int major, unsigned int minor,
-                              unsigned int rev)
-{
-       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 < (int) KERNEL_VERSION(major, minor, rev);
-}
-#else
-static int is_before_linux_ver(unsigned int major, unsigned int minor,
-                              unsigned int rev)
-{
-       return 0;
-}
-#endif
-
 /*
  * Helper function for read_bb_file and test_disk
  */
@@ -792,6 +744,54 @@ static int set_os(struct ext2_super_block *sb, char *os)
        return 1;
 }
 
+static int parse_range(char *p_start, char *p_end, char *p_hyphen)
+{
+       blk64_t start, end;
+       blk64_t *new_array;
+
+       /**
+        * e.g  0-1024G
+        *      ^      ^
+        *      |      |
+        *   p_start  p_end
+        */
+       end = parse_num_blocks(p_hyphen + 1, -1);
+
+       if (!isdigit(*(p_end - 1)) && isdigit(*(p_hyphen -1))) {
+               /* copy G/M/K unit to start value */
+               *p_hyphen = *(p_end - 1);
+               p_hyphen++;
+       }
+       *p_hyphen = 0;
+
+       start = parse_num_blocks(p_start, -1);
+
+       /* add to iops_range */
+       if (iops_count == iops_size) {
+               iops_size <<= 1;
+               if (iops_size == 0) {
+                       iops_size = iops_count;
+                       return -E2BIG;
+               }
+               if (iops_range == iops_array)
+                       new_array = malloc(iops_size * sizeof(blk64_t));
+               else
+                       new_array = realloc(iops_range,
+                                           iops_size * sizeof(blk64_t));
+               if (!new_array) {
+                       iops_size >>= 1;
+                       return -ENOMEM;
+               } else {
+                       iops_range = new_array;
+               }
+       }
+
+       iops_range[iops_count++] = start;
+       iops_range[iops_count++] = end;
+
+       return 0;
+}
+
 #define PATH_SET "PATH=/sbin"
 
 static void parse_extended_opts(struct ext2_super_block *param,
@@ -1012,6 +1012,11 @@ static void parse_extended_opts(struct ext2_super_block *param,
                                lazy_itable_init = strtoul(arg, &p, 0);
                        else
                                lazy_itable_init = 1;
+               } else if (!strcmp(token, "assume_storage_prezeroed")) {
+                       if (arg)
+                               assume_storage_prezeroed = strtoul(arg, &p, 0);
+                       else
+                               assume_storage_prezeroed = 1;
                } else if (!strcmp(token, "lazy_journal_init")) {
                        if (arg)
                                journal_flags |= strtoul(arg, &p, 0) ?
@@ -1089,6 +1094,77 @@ static void parse_extended_opts(struct ext2_super_block *param,
                                continue;
                        }
                        encoding_flags = arg;
+               } else if (!strcmp(token, "orphan_file_size")) {
+                       if (!arg) {
+                               r_usage++;
+                               badopt = token;
+                               continue;
+                       }
+                       orphan_file_blocks = parse_num_blocks2(arg,
+                                               fs_param.s_log_block_size);
+                       if (orphan_file_blocks == 0) {
+                               fprintf(stderr,
+                                       _("Invalid size of orphan file %s\n"),
+                                       arg);
+                               r_usage++;
+                               continue;
+                       }
+               } else if (!strcmp(token, "iops")) {
+                       char *p_colon, *p_hyphen;
+                       blk64_t start, end;
+
+                       /* example: iops=0-1024G:4096-8192G */
+
+                       if (!arg) {
+                               r_usage++;
+                               badopt = token;
+                               continue;
+                       }
+                       p_colon = strchr(arg, ':');
+                       while (p_colon != NULL) {
+                               *p_colon = 0;
+
+                               p_hyphen = strchr(arg, '-');
+                               if (p_hyphen == NULL) {
+                                       fprintf(stderr,
+                                               _("error: parse iops %s\n"),
+                                               arg);
+                                       r_usage++;
+                                       badopt = token;
+                                       break;
+                               }
+
+                               ret = parse_range(arg, p_colon, p_hyphen);
+                               if (ret < 0) {
+                                       fprintf(stderr,
+                                               _("error: parse iops %s:%d\n"),
+                                               arg, ret);
+                                       r_usage++;
+                                       badopt = token;
+                                       break;
+                               }
+
+                               arg = p_colon + 1;
+                               p_colon = strchr(arg, ':');
+                       }
+                       p_hyphen = strchr(arg, '-');
+                       if (p_hyphen == NULL) {
+                               fprintf(stderr,
+                                       _("error: parse iops %s\n"), arg);
+                               r_usage++;
+                               badopt = token;
+                               continue;
+                       }
+
+                       ret = parse_range(arg, arg + strlen(arg), p_hyphen);
+                       if (ret < 0) {
+                               fprintf(stderr,
+                                       _("error: parse iops %s:%d\n"),
+                                       arg, ret);
+                               r_usage++;
+                               badopt = token;
+                               continue;
+                       }
                } else {
                        r_usage++;
                        badopt = token;
@@ -1115,9 +1191,13 @@ static void parse_extended_opts(struct ext2_super_block *param,
                        "\tnodiscard\n"
                        "\tencoding=<encoding>\n"
                        "\tencoding_flags=<flags>\n"
-                       "\tquotatype=<quota type(s) to be enabled>\n\n"),
+                       "\tiops=<iops storage size range>\n"
+                       "\tquotatype=<quota type(s) to be enabled>\n"
+                       "\tassume_storage_prezeroed=<0 to disable, 1 to enable>\n\n"),
                        badopt ? badopt : "");
                free(buf);
+               if (iops_range != iops_array)
+                       free(iops_range);
                exit(1);
        }
        if (param->s_raid_stride &&
@@ -1156,7 +1236,8 @@ static __u32 ok_features[3] = {
                EXT2_FEATURE_COMPAT_EXT_ATTR |
                EXT4_FEATURE_COMPAT_SPARSE_SUPER2 |
                EXT4_FEATURE_COMPAT_FAST_COMMIT |
-               EXT4_FEATURE_COMPAT_STABLE_INODES,
+               EXT4_FEATURE_COMPAT_STABLE_INODES |
+               EXT4_FEATURE_COMPAT_ORPHAN_FILE,
        /* Incompat */
        EXT2_FEATURE_INCOMPAT_FILETYPE|
                EXT3_FEATURE_INCOMPAT_EXTENTS|
@@ -1165,6 +1246,7 @@ static __u32 ok_features[3] = {
                EXT4_FEATURE_INCOMPAT_FLEX_BG|
                EXT4_FEATURE_INCOMPAT_EA_INODE|
                EXT4_FEATURE_INCOMPAT_MMP |
+               EXT4_FEATURE_INCOMPAT_DIRDATA|
                EXT4_FEATURE_INCOMPAT_64BIT|
                EXT4_FEATURE_INCOMPAT_INLINE_DATA|
                EXT4_FEATURE_INCOMPAT_ENCRYPT |
@@ -1482,12 +1564,15 @@ extern const char *mke2fs_default_profile;
 static const char *default_files[] = { "<default>", 0 };
 
 struct device_param {
-       unsigned long min_io;           /* prefered minimum IO size */
+       unsigned long min_io;           /* preferred minimum IO size */
        unsigned long opt_io;           /* optimal IO size */
        unsigned long alignment_offset; /* alignment offset wrt physical block size */
        unsigned int dax:1;             /* supports dax? */
 };
 
+#define        OPTIMIZED_STRIPE_WIDTH  512
+#define        OPTIMIZED_STRIDE        512
+
 #ifdef HAVE_BLKID_PROBE_GET_TOPOLOGY
 /*
  * Sets the geometry of a device (stripe/stride), and returns the
@@ -1518,7 +1603,19 @@ static int get_device_geometry(const char *file,
                goto out;
 
        dev_param->min_io = blkid_topology_get_minimum_io_size(tp);
+       if (dev_param->min_io > OPTIMIZED_STRIDE) {
+               fprintf(stdout,
+                       "detected raid stride %lu too large, use optimum %lu\n",
+                       dev_param->min_io, OPTIMIZED_STRIDE);
+               dev_param->min_io = OPTIMIZED_STRIDE;
+       }
        dev_param->opt_io = blkid_topology_get_optimal_io_size(tp);
+       if (dev_param->opt_io > OPTIMIZED_STRIPE_WIDTH) {
+               fprintf(stdout,
+                       "detected raid stripe width %lu too large, use optimum %lu\n",
+                       dev_param->opt_io, OPTIMIZED_STRIPE_WIDTH);
+               dev_param->opt_io = OPTIMIZED_STRIPE_WIDTH;
+       }
        if ((dev_param->min_io == 0) && (psector_size > blocksize))
                dev_param->min_io = psector_size;
        if ((dev_param->opt_io == 0) && dev_param->min_io > 0)
@@ -1551,6 +1648,8 @@ static void PRS(int argc, char *argv[])
        int             lsector_size = 0, psector_size = 0;
        int             show_version_only = 0, is_device = 0;
        unsigned long long num_inodes = 0; /* unsigned long long to catch too-large input */
+       int             default_orphan_file = 0;
+       int             default_csum_seed = 0;
        errcode_t       retval;
        char *          oldpath = getenv("PATH");
        char *          extended_opts = 0;
@@ -1572,7 +1671,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;
-       long            sysval;
        int             s_opt = -1, r_opt = -1;
        char            *fs_features = 0;
        int             fs_features_size = 0;
@@ -1606,9 +1704,12 @@ static void PRS(int argc, char *argv[])
 #define _SC_PAGESIZE _SC_PAGE_SIZE
 #endif
 #ifdef _SC_PAGESIZE
-       sysval = sysconf(_SC_PAGESIZE);
-       if (sysval > 0)
-               sys_page_size = sysval;
+       {
+               long sysval = sysconf(_SC_PAGESIZE);
+
+               if (sysval > 0)
+                       sys_page_size = sysval;
+       }
 #endif /* _SC_PAGESIZE */
 #endif /* HAVE_SYSCONF */
 
@@ -1637,7 +1738,7 @@ profile_error:
        memset(&fs_param, 0, sizeof(struct ext2_super_block));
        fs_param.s_rev_level = 1;  /* Create revision 1 filesystems now */
 
-       if (is_before_linux_ver(2, 2, 0))
+       if (ext2fs_is_before_linux_ver(2, 2, 0))
                fs_param.s_rev_level = 0;
 
        if (argc && *argv) {
@@ -1924,10 +2025,10 @@ profile_error:
 #ifdef CONFIG_TESTIO_DEBUG
                if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
                        io_ptr = test_io_manager;
-                       test_io_backing_manager = unix_io_manager;
+                       test_io_backing_manager = default_io_manager;
                } else
 #endif
-                       io_ptr = unix_io_manager;
+                       io_ptr = default_io_manager;
                retval = ext2fs_open(journal_device,
                                     EXT2_FLAG_JOURNAL_DEV_OK, 0,
                                     0, io_ptr, &jfs);
@@ -2048,6 +2149,9 @@ profile_error:
        if (!usage_types)
                profile_get_string(profile, "devices", device_name,
                                   "usage_types", 0, &usage_types);
+       if (!creator_os)
+               profile_get_string(profile, "defaults", "creator_os", 0,
+                                  0, &creator_os);
 
        /*
         * We have the file system (or device) size, so we can now
@@ -2055,8 +2159,7 @@ profile_error:
         * be appropriately configured.
         */
        fs_types = parse_fs_type(fs_type, usage_types, &fs_param,
-                                fs_blocks_count ? fs_blocks_count : dev_size,
-                                argv[0]);
+                                fs_blocks_count, argv[0]);
        if (!fs_types) {
                fprintf(stderr, "%s", _("Failed to parse fs types list\n"));
                exit(1);
@@ -2098,8 +2201,24 @@ profile_error:
                ext2fs_clear_feature_ea_inode(&fs_param);
                ext2fs_clear_feature_casefold(&fs_param);
        }
-       edit_feature(fs_features ? fs_features : tmp,
-                    &fs_param.s_feature_compat);
+       if (!fs_features && tmp)
+               edit_feature(tmp, &fs_param.s_feature_compat);
+       /*
+        * Now all the defaults are incorporated in fs_param. Check the state
+        * of orphan_file feature so that we know whether we should silently
+        * disabled in case journal gets disabled.
+        */
+       if (ext2fs_has_feature_orphan_file(&fs_param))
+               default_orphan_file = 1;
+       if (ext2fs_has_feature_csum_seed(&fs_param))
+               default_csum_seed = 1;
+       if (fs_features)
+               edit_feature(fs_features, &fs_param.s_feature_compat);
+       /* Silently disable orphan_file if user chose fs without journal */
+       if (default_orphan_file && !ext2fs_has_feature_journal(&fs_param))
+               ext2fs_clear_feature_orphan_file(&fs_param);
+       if (default_csum_seed && !ext2fs_has_feature_metadata_csum(&fs_param))
+               ext2fs_clear_feature_csum_seed(&fs_param);
        if (tmp)
                free(tmp);
        (void) ext2fs_free_mem(&fs_features);
@@ -2159,7 +2278,8 @@ profile_error:
 
                if (use_bsize == -1) {
                        use_bsize = sys_page_size;
-                       if (is_before_linux_ver(2, 6, 0) && use_bsize > 4096)
+                       if (ext2fs_is_before_linux_ver(2, 6, 0) &&
+                           use_bsize > 4096)
                                use_bsize = 4096;
                }
                if (lsector_size && use_bsize < lsector_size)
@@ -2189,24 +2309,25 @@ profile_error:
         * We now need to do a sanity check of fs_blocks_count for
         * 32-bit vs 64-bit block number support.
         */
-       if ((fs_blocks_count > MAX_32_NUM) &&
-           ext2fs_has_feature_64bit(&fs_param))
-               ext2fs_clear_feature_resize_inode(&fs_param);
-       if ((fs_blocks_count > MAX_32_NUM) &&
-           !ext2fs_has_feature_64bit(&fs_param) &&
-           get_bool_from_profile(fs_types, "auto_64-bit_support", 0)) {
-               ext2fs_set_feature_64bit(&fs_param);
-               ext2fs_clear_feature_resize_inode(&fs_param);
-       }
-       if ((fs_blocks_count > MAX_32_NUM) &&
-           !ext2fs_has_feature_64bit(&fs_param)) {
-               fprintf(stderr, _("%s: Size of device (0x%llx blocks) %s "
+       if (fs_blocks_count > MAX_32_NUM) {
+               if (!ext2fs_has_feature_64bit(&fs_param) &&
+                   get_bool_from_profile(fs_types, "auto_64-bit_support", 0))
+                       ext2fs_set_feature_64bit(&fs_param);
+
+               if (ext2fs_has_feature_64bit(&fs_param)) {
+                       ext2fs_clear_feature_resize_inode(&fs_param);
+               } else {
+                       fprintf(stderr,
+                               _("%s: Size of device (0x%llx blocks) %s "
                                  "too big to be expressed\n\t"
                                  "in 32 bits using a blocksize of %d.\n"),
-                       program_name, (unsigned long long) fs_blocks_count,
-                       device_name, EXT2_BLOCK_SIZE(&fs_param));
-               exit(1);
+                               program_name,
+                               (unsigned long long) fs_blocks_count,
+                               device_name, EXT2_BLOCK_SIZE(&fs_param));
+                       exit(1);
+               }
        }
+
        /*
         * Guard against group descriptor count overflowing... Mostly to avoid
         * strange results for absurdly large devices.  This is in log2:
@@ -2286,13 +2407,13 @@ profile_error:
                fs_param.s_feature_compat = 0;
                fs_param.s_feature_ro_compat &=
                                        EXT4_FEATURE_RO_COMPAT_METADATA_CSUM;
-       }
+       }
 
        /* Check the user's mkfs options for 64bit */
-       if (ext2fs_has_feature_64bit(&fs_param) &&
+       if (fs_blocks_count > MAX_32_NUM &&
            !ext2fs_has_feature_extents(&fs_param)) {
-               printf("%s", _("Extents MUST be enabled for a 64-bit "
-                              "filesystem.  Pass -O extents to rectify.\n"));
+               printf("%s", _("Extents MUST be enabled for filesystems with "
+                              "over 2^32 blocks. Use '-O extents' to fix.\n"));
                exit(1);
        }
 
@@ -2391,7 +2512,7 @@ profile_error:
        }
 
        /* Metadata checksumming wasn't totally stable before 3.18. */
-       if (is_before_linux_ver(3, 18, 0) &&
+       if (ext2fs_is_before_linux_ver(3, 18, 0) &&
            ext2fs_has_feature_metadata_csum(&fs_param))
                fprintf(stderr, _("Suggestion: Use Linux kernel >= 3.18 for "
                        "improved stability of the metadata and journal "
@@ -2401,7 +2522,7 @@ profile_error:
         * On newer kernels we do have lazy_itable_init support. So pick the
         * right default in case ext4 module is not loaded.
         */
-       if (is_before_linux_ver(2, 6, 37))
+       if (ext2fs_is_before_linux_ver(2, 6, 37))
                lazy_itable_init = 0;
        else
                lazy_itable_init = 1;
@@ -2526,11 +2647,12 @@ profile_error:
                exit(1);
        }
 
-       if (!quiet && ext2fs_has_feature_bigalloc(&fs_param))
-               fprintf(stderr, "%s", _("\nWarning: the bigalloc feature is "
-                                 "still under development\n"
-                                 "See https://ext4.wiki.kernel.org/"
-                                 "index.php/Bigalloc for more information\n\n"));
+       if (!quiet && ext2fs_has_feature_bigalloc(&fs_param) &&
+           EXT2_CLUSTER_SIZE(&fs_param) > 16 * EXT2_BLOCK_SIZE(&fs_param))
+               fprintf(stderr, "%s", _("\nWarning: bigalloc file systems "
+                               "with a cluster size greater than\n"
+                               "16 times the block size is considered "
+                               "experimental\n"));
 
        /*
         * Since sparse_super is the default, we would only have a problem
@@ -2603,20 +2725,27 @@ profile_error:
                exit(1);
        }
 
+       /*
+        * Warn the user that filesystems with 128-byte inodes will
+        * not work properly beyond 2038.  This can be suppressed via
+        * a boolean in the mke2fs.conf file, and we will disable this
+        * warning for file systems created for the GNU Hurd.
+        */
+       if (inode_size == EXT2_GOOD_OLD_INODE_SIZE &&
+           get_bool_from_profile(fs_types, "warn_y2038_dates", 1))
+               printf(
+_("128-byte inodes cannot handle dates beyond 2038 and are deprecated\n"));
+
        /* Make sure number of inodes specified will fit in 32 bits */
        if (num_inodes == 0) {
                unsigned long long n;
                n = ext2fs_blocks_count(&fs_param) * blocksize / inode_ratio;
                if (n > MAX_32_NUM) {
-                       if (ext2fs_has_feature_64bit(&fs_param))
-                               num_inodes = MAX_32_NUM;
-                       else {
+                       num_inodes = MAX_32_NUM;
+                       if (!ext2fs_has_feature_64bit(&fs_param))
                                com_err(program_name, 0,
-                                       _("too many inodes (%llu), raise "
-                                         "inode ratio?"),
-                                       (unsigned long long) n);
-                               exit(1);
-                       }
+                                       _("too many inodes (%llu), reduced to "
+                                         "%llu"), n, MAX_32_NUM);
                }
        } else if (num_inodes > MAX_32_NUM) {
                com_err(program_name, 0,
@@ -2679,7 +2808,7 @@ static int should_do_undo(const char *name)
        io_channel channel;
        __u16   s_magic;
        struct ext2_super_block super;
-       io_manager manager = unix_io_manager;
+       io_manager manager = default_io_manager;
        int csum_flag, force_undo;
 
        csum_flag = ext2fs_has_feature_metadata_csum(&fs_param) ||
@@ -2813,9 +2942,7 @@ err:
 static int mke2fs_discard_device(ext2_filsys fs)
 {
        struct ext2fs_numeric_progress_struct progress;
-       blk64_t blocks = ext2fs_blocks_count(fs->super);
-       blk64_t count = DISCARD_STEP_MB;
-       blk64_t cur = 0;
+       dgrp_t group;
        int retval = 0;
 
        /*
@@ -2827,22 +2954,26 @@ static int mke2fs_discard_device(ext2_filsys fs)
        if (retval)
                return retval;
 
-       count *= (1024 * 1024);
-       count /= fs->blocksize;
-
        ext2fs_numeric_progress_init(fs, &progress,
                                     _("Discarding device blocks: "),
-                                    blocks);
-       while (cur < blocks) {
-               ext2fs_numeric_progress_update(fs, &progress, cur);
+                                    ext2fs_blocks_count(fs->super));
 
-               if (cur + count > blocks)
-                       count = blocks - cur;
+       for (group = 0; group < fs->group_desc_count; group++) {
+               blk64_t start = ext2fs_group_first_block2(fs, group);
+               blk64_t count = ext2fs_group_blocks_count(fs, group);
+               int retval_discard = 0;
 
-               retval = io_channel_discard(fs->io, cur, count);
-               if (retval)
-                       break;
-               cur += count;
+               retval_discard = io_channel_discard(fs->io, start, count);
+               if (!retval_discard) {
+                       ext2fs_bg_flags_set(fs, group, EXT2_BG_TRIMMED);
+                       ext2fs_group_desc_csum_set(fs, group);
+                       fs->super->s_flags |= EXT2_FLAGS_TRACK_TRIM;
+               } else if (!retval) {
+                       retval = retval_discard;
+               }
+
+               ext2fs_numeric_progress_update(fs, &progress,
+                                       ext2fs_group_last_block2(fs, group));
        }
 
        if (retval) {
@@ -2984,10 +3115,10 @@ int main (int argc, char *argv[])
 #ifdef CONFIG_TESTIO_DEBUG
        if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
                io_ptr = test_io_manager;
-               test_io_backing_manager = unix_io_manager;
+               test_io_backing_manager = default_io_manager;
        } else
 #endif
-               io_ptr = unix_io_manager;
+               io_ptr = default_io_manager;
 
        if (undo_file != NULL || should_do_undo(device_name)) {
                retval = mke2fs_setup_tdb(device_name, &io_ptr);
@@ -3034,6 +3165,16 @@ int main (int argc, char *argv[])
                        _("while setting up superblock"));
                exit(1);
        }
+
+       if (iops_range && iops_count) {
+               ext2fs_set_iops_group(fs, iops_range, iops_count);
+               fs->super->s_flags |= EXT2_FLAGS_HAS_IOPS;
+               ext2fs_mark_super_dirty(fs);
+
+               if (iops_range != iops_array)
+                       free(iops_range);
+       }
+
        fs->progress_ops = &ext2fs_numeric_progress_ops;
 
        /* Set the error behavior */
@@ -3067,6 +3208,19 @@ int main (int argc, char *argv[])
                exit(1);
        }
 
+       if (ext2fs_has_feature_dirdata(fs->super)) {
+               if (ext2fs_has_feature_inline_data(fs->super)) {
+                       printf("%s", _("The dirdata feature can not enabled "
+                                      "with inline data feature.\n"));
+                       exit(1);
+               }
+               if (ext2fs_has_feature_casefold(fs->super)) {
+                       printf("%s", _("The dirdata feature can not enabled "
+                                      "with casefold feature.\n"));
+                       exit(1);
+               }
+       }
+
        /* Calculate journal blocks */
        if (!journal_device && ((journal_size) ||
            ext2fs_has_feature_journal(&fs_param)))
@@ -3080,6 +3234,18 @@ int main (int argc, char *argv[])
                io_channel_set_options(fs->io, opt_string);
        }
 
+       if (assume_storage_prezeroed) {
+               if (verbose)
+                       printf("%s",
+                              _("Assuming the storage device is prezeroed "
+                              "- skipping inode table and journal wipe\n"));
+
+               lazy_itable_init = 1;
+               itable_zeroed = 1;
+               zero_hugefile = 0;
+               journal_flags |= EXT2_MKJOURNAL_LAZYINIT;
+       }
+
        /* Can't undo discard ... */
        if (!noaction && discard && dev_size && (io_ptr != undo_io_manager)) {
                retval = mke2fs_discard_device(fs);
@@ -3380,7 +3546,7 @@ int main (int argc, char *argv[])
 
                retval = ext2fs_open(journal_device, EXT2_FLAG_RW|
                                     EXT2_FLAG_JOURNAL_DEV_OK, 0,
-                                    fs->blocksize, unix_io_manager, &jfs);
+                                    fs->blocksize, default_io_manager, &jfs);
                if (retval) {
                        com_err(program_name, retval,
                                _("while trying to open journal device %s\n"),
@@ -3414,6 +3580,9 @@ int main (int argc, char *argv[])
 
                if (!jparams.num_journal_blocks) {
                        ext2fs_clear_feature_journal(fs->super);
+                       ext2fs_clear_feature_orphan_file(fs->super);
+                       ext2fs_clear_feature_journal(&fs_param);
+                       ext2fs_clear_feature_orphan_file(&fs_param);
                        goto no_journal;
                }
                if (!quiet) {
@@ -3456,6 +3625,23 @@ no_journal:
                fix_cluster_bg_counts(fs);
        if (ext2fs_has_feature_quota(&fs_param))
                create_quota_inodes(fs);
+       if (ext2fs_has_feature_orphan_file(&fs_param)) {
+               if (!ext2fs_has_feature_journal(&fs_param)) {
+                       com_err(program_name, 0, _("cannot set orphan_file "
+                               "feature without a journal."));
+                       exit(1);
+               }
+               if (!orphan_file_blocks) {
+                       orphan_file_blocks =
+                               ext2fs_default_orphan_file_blocks(fs);
+               }
+               retval = ext2fs_create_orphan_file(fs, orphan_file_blocks);
+               if (retval) {
+                       com_err(program_name, retval,
+                               _("while creating orphan file"));
+                       exit(1);
+               }
+       }
 
        retval = mk_hugefiles(fs, device_name);
        if (retval)