summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@fedoraproject.org>2009-04-22 16:06:01 +0000
committerEric Sandeen <sandeen@fedoraproject.org>2009-04-22 16:06:01 +0000
commit36a7badb2dad7c09f5e562d19852a545e85951cb (patch)
tree2f653ae891bee921fd03bc2156909d95bc309eb0
parent39346b1b74ead1f96d4fadd9376f8f5de83310aa (diff)
downloade2fsprogs-36a7badb2dad7c09f5e562d19852a545e85951cb.tar.gz
e2fsprogs-36a7badb2dad7c09f5e562d19852a545e85951cb.tar.xz
e2fsprogs-36a7badb2dad7c09f5e562d19852a545e85951cb.zip
* Wed Apr 22 2009 Eric Sandeen <sandeen@redhat.com> 1.41.4-7e2fsprogs-1_41_4-7_fc12
- Fix ext4 resize issues (#496982)
-rw-r--r--e2fsprogs-1.41.4-ext4-resize-fixes.patch241
-rw-r--r--e2fsprogs.spec8
2 files changed, 248 insertions, 1 deletions
diff --git a/e2fsprogs-1.41.4-ext4-resize-fixes.patch b/e2fsprogs-1.41.4-ext4-resize-fixes.patch
new file mode 100644
index 0000000..c950703
--- /dev/null
+++ b/e2fsprogs-1.41.4-ext4-resize-fixes.patch
@@ -0,0 +1,241 @@
+3 patches from the list to address resize issues (18 Apr 2009):
+
+When allocating a new set of block group metadata as part of growing
+the filesystem, the resize2fs code assumes that the bitmap and inode
+table blocks are in their own block group; an assumption which is
+changed by the flex_bg feature. This commit works around the problem
+by temporarily turning off flex_bg while allocating the new block
+group metadata, to avoid potentially overwriting previously allocated
+data blocks.
+
+Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
+---
+
+If we need to shrink the inode table, we need to make sure the inodes
+contained in the part of the inode table we are vacating don't get
+reused as part of the filesystem shrink operation. This wasn't a
+problem with ext3 filesystems, since the inode table was located in
+the block group that was going away, so that location was not eligible
+for reallocation.
+
+However with ext4 filesystems with flex_bg enabled, it's possible for
+a portion of the inode table in the last flex_bg group to be
+deallocated, but in a part of the filesystem which could be used as
+data blocks. So we must mark those blocks as reserved to prevent
+their reuse, and adjust the minimum filesystem size calculation to
+assure that we don't shrink a filesystem too small for the resize
+operation to succeed.
+
+Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
+---
+
+Due to a fencepost bug, when skipping a block group whose block bitmap
+was uninitialized (and hence could not contain any blocks eligible for
+relaocation), the block immediately following the block group wasn't
+checked as well. If it was in use and required relocation, it
+wouldn't get properly relocated, with the result that an inode using
+such a block would end up, post resize, with a pointer to a block now
+outside the bounds of the filesystem.
+
+This commit fixes this fencepost error.
+
+Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
+---
+
+Index: e2fsprogs-1.41.4/resize/resize2fs.c
+===================================================================
+--- e2fsprogs-1.41.4.orig/resize/resize2fs.c
++++ e2fsprogs-1.41.4/resize/resize2fs.c
+@@ -233,20 +233,29 @@ static void fix_uninit_block_bitmaps(ext
+
+ /*
+ * If the group descriptor's bitmap and inode table blocks are valid,
+- * release them in the specified filesystem data structure
++ * release them in the new filesystem data structure, and mark them as
++ * reserved so the old inode table blocks don't get overwritten.
+ */
+-static void free_gdp_blocks(ext2_filsys fs, struct ext2_group_desc *gdp)
++static void free_gdp_blocks(ext2_filsys fs,
++ ext2fs_block_bitmap reserve_blocks,
++ struct ext2_group_desc *gdp)
+ {
+ blk_t blk;
+ int j;
+
+ if (gdp->bg_block_bitmap &&
+- (gdp->bg_block_bitmap < fs->super->s_blocks_count))
++ (gdp->bg_block_bitmap < fs->super->s_blocks_count)) {
+ ext2fs_block_alloc_stats(fs, gdp->bg_block_bitmap, -1);
++ ext2fs_mark_block_bitmap(reserve_blocks,
++ gdp->bg_block_bitmap);
++ }
+
+ if (gdp->bg_inode_bitmap &&
+- (gdp->bg_inode_bitmap < fs->super->s_blocks_count))
++ (gdp->bg_inode_bitmap < fs->super->s_blocks_count)) {
+ ext2fs_block_alloc_stats(fs, gdp->bg_inode_bitmap, -1);
++ ext2fs_mark_block_bitmap(reserve_blocks,
++ gdp->bg_inode_bitmap);
++ }
+
+ if (gdp->bg_inode_table == 0 ||
+ (gdp->bg_inode_table >= fs->super->s_blocks_count))
+@@ -257,14 +266,19 @@ static void free_gdp_blocks(ext2_filsys
+ if (blk >= fs->super->s_blocks_count)
+ break;
+ ext2fs_block_alloc_stats(fs, blk, -1);
++ ext2fs_mark_block_bitmap(reserve_blocks, blk);
+ }
+ }
+
+ /*
+ * This routine is shared by the online and offline resize routines.
+ * All of the information which is adjusted in memory is done here.
++ *
++ * The reserve_blocks parameter is only needed when shrinking the
++ * filesystem.
+ */
+-errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs, blk_t new_size)
++errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs,
++ ext2fs_block_bitmap reserve_blocks, blk_t new_size)
+ {
+ errcode_t retval;
+ int overhead = 0;
+@@ -399,8 +413,8 @@ retry:
+ }
+
+ /*
+- * If we are shrinking the number block groups, we're done and
+- * can exit now.
++ * If we are shrinking the number of block groups, we're done
++ * and can exit now.
+ */
+ if (old_fs->group_desc_count > fs->group_desc_count) {
+ /*
+@@ -409,7 +423,8 @@ retry:
+ */
+ for (i = fs->group_desc_count;
+ i < old_fs->group_desc_count; i++) {
+- free_gdp_blocks(fs, &old_fs->group_desc[i]);
++ free_gdp_blocks(fs, reserve_blocks,
++ &old_fs->group_desc[i]);
+ }
+ retval = 0;
+ goto errout;
+@@ -550,7 +565,12 @@ static errcode_t adjust_superblock(ext2_
+ ext2fs_mark_bb_dirty(fs);
+ ext2fs_mark_ib_dirty(fs);
+
+- retval = adjust_fs_info(fs, rfs->old_fs, new_size);
++ retval = ext2fs_allocate_block_bitmap(fs, _("reserved blocks"),
++ &rfs->reserve_blocks);
++ if (retval)
++ return retval;
++
++ retval = adjust_fs_info(fs, rfs->old_fs, rfs->reserve_blocks, new_size);
+ if (retval)
+ goto errout;
+
+@@ -746,17 +766,13 @@ static errcode_t blocks_to_move(ext2_res
+ errcode_t retval;
+ ext2_filsys fs, old_fs;
+ ext2fs_block_bitmap meta_bmap;
++ __u32 save_incompat_flag;
+
+ fs = rfs->new_fs;
+ old_fs = rfs->old_fs;
+ if (old_fs->super->s_blocks_count > fs->super->s_blocks_count)
+ fs = rfs->old_fs;
+
+- retval = ext2fs_allocate_block_bitmap(fs, _("reserved blocks"),
+- &rfs->reserve_blocks);
+- if (retval)
+- return retval;
+-
+ retval = ext2fs_allocate_block_bitmap(fs, _("blocks to be moved"),
+ &rfs->move_blocks);
+ if (retval)
+@@ -788,7 +804,7 @@ static errcode_t blocks_to_move(ext2_res
+ * to the next block group.
+ */
+ blk = ((g+1) * fs->super->s_blocks_per_group) +
+- fs->super->s_first_data_block;
++ fs->super->s_first_data_block - 1;
+ continue;
+ }
+ if (ext2fs_test_block_bitmap(old_fs->block_map, blk) &&
+@@ -890,9 +906,29 @@ static errcode_t blocks_to_move(ext2_res
+
+ /*
+ * Allocate the missing data structures
++ *
++ * XXX We have a problem with FLEX_BG and off-line
++ * resizing where we are growing the size of the
++ * filesystem. ext2fs_allocate_group_table() will try
++ * to reserve the inode table in the desired flex_bg
++ * location. However, passing rfs->reserve_blocks
++ * doesn't work since it only has reserved the blocks
++ * that will be used in the new block group -- and
++ * with flex_bg, we can and will allocate the tables
++ * outside of the block group. And we can't pass in
++ * the fs->block_map because it doesn't handle
++ * overlapping inode table movements right. So for
++ * now, we temporarily disable flex_bg to force
++ * ext2fs_allocate_group_tables() to allocate the bg
++ * metadata in side the block group, and the restore
++ * it afterwards. Ugly, until we can fix this up
++ * right later.
+ */
++ save_incompat_flag = fs->super->s_feature_incompat;
++ fs->super->s_feature_incompat &= ~EXT4_FEATURE_INCOMPAT_FLEX_BG;
+ retval = ext2fs_allocate_group_table(fs, i,
+ rfs->reserve_blocks);
++ fs->super->s_feature_incompat = save_incompat_flag;
+ if (retval)
+ goto errout;
+
+@@ -1857,6 +1893,19 @@ blk_t calculate_minimum_resize_size(ext2
+ data_needed -= SUPER_OVERHEAD(fs) * num_of_superblocks;
+ data_needed -= META_OVERHEAD(fs) * fs->group_desc_count;
+
++ if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) {
++ /*
++ * For ext4 we need to allow for up to a flex_bg worth
++ * of inode tables of slack space so the resize
++ * operation can be guaranteed to finish.
++ */
++ int flexbg_size = 1 << fs->super->s_log_groups_per_flex;
++ int extra_groups;
++
++ extra_groups = flexbg_size - (groups & (flexbg_size - 1));
++ data_needed += META_OVERHEAD(fs) * extra_groups;
++ }
++
+ /*
+ * figure out how many data blocks we have given the number of groups
+ * we need for our inodes
+Index: e2fsprogs-1.41.4/resize/online.c
+===================================================================
+--- e2fsprogs-1.41.4.orig/resize/online.c
++++ e2fsprogs-1.41.4/resize/online.c
+@@ -104,7 +104,7 @@ errcode_t online_resize_fs(ext2_filsys f
+ * but at least it allows on-line resizing to function.
+ */
+ new_fs->super->s_feature_incompat &= ~EXT4_FEATURE_INCOMPAT_FLEX_BG;
+- retval = adjust_fs_info(new_fs, fs, *new_size);
++ retval = adjust_fs_info(new_fs, fs, 0, *new_size);
+ if (retval)
+ return retval;
+
+Index: e2fsprogs-1.41.4/resize/resize2fs.h
+===================================================================
+--- e2fsprogs-1.41.4.orig/resize/resize2fs.h
++++ e2fsprogs-1.41.4/resize/resize2fs.h
+@@ -128,6 +128,7 @@ extern errcode_t resize_fs(ext2_filsys f
+ unsigned long max));
+
+ extern errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs,
++ ext2fs_block_bitmap reserve_blocks,
+ blk_t new_size);
+ extern blk_t calculate_minimum_resize_size(ext2_filsys fs);
+
diff --git a/e2fsprogs.spec b/e2fsprogs.spec
index 22312d0..90ca465 100644
--- a/e2fsprogs.spec
+++ b/e2fsprogs.spec
@@ -4,7 +4,7 @@
Summary: Utilities for managing ext2, ext3, and ext4 filesystems
Name: e2fsprogs
Version: 1.41.4
-Release: 6%{?dist}
+Release: 7%{?dist}
# License based on upstream-modified COPYING file,
# which clearly states "V2" intent.
License: GPLv2
@@ -19,6 +19,7 @@ Patch3: e2fsprogs-1.41.4-debugfs-stat-segfault.patch
Patch4: e2fsprogs-1.41.4-libext2fs-info.patch
Patch5: e2fsprogs-1.41.4-fix-blkid-segfault.patch
Patch6: e2fsprogs-1.41.4-ignore-NEEDS_RECOVERY-mismatch.patch
+Patch7: e2fsprogs-1.41.4-ext4-resize-fixes.patch
Url: http://e2fsprogs.sourceforge.net/
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
@@ -104,6 +105,8 @@ SMP systems.
%patch5 -p1 -b .info
# Ignore NEEDS_RECOVERY mismatch
%patch6 -p1 -b .recovery
+# Fix ext4 resize issues
+%patch7 -p1 -b .resize
%build
%configure --enable-elf-shlibs --enable-nls --disable-e2initrd-helper --enable-blkid-devmapper --enable-blkid-selinux
@@ -302,6 +305,9 @@ fi
%dir %attr(2775, uuidd, uuidd) /var/lib/libuuid
%changelog
+* Wed Apr 22 2009 Eric Sandeen <sandeen@redhat.com> 1.41.4-7
+- Fix ext4 resize issues (#496982)
+
* Sat Apr 11 2009 Eric Sandeen <sandeen@redhat.com> 1.41.4-6
- ignore differing NEEDS_RECOVERY flag on fsck post-resize (#471925)