@@ -2190,6 +2190,39 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, u64 bytes_used,
return 0;
}
+/*
+ * This is a function to revert the newly created block group, mostly for error
+ * handling.
+ *
+ * Unlike btrfs_remove_block_group(), since the new block group hasn't
+ * finished creating, it's much easier to remove it.
+ */
+void btrfs_revert_block_group(struct btrfs_trans_handle *trans, u64 bytenr)
+{
+ struct btrfs_block_group *bg;
+
+ bg = btrfs_lookup_block_group(trans->fs_info, bytenr);
+
+ if (!bg)
+ return;
+ trace_btrfs_remove_block_group(bg);
+
+ btrfs_update_space_info(bg, false, NULL);
+ unlink_block_group(bg);
+
+ btrfs_delayed_refs_rsv_release(trans->fs_info, 1);
+ list_del_init(&bg->bg_list);
+
+ del_block_group(bg);
+
+ /* One for the lookup reference */
+ btrfs_put_block_group(bg);
+
+ /* Finally free the last reference */
+ WARN_ON(refcount_read(&bg->refs) != 1);
+ btrfs_put_block_group(bg);
+}
+
/*
* Mark one block group RO, can be called several times for the same block
* group.
@@ -248,6 +248,7 @@ void btrfs_mark_bg_unused(struct btrfs_block_group *bg);
int btrfs_read_block_groups(struct btrfs_fs_info *info);
int btrfs_make_block_group(struct btrfs_trans_handle *trans, u64 bytes_used,
u64 type, u64 chunk_offset, u64 size);
+void btrfs_revert_block_group(struct btrfs_trans_handle *trans, u64 bytenr);
void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans);
int btrfs_inc_block_group_ro(struct btrfs_block_group *cache,
bool do_chunk_alloc);
@@ -278,8 +278,14 @@ void btrfs_update_space_info(struct btrfs_block_group *bg, bool add,
found->full = 0;
btrfs_try_granting_tickets(info, found);
} else {
+ /* We get called for either removing an unused bg, or a newly
+ * created bg.
+ * Use their ro bit to determine which the case is.
+ */
+ bool ro = bg->ro;
+
/* The block group to be removed should be empty */
- WARN_ON(bg->used || !bg->ro);
+ WARN_ON(bg->used);
/* For removal, we need more overflow check */
if (btrfs_test_opt(info, ENOSPC_DEBUG)) {
@@ -288,9 +294,9 @@ void btrfs_update_space_info(struct btrfs_block_group *bg, bool add,
WARN_ON(found->disk_total < bg->length * factor);
}
found->total_bytes -= bg ->length;
- found->bytes_readonly -= bg->length;
found->disk_total -= bg->length * factor;
-
+ if (ro)
+ found->bytes_readonly -= bg->length;
/*
* Also remove the block group from ro list since we're
* delete it from the space info accounting.
This patch introudces a new function, btrfs_revert_block_group(), to revert a newly created but not yet finished block group. This is for error handling where we just called btrfs_make_block_group() but then some error happened. Signed-off-by: Qu Wenruo <wqu@suse.com> --- fs/btrfs/block-group.c | 33 +++++++++++++++++++++++++++++++++ fs/btrfs/block-group.h | 1 + fs/btrfs/space-info.c | 12 +++++++++--- 3 files changed, 43 insertions(+), 3 deletions(-)