]>
Commit | Line | Data |
---|---|---|
d177cad4 GKH |
1 | From 674a2b27234d1b7afcb0a9162e81b2e53aeef217 Mon Sep 17 00:00:00 2001 |
2 | From: "zhangyi (F)" <yi.zhang@huawei.com> | |
3 | Date: Sat, 23 Mar 2019 11:43:05 -0400 | |
4 | Subject: ext4: brelse all indirect buffer in ext4_ind_remove_space() | |
5 | ||
6 | From: zhangyi (F) <yi.zhang@huawei.com> | |
7 | ||
8 | commit 674a2b27234d1b7afcb0a9162e81b2e53aeef217 upstream. | |
9 | ||
10 | All indirect buffers get by ext4_find_shared() should be released no | |
11 | mater the branch should be freed or not. But now, we forget to release | |
12 | the lower depth indirect buffers when removing space from the same | |
13 | higher depth indirect block. It will lead to buffer leak and futher | |
14 | more, it may lead to quota information corruption when using old quota, | |
15 | consider the following case. | |
16 | ||
17 | - Create and mount an empty ext4 filesystem without extent and quota | |
18 | features, | |
19 | - quotacheck and enable the user & group quota, | |
20 | - Create some files and write some data to them, and then punch hole | |
21 | to some files of them, it may trigger the buffer leak problem | |
22 | mentioned above. | |
23 | - Disable quota and run quotacheck again, it will create two new | |
24 | aquota files and write the checked quota information to them, which | |
25 | probably may reuse the freed indirect block(the buffer and page | |
26 | cache was not freed) as data block. | |
27 | - Enable quota again, it will invoke | |
28 | vfs_load_quota_inode()->invalidate_bdev() to try to clean unused | |
29 | buffers and pagecache. Unfortunately, because of the buffer of quota | |
30 | data block is still referenced, quota code cannot read the up to date | |
31 | quota info from the device and lead to quota information corruption. | |
32 | ||
33 | This problem can be reproduced by xfstests generic/231 on ext3 file | |
34 | system or ext4 file system without extent and quota features. | |
35 | ||
36 | This patch fix this problem by releasing the missing indirect buffers, | |
37 | in ext4_ind_remove_space(). | |
38 | ||
39 | Reported-by: Hulk Robot <hulkci@huawei.com> | |
40 | Signed-off-by: zhangyi (F) <yi.zhang@huawei.com> | |
41 | Signed-off-by: Theodore Ts'o <tytso@mit.edu> | |
42 | Reviewed-by: Jan Kara <jack@suse.cz> | |
43 | Cc: stable@kernel.org | |
44 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
45 | ||
46 | --- | |
47 | fs/ext4/indirect.c | 12 ++++++++---- | |
48 | 1 file changed, 8 insertions(+), 4 deletions(-) | |
49 | ||
50 | --- a/fs/ext4/indirect.c | |
51 | +++ b/fs/ext4/indirect.c | |
52 | @@ -1480,10 +1480,14 @@ end_range: | |
53 | partial->p + 1, | |
54 | partial2->p, | |
55 | (chain+n-1) - partial); | |
56 | - BUFFER_TRACE(partial->bh, "call brelse"); | |
57 | - brelse(partial->bh); | |
58 | - BUFFER_TRACE(partial2->bh, "call brelse"); | |
59 | - brelse(partial2->bh); | |
60 | + while (partial > chain) { | |
61 | + BUFFER_TRACE(partial->bh, "call brelse"); | |
62 | + brelse(partial->bh); | |
63 | + } | |
64 | + while (partial2 > chain2) { | |
65 | + BUFFER_TRACE(partial2->bh, "call brelse"); | |
66 | + brelse(partial2->bh); | |
67 | + } | |
68 | return 0; | |
69 | } | |
70 |