From d8fe566ba5501d7de63b52fb590c0d628a74e027 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 14 Sep 2021 15:05:45 -0400 Subject: [PATCH] resize2fs: optimize resize2fs_calculate_summary_stats() Speed up an off-line resize of a 10GB file system to 64TB located on tmpfs from 90 seconds to 16 seconds by extracting block group bitmaps using a population count function to count the blocks in use instead checking each bit in the block bitmap. Signed-off-by: Theodore Ts'o --- resize/resize2fs.c | 79 +++++++++++++++++------------------------------------- 1 file changed, 25 insertions(+), 54 deletions(-) diff --git a/resize/resize2fs.c b/resize/resize2fs.c index 5ed0c9e..73174be 100644 --- a/resize/resize2fs.c +++ b/resize/resize2fs.c @@ -2844,69 +2844,40 @@ errout: */ static errcode_t resize2fs_calculate_summary_stats(ext2_filsys fs) { - blk64_t blk; + errcode_t retval; + blk64_t blk = fs->super->s_first_data_block; ext2_ino_t ino; - unsigned int group = 0; - unsigned int count = 0; - blk64_t total_blocks_free = 0; + unsigned int n, c, group, count; + blk64_t total_clusters_free = 0; int total_inodes_free = 0; int group_free = 0; int uninit = 0; - blk64_t super_blk, old_desc_blk, new_desc_blk; - int old_desc_blocks; + char *bitmap_buf; /* * First calculate the block statistics */ - uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT); - ext2fs_super_and_bgd_loc2(fs, group, &super_blk, &old_desc_blk, - &new_desc_blk, 0); - if (ext2fs_has_feature_meta_bg(fs->super)) - old_desc_blocks = fs->super->s_first_meta_bg; - else - old_desc_blocks = fs->desc_blocks + - fs->super->s_reserved_gdt_blocks; - for (blk = B2C(fs->super->s_first_data_block); - blk < ext2fs_blocks_count(fs->super); - blk += EXT2FS_CLUSTER_RATIO(fs)) { - if ((uninit && - !(EQ_CLSTR(blk, super_blk) || - ((old_desc_blk && old_desc_blocks && - GE_CLSTR(blk, old_desc_blk) && - LT_CLSTR(blk, old_desc_blk + old_desc_blocks))) || - ((new_desc_blk && EQ_CLSTR(blk, new_desc_blk))) || - EQ_CLSTR(blk, ext2fs_block_bitmap_loc(fs, group)) || - EQ_CLSTR(blk, ext2fs_inode_bitmap_loc(fs, group)) || - ((GE_CLSTR(blk, ext2fs_inode_table_loc(fs, group)) && - LT_CLSTR(blk, ext2fs_inode_table_loc(fs, group) - + fs->inode_blocks_per_group))))) || - (!ext2fs_fast_test_block_bitmap2(fs->block_map, blk))) { - group_free++; - total_blocks_free++; - } - count++; - if ((count == fs->super->s_clusters_per_group) || - EQ_CLSTR(blk, ext2fs_blocks_count(fs->super)-1)) { - ext2fs_bg_free_blocks_count_set(fs, group, group_free); - ext2fs_group_desc_csum_set(fs, group); - group++; - if (group >= fs->group_desc_count) - break; - count = 0; - group_free = 0; - uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT); - ext2fs_super_and_bgd_loc2(fs, group, &super_blk, - &old_desc_blk, - &new_desc_blk, 0); - if (ext2fs_has_feature_meta_bg(fs->super)) - old_desc_blocks = fs->super->s_first_meta_bg; - else - old_desc_blocks = fs->desc_blocks + - fs->super->s_reserved_gdt_blocks; + bitmap_buf = malloc(fs->blocksize); + if (!bitmap_buf) + return ENOMEM; + for (group = 0; group < fs->group_desc_count; + group++) { + retval = ext2fs_get_block_bitmap_range2(fs->block_map, + B2C(blk), fs->super->s_clusters_per_group, bitmap_buf); + if (retval) { + free(bitmap_buf); + return retval; } - } - total_blocks_free = C2B(total_blocks_free); - ext2fs_free_blocks_count_set(fs->super, total_blocks_free); + n = ext2fs_bitcount(bitmap_buf, + fs->super->s_clusters_per_group / 8); + group_free = fs->super->s_clusters_per_group - n; + total_clusters_free += group_free; + ext2fs_bg_free_blocks_count_set(fs, group, group_free); + ext2fs_group_desc_csum_set(fs, group); + blk += fs->super->s_blocks_per_group; + } + free(bitmap_buf); + ext2fs_free_blocks_count_set(fs->super, C2B(total_clusters_free)); /* * Next, calculate the inode statistics -- 1.8.3.1