mirror of https://gitee.com/openkylin/linux.git
[PATCH] fix ext3 mounts at 16T
I need to do some actual IO testing now, but this gets things mounting for a 16T ext3 filesystem. (patched up e2fsprogs is needed too, I'll send that off the kernel list) This patch fixes these issues in the kernel: o sbi->s_groups_count overflows in ext3_fill_super() sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) - le32_to_cpu(es->s_first_data_block) + EXT3_BLOCKS_PER_GROUP(sb) - 1) / EXT3_BLOCKS_PER_GROUP(sb); at 16T, s_blocks_count is already maxed out; adding EXT3_BLOCKS_PER_GROUP(sb) overflows it and groups_count comes out to 0. Not really what we want, and causes a failed mount. Feel free to check my math (actually, please do!), but changing it this way should work & avoid the overflow: (A + B - 1)/B changed to: ((A - 1)/B) + 1 o ext3_check_descriptors() overflows range checks ext3_check_descriptors() iterates over all block groups making sure that various bits are within the right block ranges... on the last pass through, it is checking the error case [item] >= block + EXT3_BLOCKS_PER_GROUP(sb) where "block" is the first block in the last block group. The last block in this group (and the last one that will fit in 32 bits) is block + EXT3_BLOCKS_PER_GROUP(sb)- 1. block + EXT3_BLOCKS_PER_GROUP(sb) wraps back around to 0. so, make things clearer with "first_block" and "last_block" where those are first and last, inclusive, and use <, > rather than <, >=. Finally, the last block group may be smaller than the rest, so account for this on the last pass through: last_block = sb->s_blocks_count - 1; (a similar patch could be done for ext2; does anyone in their right mind use ext2 at 16T? I'll send an ext2 patch doing the same thing if that's warranted) Signed-off-by: Eric Sandeen <esandeen@redhat.com> Cc: Mingming Cao <cmm@us.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
2aed348469
commit
855565e81a
|
@ -1174,7 +1174,8 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es,
|
|||
static int ext3_check_descriptors (struct super_block * sb)
|
||||
{
|
||||
struct ext3_sb_info *sbi = EXT3_SB(sb);
|
||||
ext3_fsblk_t block = le32_to_cpu(sbi->s_es->s_first_data_block);
|
||||
ext3_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
|
||||
ext3_fsblk_t last_block;
|
||||
struct ext3_group_desc * gdp = NULL;
|
||||
int desc_block = 0;
|
||||
int i;
|
||||
|
@ -1183,12 +1184,17 @@ static int ext3_check_descriptors (struct super_block * sb)
|
|||
|
||||
for (i = 0; i < sbi->s_groups_count; i++)
|
||||
{
|
||||
if (i == sbi->s_groups_count - 1)
|
||||
last_block = le32_to_cpu(sbi->s_es->s_blocks_count) - 1;
|
||||
else
|
||||
last_block = first_block +
|
||||
(EXT3_BLOCKS_PER_GROUP(sb) - 1);
|
||||
|
||||
if ((i % EXT3_DESC_PER_BLOCK(sb)) == 0)
|
||||
gdp = (struct ext3_group_desc *)
|
||||
sbi->s_group_desc[desc_block++]->b_data;
|
||||
if (le32_to_cpu(gdp->bg_block_bitmap) < block ||
|
||||
le32_to_cpu(gdp->bg_block_bitmap) >=
|
||||
block + EXT3_BLOCKS_PER_GROUP(sb))
|
||||
if (le32_to_cpu(gdp->bg_block_bitmap) < first_block ||
|
||||
le32_to_cpu(gdp->bg_block_bitmap) > last_block)
|
||||
{
|
||||
ext3_error (sb, "ext3_check_descriptors",
|
||||
"Block bitmap for group %d"
|
||||
|
@ -1197,9 +1203,8 @@ static int ext3_check_descriptors (struct super_block * sb)
|
|||
le32_to_cpu(gdp->bg_block_bitmap));
|
||||
return 0;
|
||||
}
|
||||
if (le32_to_cpu(gdp->bg_inode_bitmap) < block ||
|
||||
le32_to_cpu(gdp->bg_inode_bitmap) >=
|
||||
block + EXT3_BLOCKS_PER_GROUP(sb))
|
||||
if (le32_to_cpu(gdp->bg_inode_bitmap) < first_block ||
|
||||
le32_to_cpu(gdp->bg_inode_bitmap) > last_block)
|
||||
{
|
||||
ext3_error (sb, "ext3_check_descriptors",
|
||||
"Inode bitmap for group %d"
|
||||
|
@ -1208,9 +1213,9 @@ static int ext3_check_descriptors (struct super_block * sb)
|
|||
le32_to_cpu(gdp->bg_inode_bitmap));
|
||||
return 0;
|
||||
}
|
||||
if (le32_to_cpu(gdp->bg_inode_table) < block ||
|
||||
le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >=
|
||||
block + EXT3_BLOCKS_PER_GROUP(sb))
|
||||
if (le32_to_cpu(gdp->bg_inode_table) < first_block ||
|
||||
le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >
|
||||
last_block)
|
||||
{
|
||||
ext3_error (sb, "ext3_check_descriptors",
|
||||
"Inode table for group %d"
|
||||
|
@ -1219,7 +1224,7 @@ static int ext3_check_descriptors (struct super_block * sb)
|
|||
le32_to_cpu(gdp->bg_inode_table));
|
||||
return 0;
|
||||
}
|
||||
block += EXT3_BLOCKS_PER_GROUP(sb);
|
||||
first_block += EXT3_BLOCKS_PER_GROUP(sb);
|
||||
gdp++;
|
||||
}
|
||||
|
||||
|
@ -1622,10 +1627,9 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
|
|||
|
||||
if (EXT3_BLOCKS_PER_GROUP(sb) == 0)
|
||||
goto cantfind_ext3;
|
||||
sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) -
|
||||
le32_to_cpu(es->s_first_data_block) +
|
||||
EXT3_BLOCKS_PER_GROUP(sb) - 1) /
|
||||
EXT3_BLOCKS_PER_GROUP(sb);
|
||||
sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) -
|
||||
le32_to_cpu(es->s_first_data_block) - 1)
|
||||
/ EXT3_BLOCKS_PER_GROUP(sb)) + 1;
|
||||
db_count = (sbi->s_groups_count + EXT3_DESC_PER_BLOCK(sb) - 1) /
|
||||
EXT3_DESC_PER_BLOCK(sb);
|
||||
sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *),
|
||||
|
|
Loading…
Reference in New Issue