On Sat, Mar 19, 2011 at 11:28 PM, Theodore Ts'o <tytso@xxxxxxx> wrote: > This is an initial patchset of the bigalloc patches to ext4. This patch > adds support for clustered allocation, so that each bit in the ext4 > block allocation bitmap addresses a power of two number of blocks. For > example, if the file system is mainly going to be storing large files in > the 4-32 megabyte range, it might make sense to set a cluster size of 1 > megabyte. This means that each bit in the block allocaiton bitmap would > now address 256 4k blocks, and it means that the size of the block > bitmaps for a 2T file system shrinks from 64 megabytes to 256k. It also > means that a block group addresses 32 gigabytes instead of 128 > megabytes, also shrinking the amount of file system overhead for > metadata. > > The cost is increased disk space efficiency. Directories will consume > 1T, as will extent tree blocks. (I am on the fence as to whether I > should add complexity so that in the rare case that an inode needs more > than 344 extents --- a highly fragmented file indeed --- and need a > second extent tree block, we can avoid allocating any cluster and > instead use another block from the cluster used by the inode. The > concern is the amount of complexity this adds to the e2fsck, not just to > the kernel.) Unless you define extent tree block size = cluster size. Shouldn't be too hard to teach that to kernel and fsck, right? > > To test these patches, I have used an *extremely* kludgy set of patches > to e2fsprogs, which are attached below. These patches need *extensive* > revision before I would consider them clean enough suitable for > committing into e2fsprogs, but they were sufficient for me to do the > kernel-side changes --- mke2fs, dumpe2fs, and debugfs work. E2fsck most > definitely does _not_ work at this stage. > > Please comment! I do not intend for these patches to be merged during > the 2.6.39 merge window. I am targetting 2.6.40, 3 months from now, > since these patches are quite extensive. > > - Ted > > Theodore Ts'o (12): > ext4: read-only support for bigalloc file systems > ext4: enforce bigalloc restrictions (e.g., no online resizing, etc.) > ext4: Convert instances of EXT4_BLOCKS_PER_GROUP to > EXT4_CLUSTERS_PER_GROUP > ext4: Remove block bitmap initialization in ext4_new_inode() > ext4: factor out block group accounting into functions > ext4: split out ext4_free_blocks_after_init() > ext4: bigalloc changes to block bitmap initialization functions > ext4: Convert block group-relative offsets to use clusters > ext4: teach ext4_ext_map_blocks() about the bigalloc feature I think you are missing an important patch here: ext4: teach ext4_free_blocks() about the bigalloc feature Free only clusters whose 'base' block is contained within the requested blocks range. > ext4: teach ext4_statfs() to deal with clusters if bigalloc is > enabled > ext4: tune mballoc's default group prealloc size for bigalloc file > systems > ext4: enable mounting bigalloc as read/write > > fs/ext4/balloc.c | 268 +++++++++++++++++++++++++++++++++-------------------- > fs/ext4/ext4.h | 47 ++++++++-- > fs/ext4/extents.c | 132 +++++++++++++++++++++++--- > fs/ext4/ialloc.c | 37 -------- > fs/ext4/inode.c | 7 ++ > fs/ext4/ioctl.c | 33 ++++++- > fs/ext4/mballoc.c | 49 ++++++---- > fs/ext4/mballoc.h | 3 +- > fs/ext4/super.c | 100 ++++++++++++++++---- > 9 files changed, 472 insertions(+), 204 deletions(-) > > -- > 1.7.3.1 > > ------------------- e2fsprogs patches follow below > > diff --git a/lib/ext2fs/bmap64.h b/lib/ext2fs/bmap64.h > index b0aa84c..cfbdfd6 100644 > --- a/lib/ext2fs/bmap64.h > +++ b/lib/ext2fs/bmap64.h > @@ -31,6 +31,10 @@ struct ext2fs_struct_generic_bitmap { > ((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP64) || \ > ((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP64)) > > +/* Bitmap flags */ > + > +#define EXT2_BMFLAG_CLUSTER 0x0001 > + > struct ext2_bitmap_ops { > int type; > /* Generic bmap operators */ > diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h > index a89e33b..0970506 100644 > --- a/lib/ext2fs/ext2_fs.h > +++ b/lib/ext2fs/ext2_fs.h > @@ -228,9 +228,13 @@ struct ext2_dx_countlimit { > > #define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->s_blocks_per_group) > #define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group) > +#define EXT2_CLUSTERS_PER_GROUP(s) (EXT2_SB(s)->s_clusters_per_group) > #define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s)) > /* limits imposed by 16-bit value gd_free_{blocks,inode}_count */ > -#define EXT2_MAX_BLOCKS_PER_GROUP(s) ((1 << 16) - 8) > +#define EXT2_MAX_BLOCKS_PER_GROUP(s) (((1 << 16) - 8) * \ > + (EXT2_CLUSTER_SIZE(s) / \ > + EXT2_BLOCK_SIZE(s))) > +#define EXT2_MAX_CLUSTERS_PER_GROUP(s) ((1 << 16) - 8) > #define EXT2_MAX_INODES_PER_GROUP(s) ((1 << 16) - EXT2_INODES_PER_BLOCK(s)) > #ifdef __KERNEL__ > #define EXT2_DESC_PER_BLOCK(s) (EXT2_SB(s)->s_desc_per_block) > diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h > index d3eb31d..a065e87 100644 > --- a/lib/ext2fs/ext2fs.h > +++ b/lib/ext2fs/ext2fs.h > @@ -207,7 +207,7 @@ struct struct_ext2_filsys { > char * device_name; > struct ext2_super_block * super; > unsigned int blocksize; > - int clustersize; > + int cluster_ratio; > dgrp_t group_desc_count; > unsigned long desc_blocks; > struct opaque_ext2_group_desc * group_desc; > @@ -232,7 +232,8 @@ struct struct_ext2_filsys { > /* > * Reserved for future expansion > */ > - __u32 reserved[7]; > + __u32 clustersize; > + __u32 reserved[6]; > > /* > * Reserved for the use of the calling application. > @@ -553,7 +554,8 @@ typedef struct ext2_icount *ext2_icount_t; > EXT2_FEATURE_RO_COMPAT_LARGE_FILE|\ > EXT4_FEATURE_RO_COMPAT_DIR_NLINK|\ > EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE|\ > - EXT4_FEATURE_RO_COMPAT_GDT_CSUM) > + EXT4_FEATURE_RO_COMPAT_GDT_CSUM|\ > + EXT4_FEATURE_RO_COMPAT_BIGALLOC) > > /* > * These features are only allowed if EXT2_FLAG_SOFTSUPP_FEATURES is passed > diff --git a/lib/ext2fs/gen_bitmap64.c b/lib/ext2fs/gen_bitmap64.c > index df095ac..60321df 100644 > --- a/lib/ext2fs/gen_bitmap64.c > +++ b/lib/ext2fs/gen_bitmap64.c > @@ -559,3 +559,85 @@ int ext2fs_warn_bitmap32(ext2fs_generic_bitmap bitmap, const char *func) > "called %s with 64-bit bitmap", func); > #endif > } > + > +errcode_t ext2fs_allocate_cluster_bitmap(ext2_filsys fs, > + const char *descr, > + ext2fs_block_bitmap *ret) > +{ > + __u64 start, end, real_end; > + errcode_t retval; > + > + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); > + > + if (!(fs->flags & EXT2_FLAG_64BITS)) > + return EXT2_ET_CANT_USE_LEGACY_BITMAPS; > + > + fs->write_bitmaps = ext2fs_write_bitmaps; > + > + start = (fs->super->s_first_data_block >> > + EXT2_CLUSTER_SIZE_BITS(fs->super)); > + end = (ext2fs_blocks_count(fs->super) - 1) / fs->cluster_ratio; > + real_end = ((__u64) EXT2_CLUSTERS_PER_GROUP(fs->super) > + * (__u64) fs->group_desc_count)-1 + start; > + > + retval = ext2fs_alloc_generic_bmap(fs, > + EXT2_ET_MAGIC_BLOCK_BITMAP64, > + EXT2FS_BMAP64_BITARRAY, > + start, end, real_end, descr, ret); > + if (retval) > + return retval; > + > + (*ret)->flags = EXT2_BMFLAG_CLUSTER; > + > + printf("Returning 0...\n"); > + return 0; > +} > + > +int ext2fs_is_cluster_bitmap(ext2fs_block_bitmap bm) > +{ > + if (EXT2FS_IS_32_BITMAP(bm)) > + return 0; > + > + return (bm->flags & EXT2_BMFLAG_CLUSTER); > +} > + > +errcode_t ext2fs_convert_to_cluster_bitmap(ext2_filsys fs, > + ext2fs_block_bitmap bmap, > + ext2fs_block_bitmap *ret) > +{ > + ext2fs_block_bitmap cmap; > + errcode_t retval; > + blk64_t i, j, b_end, c_end; > + int n; > + > + retval = ext2fs_allocate_cluster_bitmap(fs, "converted cluster bitmap", > + ret); > + if (retval) > + return retval; > + > + cmap = *ret; > + i = bmap->start; > + b_end = bmap->end; > + bmap->end = bmap->real_end; > + j = cmap->start; > + c_end = cmap->end; > + cmap->end = cmap->real_end; > + n = 0; > + while (i < bmap->real_end) { > + if (ext2fs_test_block_bitmap2(bmap, i)) { > + ext2fs_mark_block_bitmap2(cmap, j); > + i += fs->cluster_ratio - n; > + j++; > + n = 0; > + continue; > + } > + i++; n++; > + if (n >= fs->cluster_ratio) { > + j++; > + n = 0; > + } > + } > + bmap->end = b_end; > + cmap->end = c_end; > + return 0; > +} > diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c > index e1f229b..00a8b38 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,12 +135,25 @@ 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); > + 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_block_size ? 0 : 1); > set_field(s_max_mnt_count, 0); > set_field(s_errors, EXT2_ERRORS_DEFAULT); > @@ -183,14 +197,36 @@ errcode_t ext2fs_initialize(const char *name, int flags, > > fs->blocksize = EXT2_BLOCK_SIZE(super); > fs->clustersize = EXT2_CLUSTER_SIZE(super); > + fs->cluster_ratio = fs->clustersize / fs->blocksize; > + > + if (bigalloc_flag) { > + if (param->s_blocks_per_group && > + param->s_clusters_per_group && > + ((param->s_clusters_per_group * fs->cluster_ratio) != > + 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 / fs->cluster_ratio; > + 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 = super->s_clusters_per_group; > + super->s_blocks_per_group *= fs->cluster_ratio; > + } 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; > + } > > - /* 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; > - > - ext2fs_blocks_count_set(super, ext2fs_blocks_count(param)); > + ext2fs_blocks_count_set(super, ext2fs_blocks_count(param) & > + ~((blk64_t) fs->cluster_ratio - 1)); > 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; > @@ -246,7 +282,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, > diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c > index 90abed1..8b37852 100644 > --- a/lib/ext2fs/openfs.c > +++ b/lib/ext2fs/openfs.c > @@ -251,6 +251,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, > goto cleanup; > } > fs->clustersize = EXT2_CLUSTER_SIZE(fs->super); > + fs->cluster_ratio = fs->clustersize / fs->blocksize; > fs->inode_blocks_per_group = ((EXT2_INODES_PER_GROUP(fs->super) * > EXT2_INODE_SIZE(fs->super) + > EXT2_BLOCK_SIZE(fs->super) - 1) / > diff --git a/lib/ext2fs/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c > index 3031b7d..aeea997 100644 > --- a/lib/ext2fs/rw_bitmaps.c > +++ b/lib/ext2fs/rw_bitmaps.c > @@ -51,7 +51,7 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block) > > inode_nbytes = block_nbytes = 0; > if (do_block) { > - block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; > + block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; > retval = ext2fs_get_memalign(fs->blocksize, fs->blocksize, > &block_buf); > if (retval) > @@ -85,7 +85,7 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block) > /* Force bitmap padding for the last group */ > nbits = ((ext2fs_blocks_count(fs->super) > - (__u64) fs->super->s_first_data_block) > - % (__u64) EXT2_BLOCKS_PER_GROUP(fs->super)); > + % (__u64) EXT2_CLUSTERS_PER_GROUP(fs->super)); > if (nbits) > for (j = nbits; j < fs->blocksize * 8; j++) > ext2fs_set_bit(j, block_buf); > @@ -141,7 +141,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) > char *block_bitmap = 0, *inode_bitmap = 0; > char *buf; > errcode_t retval; > - int block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; > + int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; > int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8; > int csum_flag = 0; > int do_image = fs->flags & EXT2_FLAG_IMAGE_FILE; > @@ -219,7 +219,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) > } > blk = (fs->image_header->offset_blockmap / > fs->blocksize); > - blk_cnt = (blk64_t)EXT2_BLOCKS_PER_GROUP(fs->super) * > + blk_cnt = (blk64_t)EXT2_CLUSTERS_PER_GROUP(fs->super) * > fs->group_desc_count; > while (block_nbytes > 0) { > retval = io_channel_read_blk64(fs->image_io, blk++, > diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c > index c01ffe5..d3f617a 100644 > --- a/misc/dumpe2fs.c > +++ b/misc/dumpe2fs.c > @@ -71,25 +71,26 @@ static void print_range(unsigned long long a, unsigned long long b) > printf("%llu-%llu", a, b); > } > > -static void print_free (unsigned long group, char * bitmap, > - unsigned long nbytes, unsigned long offset) > +static void print_free(unsigned long group, char * bitmap, > + unsigned long nbytes, unsigned long offset, int ratio) > { > int p = 0; > unsigned long i; > unsigned long j; > > + offset /= ratio; > offset += group * nbytes; > for (i = 0; i < nbytes; i++) > if (!in_use (bitmap, i)) > { > if (p) > printf (", "); > - print_number(i + offset); > + print_number((i + offset) * ratio); > for (j = i; j < nbytes && !in_use (bitmap, j); j++) > ; > if (--j != i) { > fputc('-', stdout); > - print_number(j + offset); > + print_number((j + offset) * ratio); > i = j; > } > p = 1; > @@ -153,7 +154,7 @@ static void list_desc (ext2_filsys fs) > blk64_t blk_itr = fs->super->s_first_data_block; > ext2_ino_t ino_itr = 1; > > - block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; > + block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; > inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8; > > if (fs->block_map) > @@ -238,18 +239,19 @@ static void list_desc (ext2_filsys fs) > fputs(_(" Free blocks: "), stdout); > ext2fs_get_block_bitmap_range2(fs->block_map, > blk_itr, block_nbytes << 3, block_bitmap); > - print_free (i, block_bitmap, > - fs->super->s_blocks_per_group, > - fs->super->s_first_data_block); > + print_free(i, block_bitmap, > + fs->super->s_clusters_per_group, > + fs->super->s_first_data_block, > + fs->cluster_ratio); > fputc('\n', stdout); > - blk_itr += fs->super->s_blocks_per_group; > + blk_itr += fs->super->s_clusters_per_group; > } > if (inode_bitmap) { > fputs(_(" Free inodes: "), stdout); > ext2fs_get_inode_bitmap_range2(fs->inode_map, > ino_itr, inode_nbytes << 3, inode_bitmap); > - print_free (i, inode_bitmap, > - fs->super->s_inodes_per_group, 1); > + print_free(i, inode_bitmap, > + fs->super->s_inodes_per_group, 1, 1); > fputc('\n', stdout); > ino_itr += fs->super->s_inodes_per_group; > } > diff --git a/misc/mke2fs.c b/misc/mke2fs.c > index 9798b88..079638f 100644 > --- a/misc/mke2fs.c > +++ b/misc/mke2fs.c > @@ -815,7 +815,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 > }; > > > @@ -1252,7 +1253,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); > @@ -1275,17 +1276,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); > @@ -1515,8 +1516,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; > @@ -1752,16 +1751,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) { > @@ -2049,6 +2056,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_blocks_count(fs->super) / fs->cluster_ratio; > + tot_free = num_free = num = group = grp_free = 0; > + for (cluster = fs->super->s_first_data_block / fs->cluster_ratio; > + cluster < num_clusters; cluster++) { > + if (!ext2fs_test_block_bitmap2(fs->block_map, cluster)) { > + grp_free++; > + tot_free++; > + } > + num++; > + if ((num == fs->super->s_clusters_per_group) || > + (cluster == num_clusters-1)) { > + printf("Group %d has free #: %d\n", group, grp_free); > + 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; > @@ -2367,6 +2401,17 @@ int main (int argc, char *argv[]) > } > no_journal: > > + if (EXT2_HAS_RO_COMPAT_FEATURE(&fs_param, > + EXT4_FEATURE_RO_COMPAT_BIGALLOC)) { > + ext2fs_block_bitmap cluster_map; > + > + retval = ext2fs_convert_to_cluster_bitmap(fs, fs->block_map, > + &cluster_map); > + ext2fs_free_block_bitmap(fs->block_map); > + fs->block_map = cluster_map; > + fix_cluster_bg_counts(fs); > + } > + > if (!quiet) > printf(_("Writing superblocks and " > "filesystem accounting information: ")); > -- > To unsubscribe from this list: send the line "unsubscribe linux-ext4" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html