* Wed Apr 22 2009 Eric Sandeen <sandeen@redhat.com> 1.41.4-7
- Fix ext4 resize issues (#496982)
This commit is contained in:
parent
39346b1b74
commit
36a7badb2d
241
e2fsprogs-1.41.4-ext4-resize-fixes.patch
Normal file
241
e2fsprogs-1.41.4-ext4-resize-fixes.patch
Normal file
@ -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);
|
||||||
|
|
@ -4,7 +4,7 @@
|
|||||||
Summary: Utilities for managing ext2, ext3, and ext4 filesystems
|
Summary: Utilities for managing ext2, ext3, and ext4 filesystems
|
||||||
Name: e2fsprogs
|
Name: e2fsprogs
|
||||||
Version: 1.41.4
|
Version: 1.41.4
|
||||||
Release: 6%{?dist}
|
Release: 7%{?dist}
|
||||||
# License based on upstream-modified COPYING file,
|
# License based on upstream-modified COPYING file,
|
||||||
# which clearly states "V2" intent.
|
# which clearly states "V2" intent.
|
||||||
License: GPLv2
|
License: GPLv2
|
||||||
@ -19,6 +19,7 @@ Patch3: e2fsprogs-1.41.4-debugfs-stat-segfault.patch
|
|||||||
Patch4: e2fsprogs-1.41.4-libext2fs-info.patch
|
Patch4: e2fsprogs-1.41.4-libext2fs-info.patch
|
||||||
Patch5: e2fsprogs-1.41.4-fix-blkid-segfault.patch
|
Patch5: e2fsprogs-1.41.4-fix-blkid-segfault.patch
|
||||||
Patch6: e2fsprogs-1.41.4-ignore-NEEDS_RECOVERY-mismatch.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/
|
Url: http://e2fsprogs.sourceforge.net/
|
||||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||||
@ -104,6 +105,8 @@ SMP systems.
|
|||||||
%patch5 -p1 -b .info
|
%patch5 -p1 -b .info
|
||||||
# Ignore NEEDS_RECOVERY mismatch
|
# Ignore NEEDS_RECOVERY mismatch
|
||||||
%patch6 -p1 -b .recovery
|
%patch6 -p1 -b .recovery
|
||||||
|
# Fix ext4 resize issues
|
||||||
|
%patch7 -p1 -b .resize
|
||||||
|
|
||||||
%build
|
%build
|
||||||
%configure --enable-elf-shlibs --enable-nls --disable-e2initrd-helper --enable-blkid-devmapper --enable-blkid-selinux
|
%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
|
%dir %attr(2775, uuidd, uuidd) /var/lib/libuuid
|
||||||
|
|
||||||
%changelog
|
%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
|
* Sat Apr 11 2009 Eric Sandeen <sandeen@redhat.com> 1.41.4-6
|
||||||
- ignore differing NEEDS_RECOVERY flag on fsck post-resize (#471925)
|
- ignore differing NEEDS_RECOVERY flag on fsck post-resize (#471925)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user