From aaa1ae0856fa4b2517cac9d7011316d55bbf6ed8 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 10 May 2016 21:06:15 -0400 Subject: [PATCH] resize2fs, libext2fs: fix bugs in sparse_super2 support Fix resize2fs so that the location of the backup superblocks when the sparse_super2 feature is enabled is properly set when growing the file system from a single block group to larger file system sizes. Also fix a bug where the block group summary statistics in some cases when exapnding a sparse_super2 file system. Finally, accurately calculate the file system metadata overhead of the last block group in sparse_super2 file systems. Signed-off-by: Theodore Ts'o --- lib/ext2fs/initialize.c | 15 ++++++++++++++- resize/resize2fs.c | 34 ++++++++++++++++++++++++---------- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c index 8714ff5..32f4321 100644 --- a/lib/ext2fs/initialize.c +++ b/lib/ext2fs/initialize.c @@ -98,6 +98,7 @@ errcode_t ext2fs_initialize(const char *name, int flags, int csum_flag; int bigalloc_flag; int io_flags; + int has_bg; unsigned reserved_inos; char *buf = 0; char c; @@ -404,7 +405,19 @@ ipg_retry: * backup. */ overhead = (int) (2 + fs->inode_blocks_per_group); - if (ext2fs_bg_has_super(fs, fs->group_desc_count - 1)) + has_bg = 0; + if (ext2fs_has_feature_sparse_super2(super)) { + /* + * We have to do this manually since + * super->s_backup_bgs hasn't been set up yet. + */ + if (fs->group_desc_count == 2) + has_bg = param->s_backup_bgs[0] != 0; + else + has_bg = param->s_backup_bgs[1] != 0; + } else + has_bg = ext2fs_bg_has_super(fs, fs->group_desc_count - 1); + if (has_bg) overhead += 1 + fs->desc_blocks + super->s_reserved_gdt_blocks; rem = ((ext2fs_blocks_count(super) - super->s_first_data_block) % super->s_blocks_per_group); diff --git a/resize/resize2fs.c b/resize/resize2fs.c index 36da253..8d33e54 100644 --- a/resize/resize2fs.c +++ b/resize/resize2fs.c @@ -206,6 +206,10 @@ errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags, goto errout; print_resource_track(rfs, &rtrack, fs->io); + retval = clear_sparse_super2_last_group(rfs); + if (retval) + goto errout; + init_resource_track(&rtrack, "calculate_summary_stats", fs->io); retval = ext2fs_calculate_summary_stats(rfs->new_fs); if (retval) @@ -224,10 +228,6 @@ errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags, goto errout; print_resource_track(rfs, &rtrack, fs->io); - retval = clear_sparse_super2_last_group(rfs); - if (retval) - goto errout; - retval = ext2fs_set_gdt_csum(rfs->new_fs); if (retval) goto errout; @@ -698,7 +698,7 @@ errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs, blk64_t old_numblocks, numblocks, adjblocks; unsigned long i, j, old_desc_blocks; unsigned int meta_bg, meta_bg_size; - int has_super, csum_flag; + int has_super, csum_flag, has_bg; unsigned long long new_inodes; /* u64 to check for overflow */ double percent; @@ -721,7 +721,19 @@ retry: */ overhead = (int) (2 + fs->inode_blocks_per_group); - if (ext2fs_bg_has_super(fs, fs->group_desc_count - 1)) + has_bg = 0; + if (ext2fs_has_feature_sparse_super2(fs->super)) { + /* + * We have to do this manually since + * super->s_backup_bgs hasn't been set up yet. + */ + if (fs->group_desc_count == 2) + has_bg = fs->super->s_backup_bgs[0] != 0; + else + has_bg = fs->super->s_backup_bgs[1] != 0; + } else + has_bg = ext2fs_bg_has_super(fs, fs->group_desc_count - 1); + if (has_bg) overhead += 1 + fs->desc_blocks + fs->super->s_reserved_gdt_blocks; @@ -843,10 +855,9 @@ retry: if (last_bg > old_last_bg) { if (old_fs->group_desc_count == 1) fs->super->s_backup_bgs[0] = 1; - if (old_fs->group_desc_count == 1 && - fs->super->s_backup_bgs[0]) - fs->super->s_backup_bgs[0] = last_bg; - else if (fs->super->s_backup_bgs[1]) + if ((old_fs->group_desc_count < 3 && + fs->group_desc_count > 2) || + fs->super->s_backup_bgs[1]) fs->super->s_backup_bgs[1] = last_bg; } else if (last_bg < old_last_bg) { if (fs->super->s_backup_bgs[0] > last_bg) @@ -2466,6 +2477,9 @@ static errcode_t clear_sparse_super2_last_group(ext2_resize_t rfs) fs->super->s_backup_bgs[1] == old_last_bg) return 0; + if (old_last_bg == 0) + return 0; + retval = ext2fs_super_and_bgd_loc2(rfs->old_fs, old_last_bg, &sb, &old_desc, NULL, &num); if (retval) -- 1.8.3.1