diff --git a/ext4-fix-resize-when-resizing-within-single-group.patch b/ext4-fix-resize-when-resizing-within-single-group.patch new file mode 100644 index 0000000..9d911b4 --- /dev/null +++ b/ext4-fix-resize-when-resizing-within-single-group.patch @@ -0,0 +1,82 @@ +From a0ade1deb86d2325aecc36272bb4505a6eec9235 Mon Sep 17 00:00:00 2001 +From: Lukas Czerner +Date: Mon, 20 Feb 2012 23:02:06 -0500 +Subject: [PATCH] ext4: fix resize when resizing within single group + +When resizing file system in the way that the new size of the file +system is still in the same group (no new groups are added), then we can +hit a BUG_ON in ext4_alloc_group_tables() + +BUG_ON(flex_gd->count == 0 || group_data == NULL); + +because flex_gd->count is zero. The reason is the missing check for such +case, so the code always extend the last group fully and then attempt to +add more groups, but at that time n_blocks_count is actually smaller +than o_blocks_count. + +It can be easily reproduced like this: + +mkfs.ext4 -b 4096 /dev/sda 30M +mount /dev/sda /mnt/test +resize2fs /dev/sda 50M + +Fix this by checking whether the resize happens within the singe group +and only add that many blocks into the last group to satisfy user +request. Then o_blocks_count == n_blocks_count and the resize will exit +successfully without and attempt to add more groups into the fs. + +Also fix mixing together block number and blocks count which might be +confusing and can easily lead to off-by-one errors (but it is actually +not the case here since the two occurrence of this mix-up will cancel +each other). + +Signed-off-by: Lukas Czerner +Reported-by: Milan Broz +Reviewed-by: Eric Sandeen +Signed-off-by: "Theodore Ts'o" +--- + fs/ext4/resize.c | 14 ++++++++------ + 1 files changed, 8 insertions(+), 6 deletions(-) + +diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c +index f9d948f..3fed79d 100644 +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -1582,7 +1582,7 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count) + ext4_fsblk_t o_blocks_count; + ext4_group_t o_group; + ext4_group_t n_group; +- ext4_grpblk_t offset; ++ ext4_grpblk_t offset, add; + unsigned long n_desc_blocks; + unsigned long o_desc_blocks; + unsigned long desc_blocks; +@@ -1605,7 +1605,7 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count) + return 0; + + ext4_get_group_no_and_offset(sb, n_blocks_count - 1, &n_group, &offset); +- ext4_get_group_no_and_offset(sb, o_blocks_count, &o_group, &offset); ++ ext4_get_group_no_and_offset(sb, o_blocks_count - 1, &o_group, &offset); + + n_desc_blocks = (n_group + EXT4_DESC_PER_BLOCK(sb)) / + EXT4_DESC_PER_BLOCK(sb); +@@ -1634,10 +1634,12 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count) + } + brelse(bh); + +- if (offset != 0) { +- /* extend the last group */ +- ext4_grpblk_t add; +- add = EXT4_BLOCKS_PER_GROUP(sb) - offset; ++ /* extend the last group */ ++ if (n_group == o_group) ++ add = n_blocks_count - o_blocks_count; ++ else ++ add = EXT4_BLOCKS_PER_GROUP(sb) - (offset + 1); ++ if (add > 0) { + err = ext4_group_extend_no_check(sb, o_blocks_count, add); + if (err) + goto out; +-- +1.7.6.5 + diff --git a/kernel.spec b/kernel.spec index 0053349..9a79731 100644 --- a/kernel.spec +++ b/kernel.spec @@ -719,6 +719,7 @@ Patch2901: linux-2.6-v4l-dvb-experimental.patch Patch2902: imon-dont-wedge-hardware-after-early-callbacks.patch # fs fixes +Patch4000: ext4-fix-resize-when-resizing-within-single-group.patch # NFSv4 Patch1101: linux-3.1-keys-remove-special-keyring.patch @@ -1348,6 +1349,7 @@ ApplyPatch arm-tegra-nvec-kconfig.patch # # ext4 +ApplyPatch ext4-fix-resize-when-resizing-within-single-group.patch # xfs @@ -2380,6 +2382,7 @@ fi # '-' %changelog * Tue Feb 21 2012 Josh Boyer +- ext4: fix resize when resizing within single group (rhbz 786454) - imon: don't wedge hardware after early callbacks (rhbz 781832) * Tue Feb 21 2012 Josh Boyer - 3.3.0-0.rc4.git1.2