[kernel] ext4: fix resize when resizing within single group (rhbz 786454)

Josh Boyer jwboyer at fedoraproject.org
Tue Feb 21 19:42:54 UTC 2012


commit 598ed8b2a0012e687d94d80a04d7e47cd1aad045
Author: Josh Boyer <jwboyer at redhat.com>
Date:   Tue Feb 21 14:42:16 2012 -0500

    ext4: fix resize when resizing within single group (rhbz 786454)

 ...-resize-when-resizing-within-single-group.patch |   82 ++++++++++++++++++++
 kernel.spec                                        |    3 +
 2 files changed, 85 insertions(+), 0 deletions(-)
---
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 <lczerner at redhat.com>
+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 <lczerner at redhat.com>
+Reported-by: Milan Broz <mbroz at redhat.com>
+Reviewed-by: Eric Sandeen <sandeen at redhat.com>
+Signed-off-by: "Theodore Ts'o" <tytso at mit.edu>
+---
+ 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 3bb9f1a..4f71ed6 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -717,6 +717,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
@@ -1346,6 +1347,7 @@ ApplyPatch arm-tegra-nvec-kconfig.patch
 #
 
 # ext4
+ApplyPatch ext4-fix-resize-when-resizing-within-single-group.patch
 
 # xfs
 
@@ -2368,6 +2370,7 @@ fi
 #                 ||     ||
 %changelog
 * Tue Feb 21 2012 Josh Boyer <jwboyer at redhat.com>
+- 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 <jwboyer at redhat.com> - 3.3.0-0.rc4.git1.2


More information about the scm-commits mailing list