Btrfs: don't re-enter when allocating a chunk
authorJosef Bacik <jbacik@fusionio.com>
Tue, 18 Dec 2012 14:16:16 +0000 (09:16 -0500)
committerJosef Bacik <jbacik@fusionio.com>
Wed, 20 Feb 2013 14:37:09 +0000 (09:37 -0500)
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>
fs/btrfs/extent-tree.c
fs/btrfs/transaction.c
fs/btrfs/transaction.h

index d5e60d25ca51dc6ba6fd1823fd8219ace4f263b6..c642fc2cfc2b104bf4e2f8117b006d60acedc338 100644 (file)
@@ -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 @@ again:
                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 @@ again:
        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;
 
index 86bb105b39822799477727b9afad9cabc1239d16..24fde97cba81ddc04fd6551e2d50343aea1a436b 100644 (file)
@@ -385,6 +385,7 @@ again:
        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);
 
index 0e8aa1e6c2870274bc4d623e020bb2a668b238f8..69700f7b20ac5192bca2188b602343285b7203d5 100644 (file)
@@ -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