ext4: fix online resize's handling of a too-small final block group
Avoid growing the file system to an extent so that the last block group is too small to hold all of the metadata that must be stored in the block group. This problem can be triggered with the following reproducer: umount /mnt mke2fs -F -m0 -b 4096 -t ext4 -O resize_inode,^has_journal \ -E resize=1073741824 /tmp/foo.img 128M mount /tmp/foo.img /mnt truncate --size 1708M /tmp/foo.img resize2fs /dev/loop0 295400 umount /mnt e2fsck -fy /tmp/foo.img Reported-by: Torsten Hilbrich <torsten.hilbrich@secunet.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu> Cc: stable@vger.kernel.org
This commit is contained in:
parent
4274f516d4
commit
f0a459dec5
|
@ -1986,6 +1986,26 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure the last group has enough space so that it's
|
||||
* guaranteed to have enough space for all metadata blocks
|
||||
* that it might need to hold. (We might not need to store
|
||||
* the inode table blocks in the last block group, but there
|
||||
* will be cases where this might be needed.)
|
||||
*/
|
||||
if ((ext4_group_first_block_no(sb, n_group) +
|
||||
ext4_group_overhead_blocks(sb, n_group) + 2 +
|
||||
sbi->s_itb_per_group + sbi->s_cluster_ratio) >= n_blocks_count) {
|
||||
n_blocks_count = ext4_group_first_block_no(sb, n_group);
|
||||
n_group--;
|
||||
n_blocks_count_retry = 0;
|
||||
if (resize_inode) {
|
||||
iput(resize_inode);
|
||||
resize_inode = NULL;
|
||||
}
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/* extend the last group */
|
||||
if (n_group == o_group)
|
||||
add = n_blocks_count - o_blocks_count;
|
||||
|
|
Loading…
Reference in New Issue