summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2011-06-10 18:57:22 -0400
committerTheodore Ts'o <tytso@mit.edu>2011-06-10 18:57:22 -0400
commitc6ed60cdeb1355a884f635ac8118c8f330e2ba68 (patch)
tree5a5d56df9d0a091e572447532573ac1aed1cb22e
parent4a2a9b70c89891a146bcb9cee3f29572ca2e1370 (diff)
downloade2fsprogs-c6ed60cdeb1355a884f635ac8118c8f330e2ba68.tar.gz
mke2fs: support creating bigalloc file systems
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r--lib/ext2fs/initialize.c58
-rw-r--r--misc/mke2fs.c71
2 files changed, 105 insertions, 24 deletions
diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c
index cda6b6ef..efe03be4 100644
--- a/lib/ext2fs/initialize.c
+++ b/lib/ext2fs/initialize.c
@@ -94,6 +94,7 @@ errcode_t ext2fs_initialize(const char *name, int flags,
blk_t numblocks;
int rsv_gdt;
int csum_flag;
+ int bigalloc_flag;
int io_flags;
char *buf = 0;
char c;
@@ -134,13 +135,26 @@ errcode_t ext2fs_initialize(const char *name, int flags,
#define set_field(field, default) (super->field = param->field ? \
param->field : (default))
+#define assign_field(field) (super->field = param->field)
super->s_magic = EXT2_SUPER_MAGIC;
super->s_state = EXT2_VALID_FS;
- set_field(s_log_block_size, 0); /* default blocksize: 1024 bytes */
- set_field(s_log_cluster_size, 0);
- set_field(s_first_data_block, super->s_log_block_size ? 0 : 1);
+ bigalloc_flag = EXT2_HAS_RO_COMPAT_FEATURE(param,
+ EXT4_FEATURE_RO_COMPAT_BIGALLOC);
+
+ assign_field(s_log_block_size);
+
+ if (bigalloc_flag) {
+ set_field(s_log_cluster_size, super->s_log_block_size+4);
+ if (super->s_log_block_size > super->s_log_cluster_size) {
+ retval = EXT2_ET_INVALID_ARGUMENT;
+ goto cleanup;
+ }
+ } else
+ super->s_log_cluster_size = super->s_log_block_size;
+
+ set_field(s_first_data_block, super->s_log_cluster_size ? 0 : 1);
set_field(s_max_mnt_count, 0);
set_field(s_errors, EXT2_ERRORS_DEFAULT);
set_field(s_feature_compat, 0);
@@ -185,13 +199,35 @@ errcode_t ext2fs_initialize(const char *name, int flags,
fs->cluster_ratio_bits = super->s_log_cluster_size -
super->s_log_block_size;
- /* default: (fs->blocksize*8) blocks/group, up to 2^16 (GDT limit) */
- set_field(s_blocks_per_group, fs->blocksize * 8);
- if (super->s_blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(super))
- super->s_blocks_per_group = EXT2_MAX_BLOCKS_PER_GROUP(super);
- super->s_clusters_per_group = super->s_blocks_per_group;
+ if (bigalloc_flag) {
+ if (param->s_blocks_per_group &&
+ param->s_clusters_per_group &&
+ ((param->s_clusters_per_group * EXT2FS_CLUSTER_RATIO(fs)) !=
+ param->s_blocks_per_group)) {
+ retval = EXT2_ET_INVALID_ARGUMENT;
+ goto cleanup;
+ }
+ if (param->s_clusters_per_group)
+ assign_field(s_clusters_per_group);
+ else if (param->s_blocks_per_group)
+ super->s_clusters_per_group =
+ param->s_blocks_per_group /
+ EXT2FS_CLUSTER_RATIO(fs);
+ else
+ super->s_clusters_per_group = fs->blocksize * 8;
+ if (super->s_clusters_per_group > EXT2_MAX_CLUSTERS_PER_GROUP(super))
+ super->s_blocks_per_group = EXT2_MAX_CLUSTERS_PER_GROUP(super);
+ super->s_blocks_per_group = EXT2FS_C2B(fs,
+ super->s_clusters_per_group);
+ } else {
+ set_field(s_blocks_per_group, fs->blocksize * 8);
+ if (super->s_blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(super))
+ super->s_blocks_per_group = EXT2_MAX_BLOCKS_PER_GROUP(super);
+ super->s_clusters_per_group = super->s_blocks_per_group;
+ }
- ext2fs_blocks_count_set(super, ext2fs_blocks_count(param));
+ ext2fs_blocks_count_set(super, ext2fs_blocks_count(param) &
+ ~((blk64_t) EXT2FS_CLUSTER_MASK(fs)));
ext2fs_r_blocks_count_set(super, ext2fs_r_blocks_count(param));
if (ext2fs_r_blocks_count(super) >= ext2fs_blocks_count(param)) {
retval = EXT2_ET_INVALID_ARGUMENT;
@@ -247,7 +283,7 @@ retry:
*/
ipg = ext2fs_div_ceil(super->s_inodes_count, fs->group_desc_count);
if (ipg > fs->blocksize * 8) {
- if (super->s_blocks_per_group >= 256) {
+ if (!bigalloc_flag && super->s_blocks_per_group >= 256) {
/* Try again with slightly different parameters */
super->s_blocks_per_group -= 8;
ext2fs_blocks_count_set(super,
@@ -365,7 +401,7 @@ ipg_retry:
strcpy(buf, "block bitmap for ");
strcat(buf, fs->device_name);
- retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
+ retval = ext2fs_allocate_subcluster_bitmap(fs, buf, &fs->block_map);
if (retval)
goto cleanup;
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 0b7487f4..a246ec18 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -298,7 +298,7 @@ _("Warning: the backup superblock/group descriptors at block %u contain\n"
exit(1);
}
while (ext2fs_badblocks_list_iterate(bb_iter, &blk))
- ext2fs_mark_block_bitmap2(fs->block_map, blk);
+ ext2fs_mark_block_bitmap2(fs->block_map, EXT2FS_B2C(fs, blk));
ext2fs_badblocks_list_iterate_end(bb_iter);
}
@@ -816,7 +816,8 @@ static __u32 ok_features[3] = {
EXT4_FEATURE_RO_COMPAT_DIR_NLINK|
EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE|
EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|
- EXT4_FEATURE_RO_COMPAT_GDT_CSUM
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM|
+ EXT4_FEATURE_RO_COMPAT_BIGALLOC
};
@@ -1268,7 +1269,7 @@ profile_error:
}
while ((c = getopt (argc, argv,
- "b:cf:g:G:i:jl:m:no:qr:s:t:vE:FI:J:KL:M:N:O:R:ST:U:V")) != EOF) {
+ "b:cg:i:jl:m:no:qr:s:t:vC:E:FG:I:J:KL:M:N:O:R:ST:U:V")) != EOF) {
switch (c) {
case 'b':
blocksize = strtol(optarg, &tmp, 0);
@@ -1291,17 +1292,17 @@ profile_error:
case 'c': /* Check for bad blocks */
cflag++;
break;
- case 'f':
+ case 'C':
size = strtoul(optarg, &tmp, 0);
- if (size < EXT2_MIN_BLOCK_SIZE ||
- size > EXT2_MAX_BLOCK_SIZE || *tmp) {
+ if (size < EXT2_MIN_CLUSTER_SIZE ||
+ size > EXT2_MAX_CLUSTER_SIZE || *tmp) {
com_err(program_name, 0,
_("invalid fragment size - %s"),
optarg);
exit(1);
}
- fprintf(stderr, _("Warning: fragments not supported. "
- "Ignoring -f option\n"));
+ fs_param.s_log_cluster_size =
+ int_log2(size >> EXT2_MIN_CLUSTER_LOG_SIZE);
break;
case 'g':
fs_param.s_blocks_per_group = strtoul(optarg, &tmp, 0);
@@ -1531,8 +1532,6 @@ profile_error:
check_plausibility(device_name);
check_mount(device_name, force, _("filesystem"));
- fs_param.s_log_cluster_size = fs_param.s_log_block_size;
-
/* Determine the size of the device (if possible) */
if (noaction && fs_blocks_count) {
dev_size = fs_blocks_count;
@@ -1780,16 +1779,24 @@ profile_error:
}
}
+ fs_param.s_log_block_size =
+ int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
+ if (fs_param.s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_BIGALLOC) {
+ if (fs_param.s_log_cluster_size == 0)
+ fs_param.s_log_cluster_size =
+ fs_param.s_log_block_size + 4;
+ } else
+ fs_param.s_log_cluster_size = fs_param.s_log_block_size;
+
if (inode_ratio == 0) {
inode_ratio = get_int_from_profile(fs_types, "inode_ratio",
8192);
if (inode_ratio < blocksize)
inode_ratio = blocksize;
+ if (inode_ratio < EXT2_CLUSTER_SIZE(&fs_param))
+ inode_ratio = EXT2_CLUSTER_SIZE(&fs_param);
}
- fs_param.s_log_cluster_size = fs_param.s_log_block_size =
- int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
-
#ifdef HAVE_BLKID_PROBE_GET_TOPOLOGY
retval = get_device_geometry(device_name, &fs_param, psector_size);
if (retval < 0) {
@@ -2077,6 +2084,33 @@ static int mke2fs_discard_device(ext2_filsys fs)
return retval;
}
+static fix_cluster_bg_counts(ext2_filsys fs)
+{
+ blk64_t cluster, num_clusters, tot_free;
+ int grp_free, num_free, group, num;
+
+ num_clusters = EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super));
+ tot_free = num_free = num = group = grp_free = 0;
+ for (cluster = EXT2FS_B2C(fs, fs->super->s_first_data_block);
+ cluster < num_clusters; cluster++) {
+ if (!ext2fs_test_block_bitmap2(fs->block_map,
+ EXT2FS_C2B(fs, cluster))) {
+ grp_free++;
+ tot_free++;
+ }
+ num++;
+ if ((num == fs->super->s_clusters_per_group) ||
+ (cluster == num_clusters-1)) {
+ ext2fs_bg_free_blocks_count_set(fs, group, grp_free);
+ ext2fs_group_desc_csum_set(fs, group);
+ num = 0;
+ grp_free = 0;
+ group++;
+ }
+ }
+ ext2fs_free_blocks_count_set(fs->super, tot_free);
+}
+
int main (int argc, char *argv[])
{
errcode_t retval = 0;
@@ -2283,6 +2317,14 @@ int main (int argc, char *argv[])
}
if (!quiet)
printf(_("done \n"));
+
+ retval = ext2fs_convert_subcluster_bitmap(fs, &fs->block_map);
+ if (retval) {
+ com_err(program_name, retval,
+ _("\n\twhile converting subcluster bitmap"));
+ exit(1);
+ }
+
if (super_only) {
fs->super->s_state |= EXT2_ERROR_FS;
fs->flags &= ~(EXT2_FLAG_IB_DIRTY|EXT2_FLAG_BB_DIRTY);
@@ -2395,6 +2437,9 @@ int main (int argc, char *argv[])
}
no_journal:
+ if (EXT2_HAS_RO_COMPAT_FEATURE(&fs_param,
+ EXT4_FEATURE_RO_COMPAT_BIGALLOC))
+ fix_cluster_bg_counts(fs);
if (!quiet)
printf(_("Writing superblocks and "
"filesystem accounting information: "));