* 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 <time.h>
#ifdef __linux__
#include <sys/utsname.h>
-#include <linux/version.h>
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
#endif
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#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"
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] "
"\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);
}
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;
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;
}
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,
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)
sync();
}
}
- ext2fs_zero_blocks2(0, 0, 0, 0, 0);
ext2fs_numeric_progress_close(fs, &progress,
_("done \n"));
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:
if (*p || num_backups > 2) {
fprintf(stderr,
_("Invalid # of backup "
- "superbocks: %s\n"),
+ "superblocks: %s\n"),
arg);
r_usage++;
continue;
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|
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
};
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)
{
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) {
}
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);
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;
_("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);
_("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 */
/* Print version number and exit */
show_version_only++;
break;
+ case 'z':
+ undo_file = optarg;
+ break;
default:
usage();
}
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) {
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);
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);
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);
}
}
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)
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 */
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;
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)) {
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);
}
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
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)
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;
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;
#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);
}
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 */
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;
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)
}
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
}
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 &
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 */
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"));
"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."));