summaryrefslogtreecommitdiff
path: root/resize
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2014-02-23 20:54:54 -0500
committerTheodore Ts'o <tytso@mit.edu>2014-02-23 20:54:58 -0500
commit118d3f0b58e9523486a88ebc214626f20256916d (patch)
tree7b88e7081eb44bb81f5319754526755b4485df24 /resize
parent01d6aa9d8757a5b76ed8e2b2bbe3488a6a3afc9c (diff)
downloade2fsprogs-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.c72
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;
}