diff options
author | Josef Bacik <jbacik@fusionio.com> | 2012-12-18 09:16:16 -0500 |
---|---|---|
committer | Josef Bacik <jbacik@fusionio.com> | 2013-02-20 09:37:09 -0500 |
commit | c6b305a89b1903d63652691ad5eb9f05aa0326b8 (patch) | |
tree | 2b16ef4fb5c23e64ef0d0092674ebfaee3ac54d2 /fs | |
parent | 2ab28f322f9896782da904f5942f3873432addc8 (diff) |
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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/extent-tree.c | 7 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 1 | ||||
-rw-r--r-- | fs/btrfs/transaction.h | 1 |
3 files changed, 9 insertions, 0 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index d5e60d25ca51..c642fc2cfc2b 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -3570,6 +3570,10 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, | |||
3570 | int wait_for_alloc = 0; | 3570 | int wait_for_alloc = 0; |
3571 | int ret = 0; | 3571 | int ret = 0; |
3572 | 3572 | ||
3573 | /* Don't re-enter if we're already allocating a chunk */ | ||
3574 | if (trans->allocating_chunk) | ||
3575 | return -ENOSPC; | ||
3576 | |||
3573 | space_info = __find_space_info(extent_root->fs_info, flags); | 3577 | space_info = __find_space_info(extent_root->fs_info, flags); |
3574 | if (!space_info) { | 3578 | if (!space_info) { |
3575 | ret = update_space_info(extent_root->fs_info, flags, | 3579 | ret = update_space_info(extent_root->fs_info, flags, |
@@ -3612,6 +3616,8 @@ again: | |||
3612 | goto again; | 3616 | goto again; |
3613 | } | 3617 | } |
3614 | 3618 | ||
3619 | trans->allocating_chunk = true; | ||
3620 | |||
3615 | /* | 3621 | /* |
3616 | * If we have mixed data/metadata chunks we want to make sure we keep | 3622 | * If we have mixed data/metadata chunks we want to make sure we keep |
3617 | * allocating mixed chunks instead of individual chunks. | 3623 | * allocating mixed chunks instead of individual chunks. |
@@ -3638,6 +3644,7 @@ again: | |||
3638 | check_system_chunk(trans, extent_root, flags); | 3644 | check_system_chunk(trans, extent_root, flags); |
3639 | 3645 | ||
3640 | ret = btrfs_alloc_chunk(trans, extent_root, flags); | 3646 | ret = btrfs_alloc_chunk(trans, extent_root, flags); |
3647 | trans->allocating_chunk = false; | ||
3641 | if (ret < 0 && ret != -ENOSPC) | 3648 | if (ret < 0 && ret != -ENOSPC) |
3642 | goto out; | 3649 | goto out; |
3643 | 3650 | ||
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 86bb105b3982..24fde97cba81 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -385,6 +385,7 @@ again: | |||
385 | h->qgroup_reserved = qgroup_reserved; | 385 | h->qgroup_reserved = qgroup_reserved; |
386 | h->delayed_ref_elem.seq = 0; | 386 | h->delayed_ref_elem.seq = 0; |
387 | h->type = type; | 387 | h->type = type; |
388 | h->allocating_chunk = false; | ||
388 | INIT_LIST_HEAD(&h->qgroup_ref_list); | 389 | INIT_LIST_HEAD(&h->qgroup_ref_list); |
389 | INIT_LIST_HEAD(&h->new_bgs); | 390 | INIT_LIST_HEAD(&h->new_bgs); |
390 | 391 | ||
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index 0e8aa1e6c287..69700f7b20ac 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
@@ -68,6 +68,7 @@ struct btrfs_trans_handle { | |||
68 | struct btrfs_block_rsv *orig_rsv; | 68 | struct btrfs_block_rsv *orig_rsv; |
69 | short aborted; | 69 | short aborted; |
70 | short adding_csums; | 70 | short adding_csums; |
71 | bool allocating_chunk; | ||
71 | enum btrfs_trans_type type; | 72 | enum btrfs_trans_type type; |
72 | /* | 73 | /* |
73 | * this root is only needed to validate that the root passed to | 74 | * this root is only needed to validate that the root passed to |