summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2009-01-19 09:02:55 -0500
committerTheodore Ts'o <tytso@mit.edu>2009-01-19 09:02:55 -0500
commit9227c5bbbd0861878ae73f7dceb4deb9e9f06a3c (patch)
treea82fcd360bdb9c5a2376b80b9ca828e15a96ad78
parentc58a08e673a10d0e5fa4855ca58ab2cbf48fd029 (diff)
downloade2fsprogs-9227c5bbbd0861878ae73f7dceb4deb9e9f06a3c.tar.gz
resize2fs: Release bitmap and itable blocks in flex_bg filesystems
Previously resize2fs assumed that bitmap and inode table blocks were always located in their respective block group. However, this is no longer true with flex_bg. So it is necessary to check all of the block groups which will be truncated to see if they have metadata blocks that need to be marked as no longer being in use in the new, shrunk filesystem. This bug fixes resize2fs -M, which would otherwise fail because without the released blocks, there would not be enough space in the filesystem. This bug also avoids (mostly harmless) filesystem corruptions reported by e2fsck regarding blocks marked in use but not actually used (these being the bitmap and inode table blocks associated with the truncated block groups). Note: in theory it is possible to have block group N utilize bitmap and inode table blocks in block group N+X with flex_bg. At the moment neither mke2fs nor e2fsck will create filesystems like this, which is good, because resize2fs doesn't handle this case correctly. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r--resize/resize2fs.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/resize/resize2fs.c b/resize/resize2fs.c
index e7a08daa..df4dac7f 100644
--- a/resize/resize2fs.c
+++ b/resize/resize2fs.c
@@ -232,6 +232,35 @@ static void fix_uninit_block_bitmaps(ext2_filsys fs)
*/
/*
+ * If the group descriptor's bitmap and inode table blocks are valid,
+ * release them in the specified filesystem data structure
+ */
+static void free_gdp_blocks(ext2_filsys fs, struct ext2_group_desc *gdp)
+{
+ blk_t blk;
+ int j;
+
+ if (gdp->bg_block_bitmap &&
+ (gdp->bg_block_bitmap < fs->super->s_blocks_count))
+ ext2fs_block_alloc_stats(fs, gdp->bg_block_bitmap, -1);
+
+ if (gdp->bg_inode_bitmap &&
+ (gdp->bg_inode_bitmap < fs->super->s_blocks_count))
+ ext2fs_block_alloc_stats(fs, gdp->bg_inode_bitmap, -1);
+
+ if (gdp->bg_inode_table == 0 ||
+ (gdp->bg_inode_table >= fs->super->s_blocks_count))
+ return;
+
+ for (blk = gdp->bg_inode_table, j = 0;
+ j < fs->inode_blocks_per_group; j++, blk++) {
+ if (blk >= fs->super->s_blocks_count)
+ break;
+ ext2fs_block_alloc_stats(fs, blk, -1);
+ }
+}
+
+/*
* This routine is shared by the online and offline resize routines.
* All of the information which is adjusted in memory is done here.
*/
@@ -374,6 +403,14 @@ retry:
* can exit now.
*/
if (old_fs->group_desc_count > fs->group_desc_count) {
+ /*
+ * Check the block groups that we are chopping off
+ * and free any blocks associated with their metadata
+ */
+ for (i = fs->group_desc_count;
+ i < old_fs->group_desc_count; i++) {
+ free_gdp_blocks(fs, &old_fs->group_desc[i]);
+ }
retval = 0;
goto errout;
}