|
@@ -10257,14 +10257,44 @@ out:
|
|
|
}
|
|
|
|
|
|
struct btrfs_trans_handle *
|
|
|
-btrfs_start_trans_remove_block_group(struct btrfs_fs_info *fs_info)
|
|
|
+btrfs_start_trans_remove_block_group(struct btrfs_fs_info *fs_info,
|
|
|
+ const u64 chunk_offset)
|
|
|
{
|
|
|
+ struct extent_map_tree *em_tree = &fs_info->mapping_tree.map_tree;
|
|
|
+ struct extent_map *em;
|
|
|
+ struct map_lookup *map;
|
|
|
+ unsigned int num_items;
|
|
|
+
|
|
|
+ read_lock(&em_tree->lock);
|
|
|
+ em = lookup_extent_mapping(em_tree, chunk_offset, 1);
|
|
|
+ read_unlock(&em_tree->lock);
|
|
|
+ ASSERT(em && em->start == chunk_offset);
|
|
|
+
|
|
|
/*
|
|
|
+ * We need to reserve 3 + N units from the metadata space info in order
|
|
|
+ * to remove a block group (done at btrfs_remove_chunk() and at
|
|
|
+ * btrfs_remove_block_group()), which are used for:
|
|
|
+ *
|
|
|
* 1 unit for adding the free space inode's orphan (located in the tree
|
|
|
* of tree roots).
|
|
|
+ * 1 unit for deleting the block group item (located in the extent
|
|
|
+ * tree).
|
|
|
+ * 1 unit for deleting the free space item (located in tree of tree
|
|
|
+ * roots).
|
|
|
+ * N units for deleting N device extent items corresponding to each
|
|
|
+ * stripe (located in the device tree).
|
|
|
+ *
|
|
|
+ * In order to remove a block group we also need to reserve units in the
|
|
|
+ * system space info in order to update the chunk tree (update one or
|
|
|
+ * more device items and remove one chunk item), but this is done at
|
|
|
+ * btrfs_remove_chunk() through a call to check_system_chunk().
|
|
|
*/
|
|
|
+ map = (struct map_lookup *)em->bdev;
|
|
|
+ num_items = 3 + map->num_stripes;
|
|
|
+ free_extent_map(em);
|
|
|
+
|
|
|
return btrfs_start_transaction_fallback_global_rsv(fs_info->extent_root,
|
|
|
- 1, 1);
|
|
|
+ num_items, 1);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -10333,7 +10363,8 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
|
|
|
* Want to do this before we do anything else so we can recover
|
|
|
* properly if we fail to join the transaction.
|
|
|
*/
|
|
|
- trans = btrfs_start_trans_remove_block_group(fs_info);
|
|
|
+ trans = btrfs_start_trans_remove_block_group(fs_info,
|
|
|
+ block_group->key.objectid);
|
|
|
if (IS_ERR(trans)) {
|
|
|
btrfs_dec_block_group_ro(root, block_group);
|
|
|
ret = PTR_ERR(trans);
|