diff options
author | Theodore Ts'o <tytso@mit.edu> | 2011-06-10 18:57:22 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2011-06-10 18:57:22 -0400 |
commit | c6ed60cdeb1355a884f635ac8118c8f330e2ba68 (patch) | |
tree | 5a5d56df9d0a091e572447532573ac1aed1cb22e | |
parent | 4a2a9b70c89891a146bcb9cee3f29572ca2e1370 (diff) | |
download | e2fsprogs-c6ed60cdeb1355a884f635ac8118c8f330e2ba68.tar.gz |
mke2fs: support creating bigalloc file systems
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r-- | lib/ext2fs/initialize.c | 58 | ||||
-rw-r--r-- | misc/mke2fs.c | 71 |
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: ")); |