| From 674a2b27234d1b7afcb0a9162e81b2e53aeef217 Mon Sep 17 00:00:00 2001 |
| From: "zhangyi (F)" <yi.zhang@huawei.com> |
| Date: Sat, 23 Mar 2019 11:43:05 -0400 |
| Subject: ext4: brelse all indirect buffer in ext4_ind_remove_space() |
| |
| From: zhangyi (F) <yi.zhang@huawei.com> |
| |
| commit 674a2b27234d1b7afcb0a9162e81b2e53aeef217 upstream. |
| |
| All indirect buffers get by ext4_find_shared() should be released no |
| mater the branch should be freed or not. But now, we forget to release |
| the lower depth indirect buffers when removing space from the same |
| higher depth indirect block. It will lead to buffer leak and futher |
| more, it may lead to quota information corruption when using old quota, |
| consider the following case. |
| |
| - Create and mount an empty ext4 filesystem without extent and quota |
| features, |
| - quotacheck and enable the user & group quota, |
| - Create some files and write some data to them, and then punch hole |
| to some files of them, it may trigger the buffer leak problem |
| mentioned above. |
| - Disable quota and run quotacheck again, it will create two new |
| aquota files and write the checked quota information to them, which |
| probably may reuse the freed indirect block(the buffer and page |
| cache was not freed) as data block. |
| - Enable quota again, it will invoke |
| vfs_load_quota_inode()->invalidate_bdev() to try to clean unused |
| buffers and pagecache. Unfortunately, because of the buffer of quota |
| data block is still referenced, quota code cannot read the up to date |
| quota info from the device and lead to quota information corruption. |
| |
| This problem can be reproduced by xfstests generic/231 on ext3 file |
| system or ext4 file system without extent and quota features. |
| |
| This patch fix this problem by releasing the missing indirect buffers, |
| in ext4_ind_remove_space(). |
| |
| Reported-by: Hulk Robot <hulkci@huawei.com> |
| Signed-off-by: zhangyi (F) <yi.zhang@huawei.com> |
| Signed-off-by: Theodore Ts'o <tytso@mit.edu> |
| Reviewed-by: Jan Kara <jack@suse.cz> |
| Cc: stable@kernel.org |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/ext4/indirect.c | 12 ++++++++---- |
| 1 file changed, 8 insertions(+), 4 deletions(-) |
| |
| --- a/fs/ext4/indirect.c |
| +++ b/fs/ext4/indirect.c |
| @@ -1385,10 +1385,14 @@ end_range: |
| partial->p + 1, |
| partial2->p, |
| (chain+n-1) - partial); |
| - BUFFER_TRACE(partial->bh, "call brelse"); |
| - brelse(partial->bh); |
| - BUFFER_TRACE(partial2->bh, "call brelse"); |
| - brelse(partial2->bh); |
| + while (partial > chain) { |
| + BUFFER_TRACE(partial->bh, "call brelse"); |
| + brelse(partial->bh); |
| + } |
| + while (partial2 > chain2) { |
| + BUFFER_TRACE(partial2->bh, "call brelse"); |
| + brelse(partial2->bh); |
| + } |
| return 0; |
| } |
| |