X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=misc%2Fmke2fs.c;h=68fbb66523b2d1dd11c62520939e76263f3c6cfc;hb=ec794020acd00cf62d215d216449abeefe8ca320;hp=522df1baa6edf9241522d0e2838d6f40362f565d;hpb=ba08cb996a10a8f5e72625ed054cb029571d84e0;p=tools%2Fe2fsprogs.git diff --git a/misc/mke2fs.c b/misc/mke2fs.c index 522df1b..68fbb66 100644 --- a/misc/mke2fs.c +++ b/misc/mke2fs.c @@ -16,7 +16,7 @@ * 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 @@ -26,7 +26,7 @@ #include #ifdef __linux__ #include -#include +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) #endif #ifdef HAVE_GETOPT_H #include @@ -52,10 +52,12 @@ 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" @@ -108,11 +110,14 @@ 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; static int sys_page_size = 4096; +static int errors_behavior = 0; + static void usage(void) { fprintf(stderr, _("Usage: %s [-c|-l filename] [-b block-size] " @@ -124,8 +129,9 @@ static void usage(void) "\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] [-T usage-type ] [-U UUID] " - "[-jnqvDFKSV] device [blocks-count]\n"), + "\t[-t fs-type] [-T usage-type ] [-U UUID] [-e errors_behavior]" + "[-z undo_file]\n" + "\t[-jnqvDFKSV] device [blocks-count]\n"), program_name); exit(1); } @@ -174,7 +180,8 @@ static int parse_version_number(const char *s) return KERNEL_VERSION(major, minor, rev); } -static int is_before_linux_ver(unsigned int major, unsigned int minor) +static int is_before_linux_ver(unsigned int major, unsigned int minor, + unsigned int rev) { struct utsname ut; static int linux_version_code = -1; @@ -188,10 +195,11 @@ 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, 0); + return linux_version_code < KERNEL_VERSION(major, minor, rev); } #else -static int is_before_linux_ver(unsigned int major, unsigned int minor) +static int is_before_linux_ver(unsigned int major, unsigned int minor, + unsigned int rev) { return 0; } @@ -339,13 +347,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, @@ -417,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) @@ -431,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")); @@ -620,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: @@ -862,7 +868,7 @@ static void parse_extended_opts(struct ext2_super_block *param, if (*p || num_backups > 2) { fprintf(stderr, _("Invalid # of backup " - "superbocks: %s\n"), + "superblocks: %s\n"), arg); r_usage++; continue; @@ -1072,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| @@ -1081,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 }; @@ -1345,6 +1350,18 @@ int get_int_from_profile(char **types, const char *opt, int def_val) return ret; } +static unsigned int get_uint_from_profile(char **types, const char *opt, + unsigned int def_val) +{ + unsigned int ret; + char **cpp; + + profile_get_uint(profile, "defaults", opt, 0, def_val, &ret); + for (cpp = types; *cpp; cpp++) + profile_get_uint(profile, "fs_types", *cpp, opt, ret, &ret); + return ret; +} + static double get_double_from_profile(char **types, const char *opt, double def_val) { @@ -1522,7 +1539,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)) + if (is_before_linux_ver(2, 2, 0)) fs_param.s_rev_level = 0; if (argc && *argv) { @@ -1535,7 +1552,7 @@ profile_error: } while ((c = getopt (argc, argv, - "b:cg: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); @@ -1578,6 +1595,20 @@ profile_error: case 'E': extended_opts = optarg; break; + case 'e': + if (strcmp(optarg, "continue") == 0) + errors_behavior = EXT2_ERRORS_CONTINUE; + else if (strcmp(optarg, "remount-ro") == 0) + errors_behavior = EXT2_ERRORS_RO; + else if (strcmp(optarg, "panic") == 0) + errors_behavior = EXT2_ERRORS_PANIC; + else { + com_err(program_name, 0, + _("bad error behavior - %s"), + optarg); + usage(); + } + break; case 'F': force++; break; @@ -1607,6 +1638,12 @@ profile_error: _("flex_bg size must be a power of 2")); exit(1); } + if (flex_bg_size > MAX_32_NUM) { + com_err(program_name, 0, + _("flex_bg size (%lu) must be less than" + " or equal to 2^31"), flex_bg_size); + exit(1); + } break; case 'i': inode_ratio = strtoul(optarg, &tmp, 0); @@ -1696,6 +1733,11 @@ profile_error: _("bad revision level - %s"), optarg); exit(1); } + if (r_opt > EXT2_MAX_SUPP_REV) { + com_err(program_name, EXT2_ET_REV_TOO_HIGH, + _("while trying to create revision %d"), r_opt); + exit(1); + } fs_param.s_rev_level = r_opt; break; case 's': /* deprecated */ @@ -1733,6 +1775,9 @@ profile_error: /* Print version number and exit */ show_version_only++; break; + case 'z': + undo_file = optarg; + break; default: usage(); } @@ -1786,7 +1831,7 @@ profile_error: printf(_("Using journal device's blocksize: %d\n"), blocksize); fs_param.s_log_block_size = int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE); - ext2fs_close(jfs); + ext2fs_close_free(&jfs); } if (optind < argc) { @@ -1811,6 +1856,8 @@ profile_error: flags |= CHECK_FS_EXIST; if (!quiet) flags |= VERBOSE_CREATE; + if (fs_blocks_count == 0) + flags |= NO_SIZE; if (!check_plausibility(device_name, flags, &is_device) && !force) proceed_question(proceed_delay); @@ -1886,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); @@ -1926,20 +1973,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); } } @@ -1974,7 +2021,7 @@ profile_error: if (use_bsize == -1) { use_bsize = sys_page_size; - if (is_before_linux_ver(2, 6) && use_bsize > 4096) + if (is_before_linux_ver(2, 6, 0) && use_bsize > 4096) use_bsize = 4096; } if (lsector_size && use_bsize < lsector_size) @@ -2083,7 +2130,8 @@ profile_error: reserved_ratio = 0; fs_param.s_feature_incompat = EXT3_FEATURE_INCOMPAT_JOURNAL_DEV; fs_param.s_feature_compat = 0; - fs_param.s_feature_ro_compat = 0; + fs_param.s_feature_ro_compat &= + EXT4_FEATURE_RO_COMPAT_METADATA_CSUM; } /* Check the user's mkfs options for 64bit */ @@ -2169,7 +2217,23 @@ profile_error: blocksize, sys_page_size); } - lazy_itable_init = 0; + /* 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. + */ + if (is_before_linux_ver(2, 6, 37)) + lazy_itable_init = 0; + else + lazy_itable_init = 1; + if (access("/sys/fs/ext4/features/lazy_itable_init", R_OK) == 0) lazy_itable_init = 1; @@ -2274,8 +2338,8 @@ profile_error: inode_size = get_int_from_profile(fs_types, "inode_size", 0); if (!flex_bg_size && (fs_param.s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG)) - flex_bg_size = get_int_from_profile(fs_types, - "flex_bg_size", 16); + flex_bg_size = get_uint_from_profile(fs_types, + "flex_bg_size", 16); if (flex_bg_size) { if (!(fs_param.s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG)) { @@ -2308,7 +2372,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); } @@ -2431,6 +2496,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 @@ -2464,10 +2544,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) @@ -2485,6 +2569,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; @@ -2591,6 +2676,38 @@ static int create_quota_inodes(ext2_filsys fs) return 0; } +static errcode_t set_error_behavior(ext2_filsys fs) +{ + char *arg = NULL; + short errors = fs->super->s_errors; + + arg = get_string_from_profile(fs_types, "errors", NULL); + if (arg == NULL) + goto try_user; + + if (strcmp(arg, "continue") == 0) + errors = EXT2_ERRORS_CONTINUE; + else if (strcmp(arg, "remount-ro") == 0) + errors = EXT2_ERRORS_RO; + else if (strcmp(arg, "panic") == 0) + errors = EXT2_ERRORS_PANIC; + else { + com_err(program_name, 0, + _("bad error behavior in profile - %s"), + arg); + free(arg); + return EXT2_ET_INVALID_ARGUMENT; + } + free(arg); + +try_user: + if (errors_behavior) + errors = errors_behavior; + + fs->super->s_errors = errors; + return 0; +} + int main (int argc, char *argv[]) { errcode_t retval = 0; @@ -2624,7 +2741,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); @@ -2655,23 +2772,32 @@ int main (int argc, char *argv[]) } fs->progress_ops = &ext2fs_numeric_progress_ops; + /* Set the error behavior */ + retval = set_error_behavior(fs); + if (retval) + usage(); + /* Check the user's mkfs options for metadata checksumming */ if (!quiet && + !EXT2_HAS_INCOMPAT_FEATURE(fs->super, + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) && EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 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 */ @@ -2808,6 +2934,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; @@ -2821,7 +2956,8 @@ int main (int argc, char *argv[]) if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) { create_journal_dev(fs); - exit(ext2fs_close(fs) ? 1 : 0); + printf("\n"); + exit(ext2fs_close_free(&fs) ? 1 : 0); } if (bad_blocks_filename) @@ -2854,9 +2990,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 @@ -2942,7 +3083,7 @@ int main (int argc, char *argv[]) } if (!quiet) printf("%s", _("done\n")); - ext2fs_close(jfs); + ext2fs_close_free(&jfs); free(journal_device); } else if ((journal_size) || (fs_param.s_feature_compat & @@ -2997,7 +3138,7 @@ no_journal: EXT4_FEATURE_RO_COMPAT_QUOTA)) create_quota_inodes(fs); - retval = mk_hugefiles(fs); + retval = mk_hugefiles(fs, device_name); if (retval) com_err(program_name, retval, "while creating huge files"); /* Copy files from the specified directory */ @@ -3009,7 +3150,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")); @@ -3020,7 +3161,7 @@ no_journal: "filesystem accounting information: ")); checkinterval = fs->super->s_checkinterval; max_mnt_count = fs->super->s_max_mnt_count; - retval = ext2fs_close(fs); + retval = ext2fs_close_free(&fs); if (retval) { fprintf(stderr, "%s", _("\nWarning, had trouble writing out superblocks."));