Btrfs: don't re-enter when allocating a chunk
If we start running low on metadata space we will try to allocate a chunk, which could then try to allocate a chunk to add the device entry. The thing is we allocate a chunk before we try really hard to make the allocation, so we should be able to find space for the device entry. Add a flag to the trans handle so we know we're currently allocating a chunk so we can just bail out if we try to allocate another chunk. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
This commit is contained in:
parent
2ab28f322f
commit
c6b305a89b
3 changed files with 9 additions and 0 deletions
|
@ -3570,6 +3570,10 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
|
|||
int wait_for_alloc = 0;
|
||||
int ret = 0;
|
||||
|
||||
/* Don't re-enter if we're already allocating a chunk */
|
||||
if (trans->allocating_chunk)
|
||||
return -ENOSPC;
|
||||
|
||||
space_info = __find_space_info(extent_root->fs_info, flags);
|
||||
if (!space_info) {
|
||||
ret = update_space_info(extent_root->fs_info, flags,
|
||||
|
@ -3612,6 +3616,8 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
|
|||
goto again;
|
||||
}
|
||||
|
||||
trans->allocating_chunk = true;
|
||||
|
||||
/*
|
||||
* If we have mixed data/metadata chunks we want to make sure we keep
|
||||
* allocating mixed chunks instead of individual chunks.
|
||||
|
@ -3638,6 +3644,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
|
|||
check_system_chunk(trans, extent_root, flags);
|
||||
|
||||
ret = btrfs_alloc_chunk(trans, extent_root, flags);
|
||||
trans->allocating_chunk = false;
|
||||
if (ret < 0 && ret != -ENOSPC)
|
||||
goto out;
|
||||
|
||||
|
|
|
@ -385,6 +385,7 @@ start_transaction(struct btrfs_root *root, u64 num_items, int type,
|
|||
h->qgroup_reserved = qgroup_reserved;
|
||||
h->delayed_ref_elem.seq = 0;
|
||||
h->type = type;
|
||||
h->allocating_chunk = false;
|
||||
INIT_LIST_HEAD(&h->qgroup_ref_list);
|
||||
INIT_LIST_HEAD(&h->new_bgs);
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ struct btrfs_trans_handle {
|
|||
struct btrfs_block_rsv *orig_rsv;
|
||||
short aborted;
|
||||
short adding_csums;
|
||||
bool allocating_chunk;
|
||||
enum btrfs_trans_type type;
|
||||
/*
|
||||
* this root is only needed to validate that the root passed to
|
||||
|
|
Loading…
Reference in a new issue