| From c221171b4a470dbc9a8cf2ce35068a52392081df Mon Sep 17 00:00:00 2001 |
| From: Josef Bacik <josef@toxicpanda.com> |
| Date: Tue, 21 Jan 2020 09:17:06 -0500 |
| Subject: [PATCH] btrfs: free block groups after free'ing fs trees |
| |
| commit 4e19443da1941050b346f8fc4c368aa68413bc88 upstream. |
| |
| 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: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c |
| index 3feddd97e0c5..c7b06fd00fb4 100644 |
| --- a/fs/btrfs/disk-io.c |
| +++ b/fs/btrfs/disk-io.c |
| @@ -4034,11 +4034,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.7.4 |
| |