Commit c6b305a8 authored by Josef Bacik's avatar Josef Bacik

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: default avatarJosef Bacik <jbacik@fusionio.com>
parent 2ab28f32
...@@ -3570,6 +3570,10 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, ...@@ -3570,6 +3570,10 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
int wait_for_alloc = 0; int wait_for_alloc = 0;
int ret = 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); space_info = __find_space_info(extent_root->fs_info, flags);
if (!space_info) { if (!space_info) {
ret = update_space_info(extent_root->fs_info, flags, ret = update_space_info(extent_root->fs_info, flags,
...@@ -3612,6 +3616,8 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, ...@@ -3612,6 +3616,8 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
goto again; goto again;
} }
trans->allocating_chunk = true;
/* /*
* If we have mixed data/metadata chunks we want to make sure we keep * If we have mixed data/metadata chunks we want to make sure we keep
* allocating mixed chunks instead of individual chunks. * allocating mixed chunks instead of individual chunks.
...@@ -3638,6 +3644,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, ...@@ -3638,6 +3644,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
check_system_chunk(trans, extent_root, flags); check_system_chunk(trans, extent_root, flags);
ret = btrfs_alloc_chunk(trans, extent_root, flags); ret = btrfs_alloc_chunk(trans, extent_root, flags);
trans->allocating_chunk = false;
if (ret < 0 && ret != -ENOSPC) if (ret < 0 && ret != -ENOSPC)
goto out; goto out;
......
...@@ -385,6 +385,7 @@ start_transaction(struct btrfs_root *root, u64 num_items, int type, ...@@ -385,6 +385,7 @@ start_transaction(struct btrfs_root *root, u64 num_items, int type,
h->qgroup_reserved = qgroup_reserved; h->qgroup_reserved = qgroup_reserved;
h->delayed_ref_elem.seq = 0; h->delayed_ref_elem.seq = 0;
h->type = type; h->type = type;
h->allocating_chunk = false;
INIT_LIST_HEAD(&h->qgroup_ref_list); INIT_LIST_HEAD(&h->qgroup_ref_list);
INIT_LIST_HEAD(&h->new_bgs); INIT_LIST_HEAD(&h->new_bgs);
......
...@@ -68,6 +68,7 @@ struct btrfs_trans_handle { ...@@ -68,6 +68,7 @@ struct btrfs_trans_handle {
struct btrfs_block_rsv *orig_rsv; struct btrfs_block_rsv *orig_rsv;
short aborted; short aborted;
short adding_csums; short adding_csums;
bool allocating_chunk;
enum btrfs_trans_type type; enum btrfs_trans_type type;
/* /*
* this root is only needed to validate that the root passed to * this root is only needed to validate that the root passed to
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment