From 19c4d2f994788a954af1aa7e53b0fdb46fd7925a Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Mon, 10 Oct 2016 13:43:31 -0700 Subject: 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 --- fs/btrfs/extent-tree.c | 2 +- fs/btrfs/volumes.c | 24 ++++++++++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-) (limited to 'fs/btrfs') 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) spin_lock(&block_group->lock); if (block_group->reserved || btrfs_block_group_used(&block_group->item) || - (block_group->ro && !block_group->removed) || + block_group->ro || list_is_singular(&block_group->list)) { /* * 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: static int btrfs_relocate_chunk(struct btrfs_root *root, u64 chunk_offset) { struct btrfs_root *extent_root; + struct btrfs_trans_handle *trans; int ret; - struct btrfs_block_group_cache *block_group; root = root->fs_info->chunk_root; extent_root = root->fs_info->extent_root; @@ -2937,17 +2937,21 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, u64 chunk_offset) if (ret) return ret; + trans = btrfs_start_trans_remove_block_group(root->fs_info, + chunk_offset); + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); + btrfs_handle_fs_error(root->fs_info, ret, NULL); + return ret; + } + /* - * step two, flag the chunk as removed and let - * btrfs_delete_unused_bgs() remove it. + * step two, delete the device extents and the + * chunk tree entries */ - block_group = btrfs_lookup_block_group(root->fs_info, chunk_offset); - spin_lock(&block_group->lock); - block_group->removed = 1; - spin_unlock(&block_group->lock); - btrfs_put_block_group(block_group); - - return 0; + ret = btrfs_remove_chunk(trans, root, chunk_offset); + btrfs_end_transaction(trans, extent_root); + return ret; } static int btrfs_relocate_sys_chunks(struct btrfs_root *root) -- cgit v1.2.3