X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lib%2Fext2fs%2Finitialize.c;h=2875f97ea9213598dba63890278bd9019b5e2bc2;hb=bfbeec0c89d44d456003770d25c70735e45c5622;hp=4cf0863db57389e6629bcfbe7a4ffdb723603da8;hpb=214580a339a18b0539b5998d3b47934956a30a1c;p=tools%2Fe2fsprogs.git diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c index 4cf0863..2875f97 100644 --- a/lib/ext2fs/initialize.c +++ b/lib/ext2fs/initialize.c @@ -10,6 +10,7 @@ * %End-Header% */ +#include "config.h" #include #include #if HAVE_UNISTD_H @@ -87,14 +88,15 @@ errcode_t ext2fs_initialize(const char *name, int flags, ext2_filsys fs; errcode_t retval; struct ext2_super_block *super; - int frags_per_block; unsigned int rem; unsigned int overhead = 0; unsigned int ipg; dgrp_t i; + blk64_t free_blocks; blk_t numblocks; int rsv_gdt; int csum_flag; + int bigalloc_flag; int io_flags; char *buf = 0; char c; @@ -135,13 +137,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_frag_size, 0); /* default fragsize: 1024 bytes */ - 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); @@ -182,17 +197,39 @@ errcode_t ext2fs_initialize(const char *name, int flags, super->s_creator_os = CREATOR_OS; - fs->blocksize = EXT2_BLOCK_SIZE(super); - fs->fragsize = EXT2_FRAG_SIZE(super); - frags_per_block = fs->blocksize / fs->fragsize; + fs->fragsize = fs->blocksize = EXT2_BLOCK_SIZE(super); + 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_frags_per_group = super->s_blocks_per_group * frags_per_block; + 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_clusters_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; @@ -248,13 +285,12 @@ 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, ext2fs_blocks_count(param)); - super->s_frags_per_group = super->s_blocks_per_group * - frags_per_block; + super->s_clusters_per_group = super->s_blocks_per_group; goto retry; } else { retval = EXT2_ET_TOO_MANY_INODES; @@ -285,6 +321,8 @@ ipg_retry: * multiple of 8. This is needed to simplify the bitmap * splicing code. */ + if (super->s_inodes_per_group < 8) + super->s_inodes_per_group = 8; super->s_inodes_per_group &= ~7; fs->inode_blocks_per_group = (((super->s_inodes_per_group * EXT2_INODE_SIZE(super)) + @@ -365,7 +403,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; @@ -395,7 +433,7 @@ ipg_retry: * superblock and group descriptors (the inode tables and * bitmaps will be accounted for when allocated). */ - ext2fs_free_blocks_count_set(super, 0); + free_blocks = 0; csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super, EXT4_FEATURE_RO_COMPAT_GDT_CSUM); for (i = 0; i < fs->group_desc_count; i++) { @@ -417,14 +455,14 @@ ipg_retry: if (fs->super->s_log_groups_per_flex) numblocks += 2 + fs->inode_blocks_per_group; - ext2fs_free_blocks_count_set(super, - ext2fs_free_blocks_count(super) + - numblocks); + free_blocks += numblocks; ext2fs_bg_free_blocks_count_set(fs, i, numblocks); ext2fs_bg_free_inodes_count_set(fs, i, fs->super->s_inodes_per_group); ext2fs_bg_used_dirs_count_set(fs, i, 0); ext2fs_group_desc_csum_set(fs, i); } + free_blocks &= ~EXT2FS_CLUSTER_MASK(fs); + ext2fs_free_blocks_count_set(super, free_blocks); c = (char) 255; if (((int) c) == -1) {