diff options
author | Chris Mason <clm@fb.com> | 2016-10-10 16:43:31 -0400 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2016-10-10 16:43:31 -0400 |
commit | 19c4d2f994788a954af1aa7e53b0fdb46fd7925a (patch) | |
tree | 1c2a40e3866668a68b4bfc4ff774295f3f660bc5 | |
parent | 196e02490c934398f894e5cb0ee1ac8ad13ca576 (diff) |
Revert "btrfs: let btrfs_delete_unused_bgs() to clean relocated bgs"
This reverts commit 5d8eb6fe517583f9c6d5b94faf2254a0207a45c9.
When we remove devices, we free the device structures. Delaying
btfs_remove_chunk() ends up hitting a use-after-free on them.
Signed-off-by: Chris Mason <clm@fb.com>
-rw-r--r-- | fs/btrfs/extent-tree.c | 2 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 24 |
2 files changed, 15 insertions, 11 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 11802eaaab54..210c94ac8818 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -10849,7 +10849,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info) | |||
10849 | spin_lock(&block_group->lock); | 10849 | spin_lock(&block_group->lock); |
10850 | if (block_group->reserved || | 10850 | if (block_group->reserved || |
10851 | btrfs_block_group_used(&block_group->item) || | 10851 | btrfs_block_group_used(&block_group->item) || |
10852 | (block_group->ro && !block_group->removed) || | 10852 | block_group->ro || |
10853 | list_is_singular(&block_group->list)) { | 10853 | list_is_singular(&block_group->list)) { |
10854 | /* | 10854 | /* |
10855 | * We want to bail if we made new allocations or have | 10855 | * We want to bail if we made new allocations or have |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index b4048c1b3d9b..71a60cc01451 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -2906,8 +2906,8 @@ out: | |||
2906 | static int btrfs_relocate_chunk(struct btrfs_root *root, u64 chunk_offset) | 2906 | static int btrfs_relocate_chunk(struct btrfs_root *root, u64 chunk_offset) |
2907 | { | 2907 | { |
2908 | struct btrfs_root *extent_root; | 2908 | struct btrfs_root *extent_root; |
2909 | struct btrfs_trans_handle *trans; | ||
2909 | int ret; | 2910 | int ret; |
2910 | struct btrfs_block_group_cache *block_group; | ||
2911 | 2911 | ||
2912 | root = root->fs_info->chunk_root; | 2912 | root = root->fs_info->chunk_root; |
2913 | extent_root = root->fs_info->extent_root; | 2913 | extent_root = root->fs_info->extent_root; |
@@ -2937,17 +2937,21 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, u64 chunk_offset) | |||
2937 | if (ret) | 2937 | if (ret) |
2938 | return ret; | 2938 | return ret; |
2939 | 2939 | ||
2940 | trans = btrfs_start_trans_remove_block_group(root->fs_info, | ||
2941 | chunk_offset); | ||
2942 | if (IS_ERR(trans)) { | ||
2943 | ret = PTR_ERR(trans); | ||
2944 | btrfs_handle_fs_error(root->fs_info, ret, NULL); | ||
2945 | return ret; | ||
2946 | } | ||
2947 | |||
2940 | /* | 2948 | /* |
2941 | * step two, flag the chunk as removed and let | 2949 | * step two, delete the device extents and the |
2942 | * btrfs_delete_unused_bgs() remove it. | 2950 | * chunk tree entries |
2943 | */ | 2951 | */ |
2944 | block_group = btrfs_lookup_block_group(root->fs_info, chunk_offset); | 2952 | ret = btrfs_remove_chunk(trans, root, chunk_offset); |
2945 | spin_lock(&block_group->lock); | 2953 | btrfs_end_transaction(trans, extent_root); |
2946 | block_group->removed = 1; | 2954 | return ret; |
2947 | spin_unlock(&block_group->lock); | ||
2948 | btrfs_put_block_group(block_group); | ||
2949 | |||
2950 | return 0; | ||
2951 | } | 2955 | } |
2952 | 2956 | ||
2953 | static int btrfs_relocate_sys_chunks(struct btrfs_root *root) | 2957 | static int btrfs_relocate_sys_chunks(struct btrfs_root *root) |