summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorValerie Aurora Henson <vaurora@redhat.com>2010-01-31 23:33:40 -0500
committerTheodore Ts'o <tytso@mit.edu>2010-01-31 23:33:40 -0500
commit1ee6d96eedb1c904e156a9ab7818c23be55ba4ec (patch)
tree6eb9f99bf5d51fd20f11d48da9a76c753629d4b0
parentc1e5c4a7e45d2a7aabdc0368abceb9a6056924d3 (diff)
downloade2fsprogs-pu.tar.gz
Fix bug in selecting fs type, resulting in 1K blocksizepu
One of the previous 64-bit patches (20ce9ade: 64-bit mke2fs cleanup,top of the 'js/new-64-bit' branch) moved the fs type and feature detection code to precede the determination of the device size so that we could check the 64bit flag if the device size would overflow 32 bits. Unfortunately, the fs type code uses the device size to determine the default set of parameters, and since the device size wasn't set yet, it was clearly "small enough" to fit the floppy profile. The solution is a bit complex. One problem is that you can't set the blocks count to > 32 bits if the 64bit feature isn't enabled. So I created a function to automatically set the 64bit feature if necessary. After we parse the user supplied options, I check if the 64bit feature has been disabled and bail out then. Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r--misc/mke2fs.c150
1 files changed, 92 insertions, 58 deletions
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index f5a70434..81fff1df 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -884,7 +884,7 @@ static char **parse_fs_type(const char *fs_type,
char *cp, *t;
const char *size_type;
struct str_list list;
- unsigned long meg;
+ blk64_t meg;
int is_hurd = 0;
if (init_list(&list))
@@ -1021,6 +1021,22 @@ static int get_bool_from_profile(char **fs_types, const char *opt, int def_val)
return ret;
}
+/*
+ * When setting the block count for the first time while creating a
+ * file system, we have to enable the file system's 64bit feature if
+ * the block count is greater than 32 bits. Otherwise, only the lower
+ * 32 bits of the block count gets set. Later, we have to check if
+ * the 64bit feature was explicitly disabled and bail out.
+ */
+
+static void set_blocks_count_enable_64bit(struct ext2_super_block *sb,
+ blk64_t count)
+{
+ if (count > ~0U)
+ sb->s_feature_incompat |= EXT4_FEATURE_INCOMPAT_64BIT;
+ ext2fs_blocks_count_set(sb, count);
+}
+
extern const char *mke2fs_default_profile;
static const char *default_files[] = { "<default>", 0 };
@@ -1404,8 +1420,9 @@ static void PRS(int argc, char *argv[])
blocksize, sys_page_size);
}
if (optind < argc) {
- ext2fs_blocks_count_set(&fs_param, parse_num_blocks2(argv[optind++],
- fs_param.s_log_block_size));
+ set_blocks_count_enable_64bit(&fs_param,
+ parse_num_blocks2(argv[optind++],
+ fs_param.s_log_block_size));
if (!ext2fs_blocks_count(&fs_param)) {
com_err(program_name, 0, _("invalid blocks count - %s"),
argv[optind - 1]);
@@ -1421,38 +1438,6 @@ static void PRS(int argc, char *argv[])
fs_param.s_log_frag_size = fs_param.s_log_block_size;
- fs_types = parse_fs_type(fs_type, usage_types, &fs_param, argv[0]);
- if (!fs_types) {
- fprintf(stderr, _("Failed to parse fs types list\n"));
- exit(1);
- }
-
- /* Figure out what features should be enabled */
-
- 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");
- edit_feature(tmp, &fs_param.s_feature_compat);
- free(tmp);
-
- for (cpp = fs_types; *cpp; cpp++) {
- tmp = NULL;
- profile_get_string(profile, "fs_types", *cpp,
- "features", "", &tmp);
- if (tmp && *tmp)
- edit_feature(tmp, &fs_param.s_feature_compat);
- if (tmp)
- free(tmp);
- }
- tmp = get_string_from_profile(fs_types, "default_features",
- "");
- }
- edit_feature(fs_features ? fs_features : tmp,
- &fs_param.s_feature_compat);
- if (tmp)
- free(tmp);
-
if (noaction && ext2fs_blocks_count(&fs_param)) {
dev_size = ext2fs_blocks_count(&fs_param);
retval = 0;
@@ -1461,11 +1446,13 @@ static void PRS(int argc, char *argv[])
retval = ext2fs_get_device_size2(device_name,
EXT2_BLOCK_SIZE(&fs_param),
&dev_size);
- if (!(fs_param.s_feature_incompat &
- EXT4_FEATURE_INCOMPAT_64BIT) && dev_size >= (1ULL << 32))
- retval = EFBIG;
-
- if ((retval == EFBIG) &&
+ /* Also retry if the block size is 1K and the number
+ * of blocks is greater than 2^32 - no point in
+ * setting 64bit if not necessary. For the 4
+ * bit-range of file systems in which this will make a
+ * difference.
+ */
+ if (((retval == EFBIG) || (dev_size > ~0U)) &&
(blocksize == 0) &&
(fs_param.s_log_block_size == 0)) {
fs_param.s_log_block_size = 2;
@@ -1475,24 +1462,16 @@ static void PRS(int argc, char *argv[])
}
if (retval == EFBIG) {
- blk64_t big_dev_size;
-
- if (blocksize < 4096) {
- fs_param.s_log_block_size = 2;
- blocksize = 4096;
- }
- retval = ext2fs_get_device_size2(device_name,
- EXT2_BLOCK_SIZE(&fs_param), &big_dev_size);
- if (retval)
- goto get_size_failure;
- if (big_dev_size == (1ULL << 32)) {
- dev_size = (blk_t) (big_dev_size - 1);
- goto got_size;
- }
- fprintf(stderr, _("%s: Size of device %s too big "
- "to be expressed in 32 bits\n\t"
+#ifdef HAVE_OPEN64
+ char *bits = "64";
+#else
+ char *bits = "32";
+#endif
+ fprintf(stderr, _("%s: Size of device %s too big "
+ "to be expressed in %s bits\n\t"
"using a blocksize of %d.\n"),
- program_name, device_name, EXT2_BLOCK_SIZE(&fs_param));
+ program_name, device_name, bits,
+ EXT2_BLOCK_SIZE(&fs_param));
exit(1);
}
get_size_failure:
@@ -1522,7 +1501,7 @@ got_size:
));
exit(1);
}
- ext2fs_blocks_count_set(&fs_param, dev_size);
+ set_blocks_count_enable_64bit(&fs_param, dev_size);
if (sys_page_size > EXT2_BLOCK_SIZE(&fs_param)) {
blk64_t tmp = ext2fs_blocks_count(&fs_param);
@@ -1537,6 +1516,52 @@ got_size:
proceed_question();
}
+ fs_types = parse_fs_type(fs_type, usage_types, &fs_param, argv[0]);
+ if (!fs_types) {
+ fprintf(stderr, _("Failed to parse fs types list\n"));
+ exit(1);
+ }
+
+ /* Figure out what features should be enabled */
+
+ 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");
+ edit_feature(tmp, &fs_param.s_feature_compat);
+ free(tmp);
+
+ for (cpp = fs_types; *cpp; cpp++) {
+ tmp = NULL;
+ profile_get_string(profile, "fs_types", *cpp,
+ "features", "", &tmp);
+ if (tmp && *tmp)
+ edit_feature(tmp, &fs_param.s_feature_compat);
+ if (tmp)
+ free(tmp);
+ }
+ tmp = get_string_from_profile(fs_types, "default_features",
+ "");
+ }
+ edit_feature(fs_features ? fs_features : tmp,
+ &fs_param.s_feature_compat);
+ if (tmp)
+ free(tmp);
+
+ /* If the user deliberately cleared the 64-bit flag, then the
+ * file system size might be too large to be represented in 32
+ * bits. */
+ if (!(fs_param.s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) &&
+ fs_param.s_blocks_count_hi) {
+ fprintf(stderr, _("%s: Size of device %s too big "
+ "to be expressed in 32 bits\n\t"
+ "using a blocksize of %d and 64 bit "
+ "feature is disabled.\n"),
+ program_name, device_name,
+ EXT2_BLOCK_SIZE(&fs_param));
+ exit(1);
+ }
+
if (fs_param.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
fs_types[0] = strdup("journal");
fs_types[1] = 0;
@@ -1611,6 +1636,14 @@ got_size:
if ((tmp = getenv("MKE2FS_DEVICE_SECTSIZE")) != NULL)
sector_size = atoi(tmp);
+ /* OMG. We *still* haven't figured out the blocksize. When
+ * we counted the number of blocks in the file system, we were
+ * using a block size of 1024 (EXT2FS_MIN_BLOCK_SIZE), so the
+ * number of blocks will be less than or equal to the previous
+ * number of blocks. Which is a long way of saying that we
+ * don't have to worry about the blocks count becoming 64bit.
+ */
+
if (blocksize <= 0) {
use_bsize = get_int_from_profile(fs_types, "blocksize", 4096);
@@ -1729,6 +1762,7 @@ got_size:
if (n > ~0U) {
if (fs_param.s_feature_incompat &
EXT4_FEATURE_INCOMPAT_64BIT)
+ /* XXX FIXME-64 How is this okay? */
num_inodes = ~0U;
else {
com_err(program_name, 0,