Skip to contentSkip to conversation

e2fsprogs: allocate inode table wholly within group

PATCH In review Eric Sandeen 3 participants 15 messages Jul 2, 2013 – Oct 1, 2013

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 e2fsprogs: allocate inode table wholly within group

Building e2fsprogs 1.42.8 on ppc, I got this:

r_1024_small_bg: ext2 1024 blocksize with small block groups: failed

Because during the resize step it did this:

Itable move group 1 block 1030->1092 (diff 62)

but during e2fsck it found:

/tmp/e2fsprogs-tmp.uiFhgP: Inode table for group 1 is not in group. (block 1092)

i.e. from dumpe2fs we can see:

Group 1: (Blocks 1025-1110)
Backup superblock at 1025, Group descriptors at 1026-1026 Block bitmap at 1090 (+65), Inode bitmap at 1091 (+66) Inode table at 1092-1123 (+67)
^^^^ beyond end of block group

ext2fs_allocate_group_table() currently sends the last block of the group as an acceptable *starting* point for the inode table allocation.

Because the inode table may be several blocks, and must reside wholly within the group, move the last acceptable starting block back by this amount so that the allocated range cannot extend past the end of the group.

---

p.s. I *think* this fixes it; I've not convinced myself that the failure is 100% deterministic, so extra eyeballs on the patch are welcome.

Thanks,
-Eric

lib/ext2fs/alloc_tables.c +3 -0
Index: e2fsprogs-1.42.8/lib/ext2fs/alloc_tables.c
===================================================================
@@ -200,6 +200,9 @@ errcode_t ext2fs_allocate_group_table(ex
 	}
 
 	if (!ext2fs_inode_table_loc(fs, group)) {
+		/* Inode table must fit within group, so adjust last blk */
+		last_blk -= (fs->inode_blocks_per_group - 1);
+
 		retval = ext2fs_get_free_blocks2(fs, group_blk, last_blk,
 						fs->inode_blocks_per_group,
 						bmap, &new_blk);
#1 lore raw

Re: [PATCH] e2fsprogs FTBFS: allocate inode table wholly within group

Quoted 3 lines · Eric Sandeen

Building e2fsprogs 1.42.8 on ppc, I got this:

r_1024_small_bg: ext2 1024 blocksize with small block groups: failed

You can add a RH FTBFS bug to the commit now if you like,

[Bug 980519] New: FTBFS: self checks failure: Tests failed: r_1024_small_bg

https://bugzilla.redhat.com/show_bug.cgi?id=980519

since Karsten Hopp has now reported it for Rawhide as well.

-Eric

Quoted 53 lines

Because during the resize step it did this:

Itable move group 1 block 1030->1092 (diff 62)

but during e2fsck it found:

/tmp/e2fsprogs-tmp.uiFhgP: Inode table for group 1 is not in group. (block 1092)

i.e. from dumpe2fs we can see:

Group 1: (Blocks 1025-1110)
Backup superblock at 1025, Group descriptors at 1026-1026 Block bitmap at 1090 (+65), Inode bitmap at 1091 (+66) Inode table at 1092-1123 (+67)
^^^^ beyond end of block group

ext2fs_allocate_group_table() currently sends the last block of the group as an acceptable *starting* point for the inode table allocation.

Because the inode table may be several blocks, and must reside wholly within the group, move the last acceptable starting block back by this amount so that the allocated range cannot extend past the end of the group.

---

p.s. I *think* this fixes it; I've not convinced myself that the failure is 100% deterministic, so extra eyeballs on the patch are welcome.

Thanks,
-Eric

Index: e2fsprogs-1.42.8/lib/ext2fs/alloc_tables.c
===================================================================

lib/ext2fs/alloc_tables.c +3 -1
@@ -200,6 +200,9 @@ errcode_t ext2fs_allocate_group_table(ex
 	}
 
 	if (!ext2fs_inode_table_loc(fs, group)) {
+		/* Inode table must fit within group, so adjust last blk */
+		last_blk -= (fs->inode_blocks_per_group - 1);
+
 		retval = ext2fs_get_free_blocks2(fs, group_blk, last_blk,
 						fs->inode_blocks_per_group,
 						bmap, &new_blk);
 
--

To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#2 lore raw
In reply to Eric Sandeen
Quoted 12 lines · Eric Sandeen

Building e2fsprogs 1.42.8 on ppc, I got this:

r_1024_small_bg: ext2 1024 blocksize with small block groups: failed

Because during the resize step it did this:

Itable move group 1 block 1030->1092 (diff 62)

but during e2fsck it found:

/tmp/e2fsprogs-tmp.uiFhgP: Inode table for group 1 is not in group. (block 1092)

Quoted 7 lines

i.e. from dumpe2fs we can see:

Group 1: (Blocks 1025-1110)
Backup superblock at 1025, Group descriptors at 1026-1026 Block bitmap at 1090 (+65), Inode bitmap at 1091 (+66) Inode table at 1092-1123 (+67)
^^^^ beyond end of block group

There seems to be something wrong here. The test file system was created like this:

mke2fs -t ext2 -O ^resize_inode -b 1024 -g 1024 -qF /tmp/foo.img 64M

The file system hence should have 64 block groups, and dumpe2fs before the resize looks like this on an x86 system:

Group 1: (Blocks 1025-2048)
Backup superblock at 1025, Group descriptors at 1026-1027 Block bitmap at 1028 (+3), Inode bitmap at 1029 (+4) Inode table at 1030-1061 (+5)

... and after:

Group 1: (Blocks 1025-2048)
Backup superblock at 1025, Group descriptors at 1026-1089 Block bitmap at 1090 (+65), Inode bitmap at 1091 (+66) Inode table at 1092-1123 (+67)

Note the range of block group #1: 1025-2048, whereas on the PPC, apparently the range is quite different: Group 1: (Blocks 1025-1110)

So there's something else going really wrong here....

- Ted

#3 lore raw
Quoted 20 lines · Theodore Ts'o

There seems to be something wrong here. The test file system was created like this:

mke2fs -t ext2 -O ^resize_inode -b 1024 -g 1024 -qF /tmp/foo.img 64M

The file system hence should have 64 block groups, and dumpe2fs before the resize looks like this on an x86 system:

Group 1: (Blocks 1025-2048)
Backup superblock at 1025, Group descriptors at 1026-1027 Block bitmap at 1028 (+3), Inode bitmap at 1029 (+4) Inode table at 1030-1061 (+5)

... and after:

Group 1: (Blocks 1025-2048)
Backup superblock at 1025, Group descriptors at 1026-1089 Block bitmap at 1090 (+65), Inode bitmap at 1091 (+66) Inode table at 1092-1123 (+67)

Quoted 4 lines

Note the range of block group #1: 1025-2048, whereas on the PPC, apparently the range is quite different: Group 1: (Blocks 1025-1110)

So there's something else going really wrong here....

I just tried building e2fsprogs 1.42.8 on a powerpc system in a Debian unstable (sid) chroot, and I'm not able to reproduce this test failure. I tried building using both gcc 4.6.4 and gcc 4.8, in case it was a compiler bug.

So again, there's something really, REALLY wrong....

- Ted

#4 lore raw
In reply to Theodore Ts'o
Quoted 41 lines · Theodore Ts'o
Quoted 12 lines · Eric Sandeen

Building e2fsprogs 1.42.8 on ppc, I got this:

r_1024_small_bg: ext2 1024 blocksize with small block groups: failed

Because during the resize step it did this:

Itable move group 1 block 1030->1092 (diff 62)

but during e2fsck it found:

/tmp/e2fsprogs-tmp.uiFhgP: Inode table for group 1 is not in group. (block 1092)

Quoted 7 lines

i.e. from dumpe2fs we can see:

Group 1: (Blocks 1025-1110)
Backup superblock at 1025, Group descriptors at 1026-1026 Block bitmap at 1090 (+65), Inode bitmap at 1091 (+66) Inode table at 1092-1123 (+67)
^^^^ beyond end of block group

There seems to be something wrong here. The test file system was created like this:

mke2fs -t ext2 -O ^resize_inode -b 1024 -g 1024 -qF /tmp/foo.img 64M

The file system hence should have 64 block groups, and dumpe2fs before the resize looks like this on an x86 system:

Group 1: (Blocks 1025-2048)
Backup superblock at 1025, Group descriptors at 1026-1027 Block bitmap at 1028 (+3), Inode bitmap at 1029 (+4) Inode table at 1030-1061 (+5)

... and after:

Group 1: (Blocks 1025-2048)
Backup superblock at 1025, Group descriptors at 1026-1089 Block bitmap at 1090 (+65), Inode bitmap at 1091 (+66) Inode table at 1092-1123 (+67)

Quoted 6 lines

Note the range of block group #1: 1025-2048, whereas on the PPC, apparently the range is quite different: Group 1: (Blocks 1025-1110)

So there's something else going really wrong here....

- Ted

Perhaps so, I'll look into it more. But nonetheless isn't the patch correct?

Don't we need to ensure the inode table is wholly within be group, however we may have gotten here?

-Eric

#5 lore raw
In reply to Theodore Ts'o
Quoted 41 lines · Theodore Ts'o
Quoted 12 lines · Eric Sandeen

Building e2fsprogs 1.42.8 on ppc, I got this:

r_1024_small_bg: ext2 1024 blocksize with small block groups: failed

Because during the resize step it did this:

Itable move group 1 block 1030->1092 (diff 62)

but during e2fsck it found:

/tmp/e2fsprogs-tmp.uiFhgP: Inode table for group 1 is not in group. (block 1092)

Quoted 7 lines

i.e. from dumpe2fs we can see:

Group 1: (Blocks 1025-1110)
Backup superblock at 1025, Group descriptors at 1026-1026 Block bitmap at 1090 (+65), Inode bitmap at 1091 (+66) Inode table at 1092-1123 (+67)
^^^^ beyond end of block group

There seems to be something wrong here. The test file system was created like this:

mke2fs -t ext2 -O ^resize_inode -b 1024 -g 1024 -qF /tmp/foo.img 64M

The file system hence should have 64 block groups, and dumpe2fs before the resize looks like this on an x86 system:

Group 1: (Blocks 1025-2048)
Backup superblock at 1025, Group descriptors at 1026-1027 Block bitmap at 1028 (+3), Inode bitmap at 1029 (+4) Inode table at 1030-1061 (+5)

... and after:

Group 1: (Blocks 1025-2048)
Backup superblock at 1025, Group descriptors at 1026-1089 Block bitmap at 1090 (+65), Inode bitmap at 1091 (+66) Inode table at 1092-1123 (+67)

Quoted 4 lines

Note the range of block group #1: 1025-2048, whereas on the PPC, apparently the range is quite different: Group 1: (Blocks 1025-1110)

So there's something else going really wrong here....

I don't think so - that's only after the shrink, right?

However, I understand your confusion. The test is not at all obvious about what it's doing:

Quoted 9 lines

test_description="ext2 1024 blocksize with small block groups" FEATURES="-t ext2 -O ^resize_inode -b 1024 -g 1024" SIZE_1=64M
SIZE_2=2G
LOG=$test_name.log
E2FSCK=../e2fsck/e2fsck

. $cmd_dir/scripts/resize_test

Um, ok, so we "resize test" with those parameters.

Looking at that script, which sadly has no comments, it invokes a resize to $SIZE_2 (2G) first, but then does something different:

# grep RESIZE tests/scripts/resize_test | grep -v echo
if ! $RESIZE2FS $RESIZE2FS_OPTS -d 31 $TMPFILE $SIZE_2 >> $LOG 2>&1
if ! $RESIZE2FS $RESIZE2FS_OPTS -d 31 -M $TMPFILE $SIZE_2 >> $LOG 2>&1
if ! $RESIZE2FS $RESIZE2FS_OPTS -d 31 -M $TMPFILE $SIZE_2 >> $LOG 2>&1
if ! $RESIZE2FS $RESIZE2FS_OPTS -d 31 -M $TMPFILE $SIZE_2 >> $LOG 2>&1

so it does 4 resizes; the last 3 are using "-M" which says "go to the
minimum size." Which is a weird thing to do when also specifying
an actual size:

# grep "\-M" tests/r_1024_small_bg.log 
../resize/resize2fs -d 31 -M /tmp/e2fsprogs-tmp.LoNby5 2G
../resize/resize2fs -d 31 -M /tmp/e2fsprogs-tmp.LoNby5 2G
../resize/resize2fs -d 31 -M /tmp/e2fsprogs-tmp.LoNby5 2G

But the 2G is ignored.... so it's re-resizing to minimum sizes. On x86:

# grep -w "resize\|is now" tests/r_1024_small_bg.log 
../resize/resize2fs -d 31 /tmp/e2fsprogs-tmp.LoNby5 2G
The filesystem on /tmp/e2fsprogs-tmp.LoNby5 is now 2097152 blocks long.
../resize/resize2fs -d 31 -M /tmp/e2fsprogs-tmp.LoNby5 2G
The filesystem on /tmp/e2fsprogs-tmp.LoNby5 is now 1174 blocks long.
../resize/resize2fs -d 31 -M /tmp/e2fsprogs-tmp.LoNby5 2G
The filesystem on /tmp/e2fsprogs-tmp.LoNby5 is now 1002 blocks long.

on the failing PPC build:

# grep -w "resize\|is now" tests/r_1024_small_bg.log 
../resize/resize2fs -d 31 /tmp/e2fsprogs-tmp.4KTO7a 2G
The filesystem on /tmp/e2fsprogs-tmp.4KTO7a is now 2097152 blocks long.
../resize/resize2fs -d 31 -M /tmp/e2fsprogs-tmp.4KTO7a 2G
The filesystem on /tmp/e2fsprogs-tmp.4KTO7a is now 1247 blocks long.
../resize/resize2fs -d 31 -M /tmp/e2fsprogs-tmp.4KTO7a 2G
The filesystem on /tmp/e2fsprogs-tmp.4KTO7a is now 1121 blocks long.

so they're both shrinking quite a bit. But I think due to the vagaries of the initial filesystem population, the test is behaving differently and just happening to hit this corner case.

On the last failing run, the minimum size happens to be calculated at 1121 blocks; with debug printfs:

Quoted 4 lines

../resize/resize2fs -d 31 -M /tmp/e2fsprogs-tmp.gB4G7E 2G resize2fs 1.42.8 (20-Jun-2013)
forcing to min size 1121
Resizing the filesystem on /tmp/e2fsprogs-tmp.gB4G7E to 1121 (1k) blocks.

But what's weird is that in this resize run it didn't actually move the inode table; that was done in a prior minimization run, and in this case it seems to have simply shrunk past the existing inode table end. Argh. Still looking.

-Eric

#6 lore raw
In reply to Eric Sandeen

Ok, resetting a little on this one.

The actual problem seems to be that the test does successive "-M" minimal resizes, and eventually we resize into the middle of an inode table, leaving the end of the table beyond the fs.

Point "resize2fs -M" at the attached image once or twice w/ fscks in between and you should see it.

It seems like the obvious fix would be to move the inode table if necessary, as with the following patch.

But then of course we find that we've run out of room to move the table, and the resize fails; so we've let resize2fs choose its own minimum size - which which it cannot handle. Presumably something's gone wrong in calculate_minimum_resize_size(), though I can't tell what.

Truth be told, I'm not enjoying resize2fs right now!

resize/resize2fs.c +10 -3
index 204b10a..27dc5e6 100644
@@ -891,18 +891,25 @@ static errcode_t blocks_to_move(ext2_resize_t rfs)
 	new_size = ext2fs_blocks_count(fs->super);
 	if (new_size < ext2fs_blocks_count(old_fs->super)) {
 		for (g = 0; g < fs->group_desc_count; g++) {
+			int realloc = 0;
 			/*
 			 * ext2fs_allocate_group_table re-allocates bitmaps
 			 * which are set to block 0.
 			 */
 			if (ext2fs_block_bitmap_loc(fs, g) >= new_size) {
 				ext2fs_block_bitmap_loc_set(fs, g, 0);
-				retval = ext2fs_allocate_group_table(fs, g, 0);
-				if (retval)
-					return retval;
+				realloc = 1;
 			}
 			if (ext2fs_inode_bitmap_loc(fs, g) >= new_size) {
 				ext2fs_inode_bitmap_loc_set(fs, g, 0);
+				realloc = 1;
+			}
+			if (ext2fs_inode_table_loc(fs, g) + fs->inode_blocks_per_group > new_size) {
+				ext2fs_inode_table_loc_set(fs, g, 0);
+				realloc = 1;
+			}
+
+			if (realloc) {
 				retval = ext2fs_allocate_group_table(fs, g, 0);
 				if (retval)
 					return retval;
#7 lore raw
Quoted 4 lines · Eric Sandeen

The actual problem seems to be that the test does successive "-M" minimal resizes, and eventually we resize into the middle of an inode table, leaving the end of the table beyond the fs.

Point "resize2fs -M" at the attached image once or twice w/ fscks in between and you should see it.

I've been going through my patch backlog, so I finally had a chance to take a very close look at your test image. I now understand why things are failing.

1) The test image (which you said was generated on a ppc e2fsprogs?) was doing something very weird as far as the location of the allocation bitmaps and inode table:

Filesystem features:      ext_attr dir_index filetype sparse_super
Inode count:              512
Block count:              1247

...

Group 0: (Blocks 1-1024)
Primary superblock at 1, Group descriptors at 2-2 Block bitmap at 66 (+65), Inode bitmap at 67 (+66) Inode table at 68-99 (+67)

Group 1: (Blocks 1025-1246)
Backup superblock at 1025, Group descriptors at 1026-1026 Block bitmap at 1090 (+65), Inode bitmap at 1091 (+66) Inode table at 1092-1123 (+67)

Compare and contrast this with what x86 and Debian's ppc mke2fs creates:

Group 0: (Blocks 1-1024)
Primary superblock at 1, Group descriptors at 2-2 Block bitmap at 3 (+2), Inode bitmap at 4 (+3) Inode table at 5-14 (+4)

Group 1: (Blocks 1025-1246)
Backup superblock at 1025, Group descriptors at 1026-1026 Block bitmap at 1027 (+2), Inode bitmap at 1028 (+3) Inode table at 1029-1038 (+4)

So I'm not sure why Fedora's ppc mke2fs is creating file systems in this way, but that's one of the causes of the bug.

2) The second cause of the bug is that calculate_minimum_resize_size(), when we calculate the number of blocks for the last group, the code has an implicit assumption that the metadata blocks are located at the very beginning of the block
group. That's an easy fix.

Quoted 2 lines

It seems like the obvious fix would be to move the inode table if necessary, as with the following patch.

Your patch is a good one, but at least in the context of resize2fs -M, we should be fixing calculate_minimum_resize_size() so we can avoid needing to move the inode table (since even if it can succeed, it's not worth the danger).

I'll send out some patches to address this. Thanks for sending the test image; and my apologies for not having time to get back to this until now.

- Ted

#8 lore raw

PATCH 1/4 resize2fs: add debugging support for resize2fs -M calcuations

---
 resize/main.c         |  2 +-
 resize/resize2fs.8.in |  4 +++-
 resize/resize2fs.c    | 59 +++++++++++++++++++++++++++++++++++++++++++++------
 resize/resize2fs.h    |  3 ++-
 4 files changed, 59 insertions(+), 9 deletions(-)
resize/main.c +1 -1
index b648a15..1394ae1 100644
@@ -328,7 +328,7 @@ int main (int argc, char ** argv)
 		exit(1);
 	}
 
-	min_size = calculate_minimum_resize_size(fs);
+	min_size = calculate_minimum_resize_size(fs, flags);
 
 	if (print_min_size) {
 		if (!force && ((fs->super->s_state & EXT2_ERROR_FS) ||
resize/resize2fs.8.in +3 -1
index 735fc91..a1f3099 100644
@@ -101,7 +101,9 @@ from the following list:
 	8	\-\ Debug moving the inode table
 .br
 	16	\-\ Print timing information
-.TP 
+.br
+	32	\-\ Debug minimum filesystem size (\-M) calculation
+.TP
 .B \-f
 Forces resize2fs to proceed with the filesystem resize operation, overriding
 some safety checks which resize2fs normally enforces.
resize/resize2fs.c +53 -6

125 lines not on this page · raw message

resize/resize2fs.h +2 -1
index d425491..52319b5 100644
@@ -77,6 +77,7 @@ typedef struct ext2_sim_progress *ext2_sim_progmeter;
 #define RESIZE_DEBUG_INODEMAP		0x0004
 #define RESIZE_DEBUG_ITABLEMOVE		0x0008
 #define RESIZE_DEBUG_RTRACK		0x0010
+#define RESIZE_DEBUG_MIN_CALC		0x0020
 
 #define RESIZE_PERCENT_COMPLETE		0x0100
 #define RESIZE_VERBOSE			0x0200
@@ -145,7 +146,7 @@ extern errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
 extern errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs,
 				ext2fs_block_bitmap reserve_blocks,
 				blk64_t new_size);
-extern blk64_t calculate_minimum_resize_size(ext2_filsys fs);
+extern blk64_t calculate_minimum_resize_size(ext2_filsys fs, int flags);
 
 
 /* extent.c */
Signature · 1 line
1.7.12.rc0.22.gcdd159b
#9 lore raw

PATCH 2/4 resize2fs: fix -M size calculations to avoid cutting off the inode table

If the file system's inode table blocks in the last block group are located in the middle or the end of the block group, it's possible for resize2fs -M to use a size which will require relocating the inode table blocks in the last block group. This can lead to all sorts of problems, so solve it by simply guaranteeing that we will never do that.

---
 resize/resize2fs.c | 9 +++++++++
 1 file changed, 9 insertions(+)
resize/resize2fs.c +9 -0
index 51b85b8..1e4ac19 100644
@@ -2224,6 +2224,15 @@ blk64_t calculate_minimum_resize_size(ext2_filsys fs, int flags)
 	blks_needed = (groups-1) * EXT2_BLOCKS_PER_GROUP(fs->super);
 	blks_needed += overhead;
 
+	/*
+	 * Make sure blks_needed covers the end of the inode table in
+	 * the last block group.
+	 */
+	overhead = ext2fs_inode_table_loc(fs, groups-1) +
+		fs->inode_blocks_per_group;
+	if (blks_needed < overhead)
+		blks_needed = overhead;
+
 #ifdef RESIZE2FS_DEBUG
 	if (flags & RESIZE_DEBUG_MIN_CALC)
 		printf("Estimated blocks needed: %llu\n", blks_needed);
Signature · 1 line
1.7.12.rc0.22.gcdd159b
#10 lore raw

PATCH 3/4 resize2fs: relocate inode table blocks if necessary when shrinking

In reply to Theodore Ts'o

If the file system is being shrunk, and a block group's inode table falls beyond the end of the inode table, we need to try to relocate the inode table blocks.

---
 resize/resize2fs.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)
resize/resize2fs.c +17 -7
index 1e4ac19..ec1594e 100644
@@ -884,24 +884,34 @@ static errcode_t blocks_to_move(ext2_resize_t rfs)
 	fs = rfs->new_fs;
 
 	/*
-	 * If we're shrinking the filesystem, we need to move any group's
-	 * bitmaps which are beyond the end of the new filesystem.
+	 * If we're shrinking the filesystem, we need to move any
+	 * group's metadata blocks (either allocation bitmaps or the
+	 * inode table) which are beyond the end of the new
+	 * filesystem.
 	 */
 	new_size = ext2fs_blocks_count(fs->super);
 	if (new_size < ext2fs_blocks_count(old_fs->super)) {
 		for (g = 0; g < fs->group_desc_count; g++) {
+			int realloc = 0;
 			/*
-			 * ext2fs_allocate_group_table re-allocates bitmaps
-			 * which are set to block 0.
+			 * ext2fs_allocate_group_table will re-allocate any
+			 * metadata blocks whose location is set to zero.
 			 */
 			if (ext2fs_block_bitmap_loc(fs, g) >= new_size) {
 				ext2fs_block_bitmap_loc_set(fs, g, 0);
-				retval = ext2fs_allocate_group_table(fs, g, 0);
-				if (retval)
-					return retval;
+				realloc = 1;
 			}
 			if (ext2fs_inode_bitmap_loc(fs, g) >= new_size) {
 				ext2fs_inode_bitmap_loc_set(fs, g, 0);
+				realloc = 1;
+			}
+			if ((ext2fs_inode_table_loc(fs, g) +
+			     fs->inode_blocks_per_group) > new_size) {
+				ext2fs_inode_table_loc_set(fs, g, 0);
+				realloc = 1;
+			}
+
+			if (realloc) {
 				retval = ext2fs_allocate_group_table(fs, g, 0);
 				if (retval)
 					return retval;
Signature · 1 line
1.7.12.rc0.22.gcdd159b
#11 lore raw

PATCH 4/4 tests: add test for resize2fs -M with inode table in middle of block group

In reply to Theodore Ts'o

Eric Sandeen reported that Fedora's mke2fs when compiled for ppc was creating a file system which caused problems with resize2fs -M. Closer examination showed that the problem was file system which looked like this:

Filesystem features:      ext_attr dir_index filetype sparse_super
Inode count:              512
Block count:              1247

...

Group 0: (Blocks 1-1024)
Primary superblock at 1, Group descriptors at 2-2 Block bitmap at 66 (+65), Inode bitmap at 67 (+66) Inode table at 68-99 (+67)

Group 1: (Blocks 1025-1246)
Backup superblock at 1025, Group descriptors at 1026-1026 Block bitmap at 1090 (+65), Inode bitmap at 1091 (+66) Inode table at 1092-1123 (+67)

It's not obvious to me why Fedora's ppc mke2fs is creating file systems like this (I can't reproduce this on debian ppc systems), but resize2fs -M should be able to deal with such file systems, which is what this test is designed to check.

---
 tests/r_min_itable/expect   |  14 ++++++++++++++
 tests/r_min_itable/image.gz | Bin 0 -> 3597 bytes
 tests/r_min_itable/name     |   1 +
 tests/r_min_itable/script   |  43 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 58 insertions(+)
 create mode 100644 tests/r_min_itable/expect
 create mode 100644 tests/r_min_itable/image.gz
 create mode 100644 tests/r_min_itable/name
 create mode 100644 tests/r_min_itable/script
tests/r_min_itable/expect new file +14 -0
new file mode 100644
index 0000000..104688a
@@ -0,0 +1,14 @@
+resize2fs test
+resize2fs -M test.img
+Resizing the filesystem on test.img to 1124 (1k) blocks.
+The filesystem on test.img is now 1124 blocks long.
+
+Exit status is 0
+e2fsck 1.42.8 (20-Jun-2013)
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 13/512 files (0.0% non-contiguous), 1120/1124 blocks
+Exit status is 0
tests/r_min_itable/image.gz new file binary +0 -0
new file mode 100644
index 0000000000000000000000000000000000000000..7c40c5661c86c8fc81e5c73b2adfe1658666df2c
GIT binary patch
tests/r_min_itable/name new file +1 -0
new file mode 100644
index 0000000..841b043
@@ -0,0 +1 @@
+resize2fs -M with inode table in middle of last block group
tests/r_min_itable/script new file +43 -0

43 lines not on this page · raw message

Signature · 1 line
1.7.12.rc0.22.gcdd159b
#12 lore raw
In reply to Theodore Ts'o
Quoted 6 lines · Theodore Ts'o
Quoted 4 lines · Eric Sandeen

The actual problem seems to be that the test does successive "-M" minimal resizes, and eventually we resize into the middle of an inode table, leaving the end of the table beyond the fs.

Point "resize2fs -M" at the attached image once or twice w/ fscks in between and you should see it.

Quoted 7 lines

I've been going through my patch backlog, so I finally had a chance to take a very close look at your test image. I now understand why things are failing.

1) The test image (which you said was generated on a ppc e2fsprogs?) was doing something very weird as far as the location of the allocation bitmaps and inode table:

Yes, this was just during a fedora build, during the "make check" phase.

https://bugzilla.redhat.com/show_bug.cgi?id=980519

No idea why things should be coming out differently, that's a bit alarming in and of itself.

(Fedora isn't carrying any interesting patches to speak of).

-Eric

Quoted 51 lines
Filesystem features:      ext_attr dir_index filetype sparse_super
Inode count:              512
Block count:              1247

...

Group 0: (Blocks 1-1024)
Primary superblock at 1, Group descriptors at 2-2 Block bitmap at 66 (+65), Inode bitmap at 67 (+66) Inode table at 68-99 (+67)

Group 1: (Blocks 1025-1246)
Backup superblock at 1025, Group descriptors at 1026-1026 Block bitmap at 1090 (+65), Inode bitmap at 1091 (+66) Inode table at 1092-1123 (+67)

Compare and contrast this with what x86 and Debian's ppc mke2fs creates:

Group 0: (Blocks 1-1024)
Primary superblock at 1, Group descriptors at 2-2 Block bitmap at 3 (+2), Inode bitmap at 4 (+3) Inode table at 5-14 (+4)

Group 1: (Blocks 1025-1246)
Backup superblock at 1025, Group descriptors at 1026-1026 Block bitmap at 1027 (+2), Inode bitmap at 1028 (+3) Inode table at 1029-1038 (+4)

So I'm not sure why Fedora's ppc mke2fs is creating file systems in this way, but that's one of the causes of the bug.

2) The second cause of the bug is that calculate_minimum_resize_size(), when we calculate the number of blocks for the last group, the code has an implicit assumption that the metadata blocks are located at the very beginning of the block
group. That's an easy fix.

Quoted 2 lines

It seems like the obvious fix would be to move the inode table if necessary, as with the following patch.

Your patch is a good one, but at least in the context of resize2fs -M, we should be fixing calculate_minimum_resize_size() so we can avoid needing to move the inode table (since even if it can succeed, it's not worth the danger).

I'll send out some patches to address this. Thanks for sending the test image; and my apologies for not having time to get back to this until now.

- Ted

#13 lore raw
Quoted 15 lines · Eric Sandeen
Quoted 6 lines · Theodore Ts'o
Quoted 4 lines · Eric Sandeen

The actual problem seems to be that the test does successive "-M" minimal resizes, and eventually we resize into the middle of an inode table, leaving the end of the table beyond the fs.

Point "resize2fs -M" at the attached image once or twice w/ fscks in between and you should see it.

Quoted 7 lines

I've been going through my patch backlog, so I finally had a chance to take a very close look at your test image. I now understand why things are failing.

1) The test image (which you said was generated on a ppc e2fsprogs?) was doing something very weird as far as the location of the allocation bitmaps and inode table:

Quoted 8 lines

Yes, this was just during a fedora build, during the "make check" phase.

https://bugzilla.redhat.com/show_bug.cgi?id=980519

No idea why things should be coming out differently, that's a bit alarming in and of itself.

(Fedora isn't carrying any interesting patches to speak of).

But I am doing this:

%check
+# XXX ERS Hack for now; this bug has existed for a while, +# i.e. it is not a regression in this release, but there +# is no fix yet, and we need to get this package building. +# See Bug 987133 - resize2fs tests failing on ppc, s390 +rm -rf tests/r_1024_small_bg*
+rm -rf tests/r_64bit_big_expand*
+rm -rf tests/r_bigalloc_big_expand*
+rm -rf tests/r_ext4_big_expand*
make check

I'll retest w/ your patches, thanks.

-Eric

#14 lore raw
Quoted 38 lines · Eric Sandeen
Quoted 15 lines · Eric Sandeen
Quoted 6 lines · Theodore Ts'o
Quoted 4 lines · Eric Sandeen

The actual problem seems to be that the test does successive "-M" minimal resizes, and eventually we resize into the middle of an inode table, leaving the end of the table beyond the fs.

Point "resize2fs -M" at the attached image once or twice w/ fscks in between and you should see it.

Quoted 7 lines

I've been going through my patch backlog, so I finally had a chance to take a very close look at your test image. I now understand why things are failing.

1) The test image (which you said was generated on a ppc e2fsprogs?) was doing something very weird as far as the location of the allocation bitmaps and inode table:

Quoted 8 lines

Yes, this was just during a fedora build, during the "make check" phase.

https://bugzilla.redhat.com/show_bug.cgi?id=980519

No idea why things should be coming out differently, that's a bit alarming in and of itself.

(Fedora isn't carrying any interesting patches to speak of).

But I am doing this:

%check

(quoted diff) +8 -0
+# XXX ERS Hack for now; this bug has existed for a while,
+# i.e. it is not a regression in this release, but there
+# is no fix yet, and we need to get this package building.
+# See Bug 987133 - resize2fs tests failing on ppc, s390
+rm -rf tests/r_1024_small_bg*
+rm -rf tests/r_64bit_big_expand*
+rm -rf tests/r_bigalloc_big_expand*
+rm -rf tests/r_ext4_big_expand*
 make check
Quoted 1 line

I'll retest w/ your patches, thanks.

Now all are passing on ppc64, last 3 are still failing on s390. :(

-Eric