]>
Commit | Line | Data |
---|---|---|
9d09275e GKH |
1 | From f0a459dec5495a3580f8d784555e6f8f3bf7f263 Mon Sep 17 00:00:00 2001 |
2 | From: Theodore Ts'o <tytso@mit.edu> | |
3 | Date: Mon, 3 Sep 2018 22:19:43 -0400 | |
4 | Subject: ext4: fix online resize's handling of a too-small final block group | |
5 | ||
6 | From: Theodore Ts'o <tytso@mit.edu> | |
7 | ||
8 | commit f0a459dec5495a3580f8d784555e6f8f3bf7f263 upstream. | |
9 | ||
10 | Avoid growing the file system to an extent so that the last block | |
11 | group is too small to hold all of the metadata that must be stored in | |
12 | the block group. | |
13 | ||
14 | This problem can be triggered with the following reproducer: | |
15 | ||
16 | umount /mnt | |
17 | mke2fs -F -m0 -b 4096 -t ext4 -O resize_inode,^has_journal \ | |
18 | -E resize=1073741824 /tmp/foo.img 128M | |
19 | mount /tmp/foo.img /mnt | |
20 | truncate --size 1708M /tmp/foo.img | |
21 | resize2fs /dev/loop0 295400 | |
22 | umount /mnt | |
23 | e2fsck -fy /tmp/foo.img | |
24 | ||
25 | Reported-by: Torsten Hilbrich <torsten.hilbrich@secunet.com> | |
26 | Signed-off-by: Theodore Ts'o <tytso@mit.edu> | |
27 | Cc: stable@vger.kernel.org | |
28 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
29 | ||
30 | --- | |
31 | fs/ext4/resize.c | 20 ++++++++++++++++++++ | |
32 | 1 file changed, 20 insertions(+) | |
33 | ||
34 | --- a/fs/ext4/resize.c | |
35 | +++ b/fs/ext4/resize.c | |
36 | @@ -1986,6 +1986,26 @@ retry: | |
37 | } | |
38 | } | |
39 | ||
40 | + /* | |
41 | + * Make sure the last group has enough space so that it's | |
42 | + * guaranteed to have enough space for all metadata blocks | |
43 | + * that it might need to hold. (We might not need to store | |
44 | + * the inode table blocks in the last block group, but there | |
45 | + * will be cases where this might be needed.) | |
46 | + */ | |
47 | + if ((ext4_group_first_block_no(sb, n_group) + | |
48 | + ext4_group_overhead_blocks(sb, n_group) + 2 + | |
49 | + sbi->s_itb_per_group + sbi->s_cluster_ratio) >= n_blocks_count) { | |
50 | + n_blocks_count = ext4_group_first_block_no(sb, n_group); | |
51 | + n_group--; | |
52 | + n_blocks_count_retry = 0; | |
53 | + if (resize_inode) { | |
54 | + iput(resize_inode); | |
55 | + resize_inode = NULL; | |
56 | + } | |
57 | + goto retry; | |
58 | + } | |
59 | + | |
60 | /* extend the last group */ | |
61 | if (n_group == o_group) | |
62 | add = n_blocks_count - o_blocks_count; |