diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2014-02-23 20:54:54 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2014-02-23 20:54:58 -0500 |
commit | 118d3f0b58e9523486a88ebc214626f20256916d (patch) | |
tree | 7b88e7081eb44bb81f5319754526755b4485df24 /resize | |
parent | 01d6aa9d8757a5b76ed8e2b2bbe3488a6a3afc9c (diff) | |
download | e2fsprogs-118d3f0b58e9523486a88ebc214626f20256916d.tar.gz |
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 <darrick.wong@oracle.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'resize')
-rw-r--r-- | resize/resize2fs.c | 72 |
1 files changed, 63 insertions, 9 deletions
diff --git a/resize/resize2fs.c b/resize/resize2fs.c index caff422b..6b9ca095 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; } |