Whamcloud - gitweb
libext2fs: automatically enable meta_bg to avoid filling up BG 0
[tools/e2fsprogs.git] / misc / mke2fs.c
index f09351d..179a4d1 100644 (file)
@@ -52,13 +52,14 @@ extern int optind;
 #include "ext2fs/ext2fsP.h"
 #include "uuid/uuid.h"
 #include "util.h"
-#include "profile.h"
-#include "prof_err.h"
+#include "support/nls-enable.h"
+#include "support/plausible.h"
+#include "support/profile.h"
+#include "support/prof_err.h"
 #include "../version.h"
-#include "quota/quotaio.h"
+#include "support/quotaio.h"
 #include "mke2fs.h"
 #include "create_inode.h"
-#include "nls-enable.h"
 
 #define STRIDE_LENGTH 8
 
@@ -109,6 +110,7 @@ char *journal_device;
 static int sync_kludge;        /* Set using the MKE2FS_SYNC env. option */
 char **fs_types;
 const char *root_dir;  /* Copy files from the specified directory */
+static char *undo_file;
 
 static profile_t       profile;
 
@@ -128,7 +130,8 @@ static void usage(void)
        "[-M last-mounted-directory]\n\t[-O feature[,...]] "
        "[-r fs-revision] [-E extended-option[,...]]\n"
        "\t[-t fs-type] [-T usage-type ] [-U UUID] [-e errors_behavior]"
-       "[-jnqvDFKSV] device [blocks-count]\n"),
+       "[-z undo_file]\n"
+       "\t[-jnqvDFKSV] device [blocks-count]\n"),
                program_name);
        exit(1);
 }
@@ -192,7 +195,7 @@ static int is_before_linux_ver(unsigned int major, unsigned int minor,
        if (linux_version_code == 0)
                return 0;
 
-       return linux_version_code < KERNEL_VERSION(major, minor, rev);
+       return linux_version_code < (int) KERNEL_VERSION(major, minor, rev);
 }
 #else
 static int is_before_linux_ver(unsigned int major, unsigned int minor,
@@ -420,12 +423,14 @@ static void write_inode_tables(ext2_filsys fs, int lazy_flag, int itable_zeroed)
                        ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_ZEROED);
                        ext2fs_group_desc_csum_set(fs, i);
                }
-               retval = ext2fs_zero_blocks2(fs, blk, num, &blk, &num);
-               if (retval) {
-                       fprintf(stderr, _("\nCould not write %d "
-                                 "blocks in inode table starting at %llu: %s\n"),
-                               num, blk, error_message(retval));
-                       exit(1);
+               if (!itable_zeroed) {
+                       retval = ext2fs_zero_blocks2(fs, blk, num, &blk, &num);
+                       if (retval) {
+                               fprintf(stderr, _("\nCould not write %d "
+                                         "blocks in inode table starting at %llu: %s\n"),
+                                       num, blk, error_message(retval));
+                               exit(1);
+                       }
                }
                if (sync_kludge) {
                        if (sync_kludge == 1)
@@ -434,7 +439,6 @@ static void write_inode_tables(ext2_filsys fs, int lazy_flag, int itable_zeroed)
                                sync();
                }
        }
-       ext2fs_zero_blocks2(0, 0, 0, 0, 0);
        ext2fs_numeric_progress_close(fs, &progress,
                                      _("done                            \n"));
 
@@ -623,7 +627,6 @@ static void create_journal_dev(ext2_filsys fs)
                count -= c;
                ext2fs_numeric_progress_update(fs, &progress, blk);
        }
-       ext2fs_zero_blocks2(0, 0, 0, 0, 0);
 
        ext2fs_numeric_progress_close(fs, &progress, NULL);
 write_superblock:
@@ -1075,7 +1078,8 @@ static __u32 ok_features[3] = {
                EXT4_FEATURE_INCOMPAT_FLEX_BG|
                EXT4_FEATURE_INCOMPAT_MMP |
                EXT4_FEATURE_INCOMPAT_64BIT|
-               EXT4_FEATURE_INCOMPAT_INLINE_DATA,
+               EXT4_FEATURE_INCOMPAT_INLINE_DATA|
+               EXT4_FEATURE_INCOMPAT_ENCRYPT,
        /* R/O compat */
        EXT2_FEATURE_RO_COMPAT_LARGE_FILE|
                EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
@@ -1084,9 +1088,7 @@ static __u32 ok_features[3] = {
                EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|
                EXT4_FEATURE_RO_COMPAT_GDT_CSUM|
                EXT4_FEATURE_RO_COMPAT_BIGALLOC|
-#ifdef CONFIG_QUOTA
                EXT4_FEATURE_RO_COMPAT_QUOTA|
-#endif
                EXT4_FEATURE_RO_COMPAT_METADATA_CSUM
 };
 
@@ -1392,11 +1394,11 @@ static const char *default_files[] = { "<default>", 0 };
  * device's alignment offset, if any, or a negative error.
  */
 static int get_device_geometry(const char *file,
-                              struct ext2_super_block *fs_param,
-                              int psector_size)
+                              struct ext2_super_block *param,
+                              unsigned int psector_size)
 {
        int rc = -1;
-       int blocksize;
+       unsigned int blocksize;
        blkid_probe pr;
        blkid_topology tp;
        unsigned long min_io;
@@ -1417,7 +1419,7 @@ static int get_device_geometry(const char *file,
 
        min_io = blkid_topology_get_minimum_io_size(tp);
        opt_io = blkid_topology_get_optimal_io_size(tp);
-       blocksize = EXT2_BLOCK_SIZE(fs_param);
+       blocksize = EXT2_BLOCK_SIZE(param);
        if ((min_io == 0) && (psector_size > blocksize))
                min_io = psector_size;
        if ((opt_io == 0) && min_io)
@@ -1427,9 +1429,9 @@ static int get_device_geometry(const char *file,
 
        /* setting stripe/stride to blocksize is pointless */
        if (min_io > blocksize)
-               fs_param->s_raid_stride = min_io / blocksize;
+               param->s_raid_stride = min_io / blocksize;
        if (opt_io > blocksize)
-               fs_param->s_raid_stripe_width = opt_io / blocksize;
+               param->s_raid_stripe_width = opt_io / blocksize;
 
        rc = blkid_topology_get_alignment_offset(tp);
 out:
@@ -1550,7 +1552,7 @@ profile_error:
        }
 
        while ((c = getopt (argc, argv,
-                   "b:ce:g:i:jl:m:no:qr:s:t:d:vC:DE:FG:I:J:KL:M:N:O:R:ST:U:V")) != EOF) {
+                   "b:ce:g:i:jl:m:no:qr:s:t:d:vC:DE:FG:I:J:KL:M:N:O:R:ST:U:Vz:")) != EOF) {
                switch (c) {
                case 'b':
                        blocksize = parse_num_blocks2(optarg, -1);
@@ -1773,6 +1775,9 @@ profile_error:
                        /* Print version number and exit */
                        show_version_only++;
                        break;
+               case 'z':
+                       undo_file = optarg;
+                       break;
                default:
                        usage();
                }
@@ -1928,7 +1933,7 @@ profile_error:
        tmp = NULL;
        if (fs_param.s_rev_level != EXT2_GOOD_OLD_REV) {
                tmp = get_string_from_profile(fs_types, "base_features",
-                     "sparse_super,filetype,resize_inode,dir_index");
+                     "sparse_super,large_file,filetype,resize_inode,dir_index");
                edit_feature(tmp, &fs_param.s_feature_compat);
                free(tmp);
 
@@ -2174,7 +2179,8 @@ profile_error:
        }
 
 #ifdef HAVE_BLKID_PROBE_GET_TOPOLOGY
-       retval = get_device_geometry(device_name, &fs_param, psector_size);
+       retval = get_device_geometry(device_name, &fs_param,
+                                    (unsigned int) psector_size);
        if (retval < 0) {
                fprintf(stderr,
                        _("warning: Unable to get device geometry for %s\n"),
@@ -2212,6 +2218,14 @@ profile_error:
                        blocksize, sys_page_size);
        }
 
+       /* Metadata checksumming wasn't totally stable before 3.18. */
+       if (is_before_linux_ver(3, 18, 0) &&
+           (fs_param.s_feature_ro_compat &
+                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+               fprintf(stderr, _("Suggestion: Use Linux kernel >= 3.18 for "
+                       "improved stability of the metadata and journal "
+                       "checksum features.\n"));
+
        /*
         * On newer kernels we do have lazy_itable_init support. So pick the
         * right default in case ext4 module is not loaded.
@@ -2359,7 +2373,8 @@ profile_error:
             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"),
+                       _("%d byte inodes are too small for inline data; "
+                         "specify larger size"),
                        fs_param.s_inode_size);
                exit(1);
        }
@@ -2482,6 +2497,21 @@ static int mke2fs_setup_tdb(const char *name, io_manager *io_ptr)
        char *dev_name, *tmp_name;
        int free_tdb_dir = 0;
 
+       /* (re)open a specific undo file */
+       if (undo_file && undo_file[0] != 0) {
+               retval = set_undo_io_backing_manager(*io_ptr);
+               if (retval)
+                       goto err;
+               *io_ptr = undo_io_manager;
+               retval = set_undo_io_backup_file(undo_file);
+               if (retval)
+                       goto err;
+               printf(_("Overwriting existing filesystem; this can be undone "
+                        "using the command:\n"
+                        "    e2undo %s %s\n\n"), undo_file, name);
+               return retval;
+       }
+
        /*
         * Configuration via a conf file would be
         * nice
@@ -2515,10 +2545,14 @@ static int mke2fs_setup_tdb(const char *name, io_manager *io_ptr)
 
        if ((unlink(tdb_file) < 0) && (errno != ENOENT)) {
                retval = errno;
+               com_err(program_name, retval,
+                       _("while trying to delete %s"), tdb_file);
                goto errout;
        }
 
-       set_undo_io_backing_manager(*io_ptr);
+       retval = set_undo_io_backing_manager(*io_ptr);
+       if (retval)
+               goto errout;
        *io_ptr = undo_io_manager;
        retval = set_undo_io_backup_file(tdb_file);
        if (retval)
@@ -2536,6 +2570,7 @@ errout:
        if (free_tdb_dir)
                free(tdb_dir);
        free(tdb_file);
+err:
        com_err(program_name, retval, "%s",
                _("while trying to setup undo file\n"));
        return retval;
@@ -2707,7 +2742,7 @@ int main (int argc, char *argv[])
 #endif
                io_ptr = unix_io_manager;
 
-       if (should_do_undo(device_name)) {
+       if (undo_file != NULL || should_do_undo(device_name)) {
                retval = mke2fs_setup_tdb(device_name, &io_ptr);
                if (retval)
                        exit(1);
@@ -2900,6 +2935,15 @@ int main (int argc, char *argv[])
                        sizeof(fs->super->s_last_mounted));
        }
 
+       /* Set current default encryption algorithms for data and
+        * filename encryption */
+       if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_ENCRYPT) {
+               fs->super->s_encrypt_algos[0] =
+                       EXT4_ENCRYPTION_MODE_AES_256_XTS;
+               fs->super->s_encrypt_algos[1] =
+                       EXT4_ENCRYPTION_MODE_AES_256_CTS;
+       }
+
        if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
                fs->super->s_checksum_type = EXT2_CRC32C_CHKSUM;
@@ -2947,9 +2991,14 @@ int main (int argc, char *argv[])
        }
 
        if (super_only) {
+               check_plausibility(device_name, CHECK_FS_EXIST, NULL);
+               printf(_("%s may be further corrupted by superblock rewrite\n"),
+                      device_name);
+               if (!force)
+                       proceed_question(proceed_delay);
                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
@@ -3102,7 +3151,7 @@ no_journal:
                                     EXT2_ROOT_INO);
                if (retval) {
                        com_err(program_name, retval, "%s",
-                               _("\nError while populating file system\n"));
+                               _("while populating file system"));
                        exit(1);
                } else if (!quiet)
                        printf("%s", _("done\n"));