aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-03-24 15:01:59 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:01 -0400
commit6324fbf334f4586325057197da7752f4ffa409d3 (patch)
treeaf67d90c3a58f48b91f73ac23f753f4f3907a453
parent0b86a832a1f38abec695864ec2eaedc9d2383f1b (diff)
Btrfs: Dynamic chunk and block group allocation
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/ctree.h12
-rw-r--r--fs/btrfs/disk-io.c2
-rw-r--r--fs/btrfs/extent-tree.c208
-rw-r--r--fs/btrfs/inode.c9
-rw-r--r--fs/btrfs/volumes.c87
-rw-r--r--fs/btrfs/volumes.h2
6 files changed, 263 insertions, 57 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 1453d995fef6..a877105f5c47 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -431,9 +431,19 @@ struct btrfs_block_group_item {
431 __le64 flags; 431 __le64 flags;
432} __attribute__ ((__packed__)); 432} __attribute__ ((__packed__));
433 433
434struct btrfs_space_info {
435 u64 flags;
436 u64 total_bytes;
437 u64 bytes_used;
438 u64 bytes_pinned;
439 int full;
440 struct list_head list;
441};
442
434struct btrfs_block_group_cache { 443struct btrfs_block_group_cache {
435 struct btrfs_key key; 444 struct btrfs_key key;
436 struct btrfs_block_group_item item; 445 struct btrfs_block_group_item item;
446 struct btrfs_space_info *space_info;
437 u64 pinned; 447 u64 pinned;
438 u64 flags; 448 u64 flags;
439 int cached; 449 int cached;
@@ -490,7 +500,7 @@ struct btrfs_fs_info {
490 struct list_head dirty_cowonly_roots; 500 struct list_head dirty_cowonly_roots;
491 501
492 struct list_head devices; 502 struct list_head devices;
493 struct list_head *last_device; 503 struct list_head space_info;
494 spinlock_t delalloc_lock; 504 spinlock_t delalloc_lock;
495 spinlock_t new_trans_lock; 505 spinlock_t new_trans_lock;
496 u64 delalloc_bytes; 506 u64 delalloc_bytes;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 8e37fa120cc8..2a239ae49f78 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -700,8 +700,8 @@ struct btrfs_root *open_ctree(struct super_block *sb)
700 fs_info->dev_root = dev_root; 700 fs_info->dev_root = dev_root;
701 INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots); 701 INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots);
702 INIT_LIST_HEAD(&fs_info->devices); 702 INIT_LIST_HEAD(&fs_info->devices);
703 INIT_LIST_HEAD(&fs_info->space_info);
703 btrfs_mapping_init(&fs_info->mapping_tree); 704 btrfs_mapping_init(&fs_info->mapping_tree);
704 fs_info->last_device = &fs_info->devices;
705 fs_info->sb = sb; 705 fs_info->sb = sb;
706 fs_info->throttles = 0; 706 fs_info->throttles = 0;
707 fs_info->mount_opt = 0; 707 fs_info->mount_opt = 0;
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 2cd957d6e8d8..15082b1087be 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -36,6 +36,10 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
36 btrfs_root *extent_root); 36 btrfs_root *extent_root);
37static int del_pending_extents(struct btrfs_trans_handle *trans, struct 37static int del_pending_extents(struct btrfs_trans_handle *trans, struct
38 btrfs_root *extent_root); 38 btrfs_root *extent_root);
39int btrfs_make_block_group(struct btrfs_trans_handle *trans,
40 struct btrfs_root *root, u64 bytes_used,
41 u64 type, u64 chunk_tree, u64 chunk_objectid,
42 u64 size);
39 43
40 44
41static int cache_block_group(struct btrfs_root *root, 45static int cache_block_group(struct btrfs_root *root,
@@ -168,16 +172,7 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group(struct
168 172
169static int block_group_bits(struct btrfs_block_group_cache *cache, u64 bits) 173static int block_group_bits(struct btrfs_block_group_cache *cache, u64 bits)
170{ 174{
171 if ((bits & BLOCK_GROUP_DATA) && 175 return (cache->flags & bits);
172 (cache->flags & BTRFS_BLOCK_GROUP_DATA))
173 return 1;
174 if ((bits & BLOCK_GROUP_METADATA) &&
175 (cache->flags & BTRFS_BLOCK_GROUP_METADATA))
176 return 1;
177 if ((bits & BLOCK_GROUP_SYSTEM) &&
178 (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM))
179 return 1;
180 return 0;
181} 176}
182 177
183static int noinline find_search_start(struct btrfs_root *root, 178static int noinline find_search_start(struct btrfs_root *root,
@@ -276,6 +271,18 @@ static u64 div_factor(u64 num, int factor)
276 return num; 271 return num;
277} 272}
278 273
274static int block_group_state_bits(u64 flags)
275{
276 int bits = 0;
277 if (flags & BTRFS_BLOCK_GROUP_DATA)
278 bits |= BLOCK_GROUP_DATA;
279 if (flags & BTRFS_BLOCK_GROUP_METADATA)
280 bits |= BLOCK_GROUP_METADATA;
281 if (flags & BTRFS_BLOCK_GROUP_SYSTEM)
282 bits |= BLOCK_GROUP_SYSTEM;
283 return bits;
284}
285
279struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, 286struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
280 struct btrfs_block_group_cache 287 struct btrfs_block_group_cache
281 *hint, u64 search_start, 288 *hint, u64 search_start,
@@ -304,7 +311,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
304 if (!owner) 311 if (!owner)
305 factor = 8; 312 factor = 8;
306 313
307 bit = data; 314 bit = block_group_state_bits(data);
308 315
309 if (search_start && search_start < total_fs_bytes) { 316 if (search_start && search_start < total_fs_bytes) {
310 struct btrfs_block_group_cache *shint; 317 struct btrfs_block_group_cache *shint;
@@ -358,10 +365,15 @@ again:
358 free_check = cache->key.offset; 365 free_check = cache->key.offset;
359 else 366 else
360 free_check = div_factor(cache->key.offset, factor); 367 free_check = div_factor(cache->key.offset, factor);
368
361 if (used + cache->pinned < free_check) { 369 if (used + cache->pinned < free_check) {
362 found_group = cache; 370 found_group = cache;
363 goto found; 371 goto found;
364 } 372 }
373 if (full_search) {
374 printk("failed on cache %Lu used %Lu total %Lu\n",
375 cache->key.objectid, used, cache->key.offset);
376 }
365 cond_resched(); 377 cond_resched();
366 } 378 }
367 if (!full_search) { 379 if (!full_search) {
@@ -983,6 +995,58 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
983 return werr; 995 return werr;
984} 996}
985 997
998static struct btrfs_space_info *__find_space_info(struct btrfs_fs_info *info,
999 u64 flags)
1000{
1001 struct list_head *head = &info->space_info;
1002 struct list_head *cur;
1003 struct btrfs_space_info *found;
1004 list_for_each(cur, head) {
1005 found = list_entry(cur, struct btrfs_space_info, list);
1006 if (found->flags == flags)
1007 return found;
1008 }
1009 return NULL;
1010
1011}
1012
1013static int do_chunk_alloc(struct btrfs_trans_handle *trans,
1014 struct btrfs_root *extent_root, u64 alloc_bytes,
1015 u64 flags)
1016{
1017 struct btrfs_space_info *space_info;
1018 u64 thresh;
1019 u64 start;
1020 u64 num_bytes;
1021 int ret;
1022
1023 space_info = __find_space_info(extent_root->fs_info, flags);
1024 BUG_ON(!space_info);
1025
1026 if (space_info->full)
1027 return 0;
1028
1029 thresh = div_factor(space_info->total_bytes, 7);
1030 if ((space_info->bytes_used + space_info->bytes_pinned + alloc_bytes) <
1031 thresh)
1032 return 0;
1033
1034 ret = btrfs_alloc_chunk(trans, extent_root, &start, &num_bytes, flags);
1035 if (ret == -ENOSPC) {
1036printk("space info full %Lu\n", flags);
1037 space_info->full = 1;
1038 return 0;
1039 }
1040
1041 BUG_ON(ret);
1042
1043 ret = btrfs_make_block_group(trans, extent_root, 0, flags,
1044 extent_root->fs_info->chunk_root->root_key.objectid,
1045 start, num_bytes);
1046 BUG_ON(ret);
1047 return 0;
1048}
1049
986static int update_block_group(struct btrfs_trans_handle *trans, 1050static int update_block_group(struct btrfs_trans_handle *trans,
987 struct btrfs_root *root, 1051 struct btrfs_root *root,
988 u64 bytenr, u64 num_bytes, int alloc, 1052 u64 bytenr, u64 num_bytes, int alloc,
@@ -1012,8 +1076,10 @@ static int update_block_group(struct btrfs_trans_handle *trans,
1012 num_bytes = min(total, cache->key.offset - byte_in_group); 1076 num_bytes = min(total, cache->key.offset - byte_in_group);
1013 if (alloc) { 1077 if (alloc) {
1014 old_val += num_bytes; 1078 old_val += num_bytes;
1079 cache->space_info->bytes_used += num_bytes;
1015 } else { 1080 } else {
1016 old_val -= num_bytes; 1081 old_val -= num_bytes;
1082 cache->space_info->bytes_used -= num_bytes;
1017 if (mark_free) { 1083 if (mark_free) {
1018 set_extent_dirty(&info->free_space_cache, 1084 set_extent_dirty(&info->free_space_cache,
1019 bytenr, bytenr + num_bytes - 1, 1085 bytenr, bytenr + num_bytes - 1,
@@ -1026,6 +1092,7 @@ static int update_block_group(struct btrfs_trans_handle *trans,
1026 } 1092 }
1027 return 0; 1093 return 0;
1028} 1094}
1095
1029static int update_pinned_extents(struct btrfs_root *root, 1096static int update_pinned_extents(struct btrfs_root *root,
1030 u64 bytenr, u64 num, int pin) 1097 u64 bytenr, u64 num, int pin)
1031{ 1098{
@@ -1047,9 +1114,11 @@ static int update_pinned_extents(struct btrfs_root *root,
1047 (bytenr - cache->key.objectid)); 1114 (bytenr - cache->key.objectid));
1048 if (pin) { 1115 if (pin) {
1049 cache->pinned += len; 1116 cache->pinned += len;
1117 cache->space_info->bytes_pinned += len;
1050 fs_info->total_pinned += len; 1118 fs_info->total_pinned += len;
1051 } else { 1119 } else {
1052 cache->pinned -= len; 1120 cache->pinned -= len;
1121 cache->space_info->bytes_pinned -= len;
1053 fs_info->total_pinned -= len; 1122 fs_info->total_pinned -= len;
1054 } 1123 }
1055 bytenr += len; 1124 bytenr += len;
@@ -1472,7 +1541,7 @@ check_failed:
1472 goto new_group; 1541 goto new_group;
1473 } 1542 }
1474 1543
1475 if (!(data & BLOCK_GROUP_DATA)) { 1544 if (!(data & BTRFS_BLOCK_GROUP_DATA)) {
1476 block_group = btrfs_lookup_block_group(info, ins->objectid); 1545 block_group = btrfs_lookup_block_group(info, ins->objectid);
1477 if (block_group) 1546 if (block_group)
1478 trans->block_group = block_group; 1547 trans->block_group = block_group;
@@ -1532,12 +1601,25 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1532 struct btrfs_path *path; 1601 struct btrfs_path *path;
1533 struct btrfs_key keys[2]; 1602 struct btrfs_key keys[2];
1534 1603
1535 if (data) 1604 if (data) {
1536 data = BLOCK_GROUP_DATA; 1605 data = BTRFS_BLOCK_GROUP_DATA;
1537 else if (root == root->fs_info->chunk_root) 1606 } else if (root == root->fs_info->chunk_root) {
1538 data = BLOCK_GROUP_SYSTEM; 1607 data = BTRFS_BLOCK_GROUP_SYSTEM;
1539 else 1608 } else {
1540 data = BLOCK_GROUP_METADATA; 1609 data = BTRFS_BLOCK_GROUP_METADATA;
1610 }
1611
1612 if (root->ref_cows) {
1613 if (data != BTRFS_BLOCK_GROUP_METADATA) {
1614 ret = do_chunk_alloc(trans, root->fs_info->extent_root,
1615 num_bytes,
1616 BTRFS_BLOCK_GROUP_METADATA);
1617 BUG_ON(ret);
1618 }
1619 ret = do_chunk_alloc(trans, root->fs_info->extent_root,
1620 num_bytes, data);
1621 BUG_ON(ret);
1622 }
1541 1623
1542 new_hint = max(hint_byte, root->fs_info->alloc_start); 1624 new_hint = max(hint_byte, root->fs_info->alloc_start);
1543 if (new_hint < btrfs_super_total_bytes(&info->super_copy)) 1625 if (new_hint < btrfs_super_total_bytes(&info->super_copy))
@@ -2490,6 +2572,34 @@ error:
2490 return ret; 2572 return ret;
2491} 2573}
2492 2574
2575static int update_space_info(struct btrfs_fs_info *info, u64 flags,
2576 u64 total_bytes, u64 bytes_used,
2577 struct btrfs_space_info **space_info)
2578{
2579 struct btrfs_space_info *found;
2580
2581 found = __find_space_info(info, flags);
2582 if (found) {
2583 found->total_bytes += total_bytes;
2584 found->bytes_used += bytes_used;
2585 WARN_ON(found->total_bytes < found->bytes_used);
2586 *space_info = found;
2587 return 0;
2588 }
2589 found = kmalloc(sizeof(*found), GFP_NOFS);
2590 if (!found)
2591 return -ENOMEM;
2592
2593 list_add(&found->list, &info->space_info);
2594 found->flags = flags;
2595 found->total_bytes = total_bytes;
2596 found->bytes_used = bytes_used;
2597 found->bytes_pinned = 0;
2598 found->full = 0;
2599 *space_info = found;
2600 return 0;
2601}
2602
2493int btrfs_read_block_groups(struct btrfs_root *root) 2603int btrfs_read_block_groups(struct btrfs_root *root)
2494{ 2604{
2495 struct btrfs_path *path; 2605 struct btrfs_path *path;
@@ -2497,6 +2607,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
2497 int bit; 2607 int bit;
2498 struct btrfs_block_group_cache *cache; 2608 struct btrfs_block_group_cache *cache;
2499 struct btrfs_fs_info *info = root->fs_info; 2609 struct btrfs_fs_info *info = root->fs_info;
2610 struct btrfs_space_info *space_info;
2500 struct extent_io_tree *block_group_cache; 2611 struct extent_io_tree *block_group_cache;
2501 struct btrfs_key key; 2612 struct btrfs_key key;
2502 struct btrfs_key found_key; 2613 struct btrfs_key found_key;
@@ -2547,6 +2658,12 @@ int btrfs_read_block_groups(struct btrfs_root *root)
2547 bit = BLOCK_GROUP_METADATA; 2658 bit = BLOCK_GROUP_METADATA;
2548 } 2659 }
2549 2660
2661 ret = update_space_info(info, cache->flags, found_key.offset,
2662 btrfs_block_group_used(&cache->item),
2663 &space_info);
2664 BUG_ON(ret);
2665 cache->space_info = space_info;
2666
2550 /* use EXTENT_LOCKED to prevent merging */ 2667 /* use EXTENT_LOCKED to prevent merging */
2551 set_extent_bits(block_group_cache, found_key.objectid, 2668 set_extent_bits(block_group_cache, found_key.objectid,
2552 found_key.objectid + found_key.offset - 1, 2669 found_key.objectid + found_key.offset - 1,
@@ -2563,3 +2680,58 @@ error:
2563 btrfs_free_path(path); 2680 btrfs_free_path(path);
2564 return ret; 2681 return ret;
2565} 2682}
2683
2684int btrfs_make_block_group(struct btrfs_trans_handle *trans,
2685 struct btrfs_root *root, u64 bytes_used,
2686 u64 type, u64 chunk_tree, u64 chunk_objectid,
2687 u64 size)
2688{
2689 int ret;
2690 int bit = 0;
2691 struct btrfs_root *extent_root;
2692 struct btrfs_block_group_cache *cache;
2693 struct extent_io_tree *block_group_cache;
2694
2695 extent_root = root->fs_info->extent_root;
2696 block_group_cache = &root->fs_info->block_group_cache;
2697
2698 cache = kmalloc(sizeof(*cache), GFP_NOFS);
2699 BUG_ON(!cache);
2700 cache->key.objectid = chunk_objectid;
2701 cache->key.offset = size;
2702 cache->cached = 0;
2703 cache->pinned = 0;
2704 btrfs_set_key_type(&cache->key, BTRFS_BLOCK_GROUP_ITEM_KEY);
2705 memset(&cache->item, 0, sizeof(cache->item));
2706 btrfs_set_block_group_used(&cache->item, bytes_used);
2707 btrfs_set_block_group_chunk_tree(&cache->item, chunk_tree);
2708 btrfs_set_block_group_chunk_objectid(&cache->item, chunk_objectid);
2709 cache->flags = type;
2710 btrfs_set_block_group_flags(&cache->item, type);
2711
2712 ret = update_space_info(root->fs_info, cache->flags, size, bytes_used,
2713 &cache->space_info);
2714 BUG_ON(ret);
2715
2716 if (type & BTRFS_BLOCK_GROUP_DATA) {
2717 bit = BLOCK_GROUP_DATA;
2718 } else if (type & BTRFS_BLOCK_GROUP_SYSTEM) {
2719 bit = BLOCK_GROUP_SYSTEM;
2720 } else if (type & BTRFS_BLOCK_GROUP_METADATA) {
2721 bit = BLOCK_GROUP_METADATA;
2722 }
2723 set_extent_bits(block_group_cache, chunk_objectid,
2724 chunk_objectid + size - 1,
2725 bit | EXTENT_LOCKED, GFP_NOFS);
2726 set_state_private(block_group_cache, chunk_objectid,
2727 (unsigned long)cache);
2728
2729 ret = btrfs_insert_item(trans, extent_root, &cache->key, &cache->item,
2730 sizeof(cache->item));
2731 BUG_ON(ret);
2732
2733 finish_current_insert(trans, extent_root);
2734 ret = del_pending_extents(trans, extent_root);
2735 BUG_ON(ret);
2736 return 0;
2737}
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 17063cd2cb73..109576b57f69 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1527,6 +1527,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
1527{ 1527{
1528 struct inode *inode; 1528 struct inode *inode;
1529 struct btrfs_inode_item *inode_item; 1529 struct btrfs_inode_item *inode_item;
1530 struct btrfs_block_group_cache *new_inode_group;
1530 struct btrfs_key *location; 1531 struct btrfs_key *location;
1531 struct btrfs_path *path; 1532 struct btrfs_path *path;
1532 struct btrfs_inode_ref *ref; 1533 struct btrfs_inode_ref *ref;
@@ -1553,9 +1554,13 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
1553 owner = 0; 1554 owner = 0;
1554 else 1555 else
1555 owner = 1; 1556 owner = 1;
1556 group = btrfs_find_block_group(root, group, 0, 1557 new_inode_group = btrfs_find_block_group(root, group, 0,
1557 BTRFS_BLOCK_GROUP_METADATA, owner); 1558 BTRFS_BLOCK_GROUP_METADATA, owner);
1558 BTRFS_I(inode)->block_group = group; 1559 if (!new_inode_group) {
1560 printk("find_block group failed\n");
1561 new_inode_group = group;
1562 }
1563 BTRFS_I(inode)->block_group = new_inode_group;
1559 BTRFS_I(inode)->flags = 0; 1564 BTRFS_I(inode)->flags = 0;
1560 1565
1561 key[0].objectid = objectid; 1566 key[0].objectid = objectid;
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 90a8d45dc6d7..a52a13f365d6 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -131,7 +131,7 @@ check_pending:
131 btrfs_release_path(root, path); 131 btrfs_release_path(root, path);
132 BUG_ON(*start < search_start); 132 BUG_ON(*start < search_start);
133 133
134 if (*start + num_bytes >= search_end) { 134 if (*start + num_bytes > search_end) {
135 ret = -ENOSPC; 135 ret = -ENOSPC;
136 goto error; 136 goto error;
137 } 137 }
@@ -159,8 +159,9 @@ int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
159 return -ENOMEM; 159 return -ENOMEM;
160 160
161 ret = find_free_dev_extent(trans, device, path, num_bytes, start); 161 ret = find_free_dev_extent(trans, device, path, num_bytes, start);
162 if (ret) 162 if (ret) {
163 goto err; 163 goto err;
164 }
164 165
165 key.objectid = device->devid; 166 key.objectid = device->devid;
166 key.offset = *start; 167 key.offset = *start;
@@ -214,22 +215,6 @@ error:
214 return ret; 215 return ret;
215} 216}
216 217
217static struct btrfs_device *next_device(struct list_head *head,
218 struct list_head *last)
219{
220 struct list_head *next = last->next;
221 struct btrfs_device *dev;
222
223 if (list_empty(head))
224 return NULL;
225
226 if (next == head)
227 next = next->next;
228
229 dev = list_entry(next, struct btrfs_device, dev_list);
230 return dev;
231}
232
233static int find_next_devid(struct btrfs_root *root, struct btrfs_path *path, 218static int find_next_devid(struct btrfs_root *root, struct btrfs_path *path,
234 u64 *objectid) 219 u64 *objectid)
235{ 220{
@@ -397,31 +382,63 @@ int btrfs_add_system_chunk(struct btrfs_trans_handle *trans,
397 382
398int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, 383int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
399 struct btrfs_root *extent_root, u64 *start, 384 struct btrfs_root *extent_root, u64 *start,
400 u64 *num_bytes, u32 type) 385 u64 *num_bytes, u64 type)
401{ 386{
402 u64 dev_offset; 387 u64 dev_offset;
403 struct btrfs_root *chunk_root = extent_root->fs_info->chunk_root; 388 struct btrfs_root *chunk_root = extent_root->fs_info->chunk_root;
404 struct btrfs_stripe *stripes; 389 struct btrfs_stripe *stripes;
405 struct btrfs_device *device = NULL; 390 struct btrfs_device *device = NULL;
406 struct btrfs_chunk *chunk; 391 struct btrfs_chunk *chunk;
392 struct list_head private_devs;
407 struct list_head *dev_list = &extent_root->fs_info->devices; 393 struct list_head *dev_list = &extent_root->fs_info->devices;
408 struct list_head *last_dev = extent_root->fs_info->last_device; 394 struct list_head *cur;
409 struct extent_map_tree *em_tree; 395 struct extent_map_tree *em_tree;
410 struct map_lookup *map; 396 struct map_lookup *map;
411 struct extent_map *em; 397 struct extent_map *em;
412 u64 physical; 398 u64 physical;
413 u64 calc_size = 1024 * 1024 * 1024; 399 u64 calc_size = 1024 * 1024 * 1024;
414 int num_stripes; 400 u64 avail;
401 u64 max_avail = 0;
402 int num_stripes = 1;
403 int looped = 0;
415 int ret; 404 int ret;
416 int index = 0; 405 int index;
417 struct btrfs_key key; 406 struct btrfs_key key;
418 407
408 if (list_empty(dev_list))
409 return -ENOSPC;
410again:
411 INIT_LIST_HEAD(&private_devs);
412 cur = dev_list->next;
413 index = 0;
414 /* build a private list of devices we will allocate from */
415 while(index < num_stripes) {
416 device = list_entry(cur, struct btrfs_device, dev_list);
417 avail = device->total_bytes - device->bytes_used;
418 cur = cur->next;
419 if (avail > max_avail)
420 max_avail = avail;
421 if (avail >= calc_size) {
422 list_move_tail(&device->dev_list, &private_devs);
423 index++;
424 }
425 if (cur == dev_list)
426 break;
427 }
428 if (index < num_stripes) {
429 list_splice(&private_devs, dev_list);
430 if (!looped && max_avail > 0) {
431 looped = 1;
432 calc_size = max_avail;
433 goto again;
434 }
435 return -ENOSPC;
436 }
419 437
420 ret = find_next_chunk(chunk_root, &key.objectid); 438 ret = find_next_chunk(chunk_root, &key.objectid);
421 if (ret) 439 if (ret)
422 return ret; 440 return ret;
423 441
424 num_stripes = 1;
425 chunk = kmalloc(btrfs_chunk_item_size(num_stripes), GFP_NOFS); 442 chunk = kmalloc(btrfs_chunk_item_size(num_stripes), GFP_NOFS);
426 if (!chunk) 443 if (!chunk)
427 return -ENOMEM; 444 return -ENOMEM;
@@ -429,11 +446,12 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
429 stripes = &chunk->stripe; 446 stripes = &chunk->stripe;
430 447
431 *num_bytes = calc_size; 448 *num_bytes = calc_size;
449 index = 0;
432 while(index < num_stripes) { 450 while(index < num_stripes) {
433 device = next_device(dev_list, last_dev); 451 BUG_ON(list_empty(&private_devs));
434 BUG_ON(!device); 452 cur = private_devs.next;
435 last_dev = &device->dev_list; 453 device = list_entry(cur, struct btrfs_device, dev_list);
436 extent_root->fs_info->last_device = last_dev; 454 list_move_tail(&device->dev_list, dev_list);
437 455
438 ret = btrfs_alloc_dev_extent(trans, device, 456 ret = btrfs_alloc_dev_extent(trans, device,
439 key.objectid, 457 key.objectid,
@@ -449,6 +467,7 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
449 physical = dev_offset; 467 physical = dev_offset;
450 index++; 468 index++;
451 } 469 }
470 BUG_ON(!list_empty(&private_devs));
452 471
453 /* key.objectid was set above */ 472 /* key.objectid was set above */
454 key.offset = *num_bytes; 473 key.offset = *num_bytes;
@@ -692,17 +711,17 @@ static int read_one_dev(struct btrfs_root *root, struct btrfs_key *key,
692 int ret; 711 int ret;
693 712
694 devid = btrfs_device_id(leaf, dev_item); 713 devid = btrfs_device_id(leaf, dev_item);
695 if (btrfs_find_device(root, devid)) 714 device = btrfs_find_device(root, devid);
696 return 0; 715 if (!device) {
697 716 device = kmalloc(sizeof(*device), GFP_NOFS);
698 device = kmalloc(sizeof(*device), GFP_NOFS); 717 if (!device)
699 if (!device) 718 return -ENOMEM;
700 return -ENOMEM; 719 list_add(&device->dev_list, &root->fs_info->devices);
720 }
701 721
702 fill_device_from_item(leaf, dev_item, device); 722 fill_device_from_item(leaf, dev_item, device);
703 device->dev_root = root->fs_info->dev_root; 723 device->dev_root = root->fs_info->dev_root;
704 device->bdev = root->fs_info->sb->s_bdev; 724 device->bdev = root->fs_info->sb->s_bdev;
705 list_add(&device->dev_list, &root->fs_info->devices);
706 memcpy(&device->dev_key, key, sizeof(*key)); 725 memcpy(&device->dev_key, key, sizeof(*key));
707 ret = 0; 726 ret = 0;
708#if 0 727#if 0
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 4a47dcb00a73..4ab9891878a8 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -71,7 +71,7 @@ int btrfs_read_sys_array(struct btrfs_root *root);
71int btrfs_read_chunk_tree(struct btrfs_root *root); 71int btrfs_read_chunk_tree(struct btrfs_root *root);
72int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, 72int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
73 struct btrfs_root *extent_root, u64 *start, 73 struct btrfs_root *extent_root, u64 *start,
74 u64 *num_bytes, u32 type); 74 u64 *num_bytes, u64 type);
75void btrfs_mapping_init(struct btrfs_mapping_tree *tree); 75void btrfs_mapping_init(struct btrfs_mapping_tree *tree);
76void btrfs_mapping_tree_free(struct btrfs_mapping_tree *tree); 76void btrfs_mapping_tree_free(struct btrfs_mapping_tree *tree);
77int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio); 77int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio);