From 118d3f0b58e9523486a88ebc214626f20256916d Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Sun, 23 Feb 2014 20:54:54 -0500 Subject: [PATCH] resize2fs: don't free in-use clusters when moving blocks When we're moving blocks around the filesystem, ensure that freeing the old blocks only frees the clusters if they're not in use by other metadata. Signed-off-by: Darrick J. Wong Signed-off-by: "Theodore Ts'o" --- resize/resize2fs.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 63 insertions(+), 9 deletions(-) diff --git a/resize/resize2fs.c b/resize/resize2fs.c index caff422..6b9ca09 100644 --- a/resize/resize2fs.c +++ b/resize/resize2fs.c @@ -909,12 +909,12 @@ static errcode_t blocks_to_move(ext2_resize_t rfs) int j, has_super; dgrp_t i, max_groups, g; blk64_t blk, group_blk; - blk64_t old_blocks, new_blocks; + blk64_t old_blocks, new_blocks, group_end, cluster_freed; blk64_t new_size; unsigned int meta_bg, meta_bg_size; errcode_t retval; ext2_filsys fs, old_fs; - ext2fs_block_bitmap meta_bmap; + ext2fs_block_bitmap meta_bmap, new_meta_bmap = NULL; int flex_bg; fs = rfs->new_fs; @@ -1026,15 +1026,42 @@ static errcode_t blocks_to_move(ext2_resize_t rfs) * blocks as free. */ if (old_blocks > new_blocks) { + if (EXT2FS_CLUSTER_RATIO(fs) > 1) { + retval = ext2fs_allocate_block_bitmap(fs, + _("new meta blocks"), + &new_meta_bmap); + if (retval) + goto errout; + + retval = mark_table_blocks(fs, new_meta_bmap); + if (retval) + goto errout; + } + for (i = 0; i < max_groups; i++) { if (!ext2fs_bg_has_super(fs, i)) { group_blk += fs->super->s_blocks_per_group; continue; } - for (blk = group_blk+1+new_blocks; - blk < group_blk+1+old_blocks; blk++) { - ext2fs_block_alloc_stats2(fs, blk, -1); + group_end = group_blk + 1 + old_blocks; + for (blk = group_blk + 1 + new_blocks; + blk < group_end;) { + if (new_meta_bmap == NULL || + !ext2fs_test_block_bitmap2(new_meta_bmap, + blk)) { + cluster_freed = + EXT2FS_CLUSTER_RATIO(fs) - + (blk & + EXT2FS_CLUSTER_MASK(fs)); + if (cluster_freed > group_end - blk) + cluster_freed = group_end - blk; + ext2fs_block_alloc_stats2(fs, blk, -1); + blk += EXT2FS_CLUSTER_RATIO(fs); + rfs->needed_blocks -= cluster_freed; + continue; + } rfs->needed_blocks--; + blk++; } group_blk += fs->super->s_blocks_per_group; } @@ -1180,6 +1207,8 @@ static errcode_t blocks_to_move(ext2_resize_t rfs) retval = 0; errout: + if (new_meta_bmap) + ext2fs_free_block_bitmap(new_meta_bmap); if (meta_bmap) ext2fs_free_block_bitmap(meta_bmap); @@ -1779,9 +1808,10 @@ static errcode_t move_itables(ext2_resize_t rfs) dgrp_t i, max_groups; ext2_filsys fs = rfs->new_fs; char *cp; - blk64_t old_blk, new_blk, blk; + blk64_t old_blk, new_blk, blk, cluster_freed; errcode_t retval; int j, to_move, moved; + ext2fs_block_bitmap new_bmap = NULL; max_groups = fs->group_desc_count; if (max_groups > rfs->old_fs->group_desc_count) @@ -1794,6 +1824,17 @@ static errcode_t move_itables(ext2_resize_t rfs) return retval; } + if (EXT2FS_CLUSTER_RATIO(fs) > 1) { + retval = ext2fs_allocate_block_bitmap(fs, _("new meta blocks"), + &new_bmap); + if (retval) + return retval; + + retval = mark_table_blocks(fs, new_bmap); + if (retval) + goto errout; + } + /* * Figure out how many inode tables we need to move */ @@ -1871,8 +1912,19 @@ static errcode_t move_itables(ext2_resize_t rfs) } for (blk = ext2fs_inode_table_loc(rfs->old_fs, i), j=0; - j < fs->inode_blocks_per_group ; j++, blk++) - ext2fs_block_alloc_stats2(fs, blk, -1); + j < fs->inode_blocks_per_group;) { + if (new_bmap == NULL || + !ext2fs_test_block_bitmap2(new_bmap, blk)) { + ext2fs_block_alloc_stats2(fs, blk, -1); + cluster_freed = EXT2FS_CLUSTER_RATIO(fs) - + (blk & EXT2FS_CLUSTER_MASK(fs)); + blk += cluster_freed; + j += cluster_freed; + continue; + } + blk++; + j++; + } ext2fs_inode_table_loc_set(rfs->old_fs, i, new_blk); ext2fs_group_desc_csum_set(rfs->old_fs, i); @@ -1892,9 +1944,11 @@ static errcode_t move_itables(ext2_resize_t rfs) if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE) printf("Inode table move finished.\n"); #endif - return 0; + retval = 0; errout: + if (new_bmap) + ext2fs_free_block_bitmap(new_bmap); return retval; } -- 1.8.3.1