summaryrefslogtreecommitdiff
path: root/extent-tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'extent-tree.c')
-rw-r--r--extent-tree.c77
1 files changed, 44 insertions, 33 deletions
diff --git a/extent-tree.c b/extent-tree.c
index 3b5d2b6e..9696aabf 100644
--- a/extent-tree.c
+++ b/extent-tree.c
@@ -989,6 +989,35 @@ static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info,
}
+static int update_space_info(struct btrfs_fs_info *info, u64 flags,
+ u64 total_bytes, u64 bytes_used,
+ struct btrfs_space_info **space_info)
+{
+ struct btrfs_space_info *found;
+
+ found = __find_space_info(info, flags);
+ if (found) {
+ found->total_bytes += total_bytes;
+ found->bytes_used += bytes_used;
+ WARN_ON(found->total_bytes < found->bytes_used);
+ *space_info = found;
+ return 0;
+ }
+ found = kmalloc(sizeof(*found), GFP_NOFS);
+ if (!found)
+ return -ENOMEM;
+
+ list_add(&found->list, &info->space_info);
+ found->flags = flags;
+ found->total_bytes = total_bytes;
+ found->bytes_used = bytes_used;
+ found->bytes_pinned = 0;
+ found->full = 0;
+ *space_info = found;
+ return 0;
+}
+
+
static int do_chunk_alloc(struct btrfs_trans_handle *trans,
struct btrfs_root *extent_root, u64 alloc_bytes,
u64 flags)
@@ -1000,6 +1029,11 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
int ret;
space_info = __find_space_info(extent_root->fs_info, flags);
+ if (!space_info) {
+ ret = update_space_info(extent_root->fs_info, flags,
+ 0, 0, &space_info);
+ BUG_ON(ret);
+ }
BUG_ON(!space_info);
if (space_info->full)
@@ -1579,25 +1613,30 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
struct btrfs_extent_item *extent_item;
struct btrfs_extent_ref *ref;
struct btrfs_key keys[2];
+ int extra_alloc_flags = 0;
+
+ if (btrfs_super_num_devices(&info->super_copy) > 1)
+ extra_alloc_flags = BTRFS_BLOCK_GROUP_RAID0;
if (data) {
- data = BTRFS_BLOCK_GROUP_DATA;
+ data = BTRFS_BLOCK_GROUP_DATA | extra_alloc_flags;
} else if (root == root->fs_info->chunk_root ||
info->force_system_allocs) {
data = BTRFS_BLOCK_GROUP_SYSTEM;
} else {
- data = BTRFS_BLOCK_GROUP_METADATA;
+ data = BTRFS_BLOCK_GROUP_METADATA | extra_alloc_flags;
}
if (root->ref_cows) {
- if (data != BTRFS_BLOCK_GROUP_METADATA) {
+ if (!(data & BTRFS_BLOCK_GROUP_METADATA)) {
ret = do_chunk_alloc(trans, root->fs_info->extent_root,
num_bytes,
- BTRFS_BLOCK_GROUP_METADATA);
+ BTRFS_BLOCK_GROUP_METADATA |
+ extra_alloc_flags);
BUG_ON(ret);
}
ret = do_chunk_alloc(trans, root->fs_info->extent_root,
- num_bytes, data);
+ num_bytes + 2 * 1024 * 1024, data);
BUG_ON(ret);
}
@@ -2143,34 +2182,6 @@ error:
return ret;
}
-static int update_space_info(struct btrfs_fs_info *info, u64 flags,
- u64 total_bytes, u64 bytes_used,
- struct btrfs_space_info **space_info)
-{
- struct btrfs_space_info *found;
-
- found = __find_space_info(info, flags);
- if (found) {
- found->total_bytes += total_bytes;
- found->bytes_used += bytes_used;
- WARN_ON(found->total_bytes < found->bytes_used);
- *space_info = found;
- return 0;
- }
- found = kmalloc(sizeof(*found), GFP_NOFS);
- if (!found)
- return -ENOMEM;
-
- list_add(&found->list, &info->space_info);
- found->flags = flags;
- found->total_bytes = total_bytes;
- found->bytes_used = bytes_used;
- found->bytes_pinned = 0;
- found->full = 0;
- *space_info = found;
- return 0;
-}
-
int btrfs_read_block_groups(struct btrfs_root *root)
{
struct btrfs_path *path;