| From c0ff51f97e8a0af5c9b27a0a54496f2a372da6ca Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 21 Jan 2020 09:17:06 -0500 |
| Subject: btrfs: free block groups after free'ing fs trees |
| |
| From: Josef Bacik <josef@toxicpanda.com> |
| |
| [ Upstream commit 4e19443da1941050b346f8fc4c368aa68413bc88 ] |
| |
| Sometimes when running generic/475 we would trip the |
| WARN_ON(cache->reserved) check when free'ing the block groups on umount. |
| This is because sometimes we don't commit the transaction because of IO |
| errors and thus do not cleanup the tree logs until at umount time. |
| |
| These blocks are still reserved until they are cleaned up, but they |
| aren't cleaned up until _after_ we do the free block groups work. Fix |
| this by moving the free after free'ing the fs roots, that way all of the |
| tree logs are cleaned up and we have a properly cleaned fs. A bunch of |
| loops of generic/475 confirmed this fixes the problem. |
| |
| CC: stable@vger.kernel.org # 4.9+ |
| Signed-off-by: Josef Bacik <josef@toxicpanda.com> |
| Reviewed-by: David Sterba <dsterba@suse.com> |
| Signed-off-by: David Sterba <dsterba@suse.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| fs/btrfs/disk-io.c | 11 +++++++++-- |
| 1 file changed, 9 insertions(+), 2 deletions(-) |
| |
| diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c |
| index d296ea329bd4e..9e467e8a8cb5d 100644 |
| --- a/fs/btrfs/disk-io.c |
| +++ b/fs/btrfs/disk-io.c |
| @@ -3983,11 +3983,18 @@ void close_ctree(struct btrfs_fs_info *fs_info) |
| invalidate_inode_pages2(fs_info->btree_inode->i_mapping); |
| btrfs_stop_all_workers(fs_info); |
| |
| - btrfs_free_block_groups(fs_info); |
| - |
| clear_bit(BTRFS_FS_OPEN, &fs_info->flags); |
| free_root_pointers(fs_info, true); |
| |
| + /* |
| + * We must free the block groups after dropping the fs_roots as we could |
| + * have had an IO error and have left over tree log blocks that aren't |
| + * cleaned up until the fs roots are freed. This makes the block group |
| + * accounting appear to be wrong because there's pending reserved bytes, |
| + * so make sure we do the block group cleanup afterwards. |
| + */ |
| + btrfs_free_block_groups(fs_info); |
| + |
| iput(fs_info->btree_inode); |
| |
| #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY |
| -- |
| 2.20.1 |
| |