| From b4c5d8fdfff3e2b6c4fa4a5043e8946dff500f8c Mon Sep 17 00:00:00 2001 |
| From: Qu Wenruo <wqu@suse.com> |
| Date: Fri, 24 Jul 2020 14:46:09 +0800 |
| Subject: btrfs: qgroup: fix wrong qgroup metadata reserve for delayed inode |
| |
| From: Qu Wenruo <wqu@suse.com> |
| |
| commit b4c5d8fdfff3e2b6c4fa4a5043e8946dff500f8c upstream. |
| |
| For delayed inode facility, qgroup metadata is reserved for it, and |
| later freed. |
| |
| However we're freeing more bytes than we reserved. |
| In btrfs_delayed_inode_reserve_metadata(): |
| |
| num_bytes = btrfs_calc_metadata_size(fs_info, 1); |
| ... |
| ret = btrfs_qgroup_reserve_meta_prealloc(root, |
| fs_info->nodesize, true); |
| ... |
| if (!ret) { |
| node->bytes_reserved = num_bytes; |
| |
| But in btrfs_delayed_inode_release_metadata(): |
| |
| if (qgroup_free) |
| btrfs_qgroup_free_meta_prealloc(node->root, |
| node->bytes_reserved); |
| else |
| btrfs_qgroup_convert_reserved_meta(node->root, |
| node->bytes_reserved); |
| |
| This means, we're always releasing more qgroup metadata rsv than we have |
| reserved. |
| |
| This won't trigger selftest warning, as btrfs qgroup metadata rsv has |
| extra protection against cases like quota enabled half-way. |
| |
| But we still need to fix this problem any way. |
| |
| This patch will use the same num_bytes for qgroup metadata rsv so we |
| could handle it correctly. |
| |
| Fixes: f218ea6c4792 ("btrfs: delayed-inode: Remove wrong qgroup meta reservation calls") |
| CC: stable@vger.kernel.org # 4.19+ |
| Reviewed-by: Josef Bacik <josef@toxicpanda.com> |
| Signed-off-by: Qu Wenruo <wqu@suse.com> |
| Signed-off-by: David Sterba <dsterba@suse.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/btrfs/delayed-inode.c | 3 +-- |
| 1 file changed, 1 insertion(+), 2 deletions(-) |
| |
| --- a/fs/btrfs/delayed-inode.c |
| +++ b/fs/btrfs/delayed-inode.c |
| @@ -627,8 +627,7 @@ static int btrfs_delayed_inode_reserve_m |
| */ |
| if (!src_rsv || (!trans->bytes_reserved && |
| src_rsv->type != BTRFS_BLOCK_RSV_DELALLOC)) { |
| - ret = btrfs_qgroup_reserve_meta_prealloc(root, |
| - fs_info->nodesize, true); |
| + ret = btrfs_qgroup_reserve_meta_prealloc(root, num_bytes, true); |
| if (ret < 0) |
| return ret; |
| ret = btrfs_block_rsv_add(root, dst_rsv, num_bytes, |