aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-05-06 10:15:01 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-05-06 10:15:01 -0400
commitbe74417553f4b2ee46be2088007a674ef2f02330 (patch)
treef3c3e0f3d15b2c638699f3c8305a090c88e16c8b /fs/btrfs/extent-tree.c
parentbe08c1b9f8e679d45e086728445ac36cf250e92e (diff)
Btrfs: more allocator enhancements
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c317
1 files changed, 238 insertions, 79 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index c5ae51893f78..2937fd9aba74 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -12,36 +12,88 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
12static int del_pending_extents(struct btrfs_trans_handle *trans, struct 12static int del_pending_extents(struct btrfs_trans_handle *trans, struct
13 btrfs_root *extent_root); 13 btrfs_root *extent_root);
14 14
15static struct btrfs_block_group_cache *lookup_block_group(struct
16 btrfs_fs_info *info,
17 u64 blocknr)
18{
19 struct btrfs_block_group_cache *block_group;
20 int ret;
21
22 ret = radix_tree_gang_lookup(&info->block_group_radix,
23 (void **)&block_group,
24 blocknr, 1);
25 if (ret) {
26 if (block_group->key.objectid <= blocknr && blocknr <
27 block_group->key.objectid + block_group->key.offset)
28 return block_group;
29 }
30 ret = radix_tree_gang_lookup(&info->block_group_data_radix,
31 (void **)&block_group,
32 blocknr, 1);
33 if (ret) {
34 if (block_group->key.objectid <= blocknr && blocknr <
35 block_group->key.objectid + block_group->key.offset)
36 return block_group;
37 }
38printk("lookup_block_group fails for blocknr %Lu\n", blocknr);
39 return NULL;
40}
41
15struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, 42struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
16 struct btrfs_block_group_cache 43 struct btrfs_block_group_cache
17 *hint, int data) 44 *hint, u64 search_start,
45 int data)
18{ 46{
19 struct btrfs_block_group_cache *cache[8]; 47 struct btrfs_block_group_cache *cache[8];
20 struct btrfs_block_group_cache *found_group = NULL; 48 struct btrfs_block_group_cache *found_group = NULL;
21 struct btrfs_fs_info *info = root->fs_info; 49 struct btrfs_fs_info *info = root->fs_info;
50 struct radix_tree_root *radix;
22 u64 used; 51 u64 used;
23 u64 last = 0; 52 u64 last = 0;
24 u64 hint_last; 53 u64 hint_last;
25 int i; 54 int i;
26 int ret; 55 int ret;
27 int full_search = 0; 56 int full_search = 0;
28 if (!data && hint) { 57
58 if (data)
59 radix = &info->block_group_data_radix;
60 else
61 radix = &info->block_group_radix;
62
63 if (search_start) {
64 struct btrfs_block_group_cache *shint;
65 shint = lookup_block_group(info, search_start);
66 if (shint->data == data) {
67 used = btrfs_block_group_used(&shint->item);
68 if (used + shint->pinned <
69 (shint->key.offset * 8) / 10) {
70 return shint;
71 }
72 }
73 }
74 if (hint && hint->data == data) {
29 used = btrfs_block_group_used(&hint->item); 75 used = btrfs_block_group_used(&hint->item);
30 if (used < (hint->key.offset * 2) / 3) { 76 if (used + hint->pinned < (hint->key.offset * 8) / 10) {
31 return hint; 77 return hint;
32 } 78 }
33 radix_tree_tag_clear(&info->block_group_radix, 79 if (used >= (hint->key.offset * 8) / 10) {
34 hint->key.objectid + hint->key.offset - 1, 80 radix_tree_tag_clear(radix,
35 BTRFS_BLOCK_GROUP_AVAIL); 81 hint->key.objectid +
36 last = hint->key.objectid + hint->key.offset; 82 hint->key.offset - 1,
83 BTRFS_BLOCK_GROUP_AVAIL);
84 }
85 last = hint->key.offset * 2;
86 if (hint->key.objectid >= last)
87 last = max(search_start, hint->key.objectid - last);
88 else
89 last = hint->key.objectid + hint->key.offset;
37 hint_last = last; 90 hint_last = last;
38 } else { 91 } else {
39 hint_last = 0; 92 hint_last = search_start;
40 last = 0; 93 last = search_start;
41 } 94 }
42 while(1) { 95 while(1) {
43 ret = radix_tree_gang_lookup_tag(&info->block_group_radix, 96 ret = radix_tree_gang_lookup_tag(radix, (void **)cache,
44 (void **)cache,
45 last, ARRAY_SIZE(cache), 97 last, ARRAY_SIZE(cache),
46 BTRFS_BLOCK_GROUP_AVAIL); 98 BTRFS_BLOCK_GROUP_AVAIL);
47 if (!ret) 99 if (!ret)
@@ -49,65 +101,54 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
49 for (i = 0; i < ret; i++) { 101 for (i = 0; i < ret; i++) {
50 last = cache[i]->key.objectid + 102 last = cache[i]->key.objectid +
51 cache[i]->key.offset; 103 cache[i]->key.offset;
52 if (!full_search && !data &&
53 (cache[i]->key.objectid & cache[i]->key.offset))
54 continue;
55 if (!full_search && data &&
56 (cache[i]->key.objectid & cache[i]->key.offset) == 0)
57 continue;
58 used = btrfs_block_group_used(&cache[i]->item); 104 used = btrfs_block_group_used(&cache[i]->item);
59 if (used < (cache[i]->key.offset * 2) / 3) { 105 if (used + cache[i]->pinned <
60 info->block_group_cache = cache[i]; 106 (cache[i]->key.offset * 8) / 10) {
61 found_group = cache[i]; 107 found_group = cache[i];
62 goto found; 108 goto found;
63 } 109 }
64 radix_tree_tag_clear(&info->block_group_radix, 110 if (used >= (cache[i]->key.offset * 8) / 10) {
65 cache[i]->key.objectid + 111 radix_tree_tag_clear(radix,
66 cache[i]->key.offset - 1, 112 cache[i]->key.objectid +
67 BTRFS_BLOCK_GROUP_AVAIL); 113 cache[i]->key.offset - 1,
114 BTRFS_BLOCK_GROUP_AVAIL);
115 }
68 } 116 }
69 } 117 }
70 last = hint_last; 118 last = hint_last;
71again: 119again:
72 while(1) { 120 while(1) {
73 ret = radix_tree_gang_lookup(&info->block_group_radix, 121 ret = radix_tree_gang_lookup(radix, (void **)cache,
74 (void **)cache, 122 last, ARRAY_SIZE(cache));
75 last, ARRAY_SIZE(cache));
76 if (!ret) 123 if (!ret)
77 break; 124 break;
78 for (i = 0; i < ret; i++) { 125 for (i = 0; i < ret; i++) {
79 last = cache[i]->key.objectid + 126 last = cache[i]->key.objectid +
80 cache[i]->key.offset; 127 cache[i]->key.offset;
81 if (!full_search && !data &&
82 (cache[i]->key.objectid & cache[i]->key.offset))
83 continue;
84 if (!full_search && data &&
85 (cache[i]->key.objectid & cache[i]->key.offset) == 0)
86 continue;
87 used = btrfs_block_group_used(&cache[i]->item); 128 used = btrfs_block_group_used(&cache[i]->item);
88 if (used < cache[i]->key.offset) { 129 if (used + cache[i]->pinned < cache[i]->key.offset) {
89 info->block_group_cache = cache[i];
90 found_group = cache[i]; 130 found_group = cache[i];
91 goto found; 131 goto found;
92 } 132 }
93 radix_tree_tag_clear(&info->block_group_radix, 133 if (used >= cache[i]->key.offset) {
94 cache[i]->key.objectid + 134 radix_tree_tag_clear(radix,
95 cache[i]->key.offset - 1, 135 cache[i]->key.objectid +
96 BTRFS_BLOCK_GROUP_AVAIL); 136 cache[i]->key.offset - 1,
137 BTRFS_BLOCK_GROUP_AVAIL);
138 }
97 } 139 }
98 } 140 }
99 info->block_group_cache = NULL;
100 if (!full_search) { 141 if (!full_search) {
101 last = 0; 142 last = search_start;
102 full_search = 1; 143 full_search = 1;
103 goto again; 144 goto again;
104 } 145 }
105found:
106 if (!found_group) { 146 if (!found_group) {
107 ret = radix_tree_gang_lookup(&info->block_group_radix, 147 ret = radix_tree_gang_lookup(radix,
108 (void **)&found_group, 0, 1); 148 (void **)&found_group, 0, 1);
109 BUG_ON(ret != 1); 149 BUG_ON(ret != 1);
110 } 150 }
151found:
111 return found_group; 152 return found_group;
112} 153}
113 154
@@ -252,18 +293,20 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans,
252 return ret; 293 return ret;
253 if (pending_ret) 294 if (pending_ret)
254 return pending_ret; 295 return pending_ret;
296 if (cache->data)
297 cache->last_alloc = cache->first_free;
255 return 0; 298 return 0;
256 299
257} 300}
258 301
259int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, 302static int write_dirty_block_radix(struct btrfs_trans_handle *trans,
260 struct btrfs_root *root) 303 struct btrfs_root *root,
304 struct radix_tree_root *radix)
261{ 305{
262 struct btrfs_block_group_cache *cache[8]; 306 struct btrfs_block_group_cache *cache[8];
263 int ret; 307 int ret;
264 int err = 0; 308 int err = 0;
265 int werr = 0; 309 int werr = 0;
266 struct radix_tree_root *radix = &root->fs_info->block_group_radix;
267 int i; 310 int i;
268 struct btrfs_path *path; 311 struct btrfs_path *path;
269 312
@@ -285,35 +328,74 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
285 path, cache[i]); 328 path, cache[i]);
286 if (err) 329 if (err)
287 werr = err; 330 werr = err;
288 cache[i]->last_alloc = cache[i]->first_free;
289 } 331 }
290 } 332 }
291 btrfs_free_path(path); 333 btrfs_free_path(path);
292 return werr; 334 return werr;
293} 335}
294 336
337int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
338 struct btrfs_root *root)
339{
340 int ret;
341 int ret2;
342 ret = write_dirty_block_radix(trans, root,
343 &root->fs_info->block_group_radix);
344 ret2 = write_dirty_block_radix(trans, root,
345 &root->fs_info->block_group_data_radix);
346 if (ret)
347 return ret;
348 if (ret2)
349 return ret2;
350 return 0;
351}
352
295static int update_block_group(struct btrfs_trans_handle *trans, 353static int update_block_group(struct btrfs_trans_handle *trans,
296 struct btrfs_root *root, 354 struct btrfs_root *root,
297 u64 blocknr, u64 num, int alloc) 355 u64 blocknr, u64 num, int alloc)
298{ 356{
299 struct btrfs_block_group_cache *cache; 357 struct btrfs_block_group_cache *cache;
300 struct btrfs_fs_info *info = root->fs_info; 358 struct btrfs_fs_info *info = root->fs_info;
359 struct radix_tree_root *radix;
301 u64 total = num; 360 u64 total = num;
302 u64 old_val; 361 u64 old_val;
303 u64 block_in_group; 362 u64 block_in_group;
304 int ret; 363 int ret;
364 if (num != 1)
365 radix = &info->block_group_data_radix;
366 else
367 radix = &info->block_group_radix;
305 while(total) { 368 while(total) {
306 ret = radix_tree_gang_lookup(&info->block_group_radix, 369 ret = radix_tree_gang_lookup(radix, (void **)&cache,
307 (void **)&cache, blocknr, 1); 370 blocknr, 1);
308 if (!ret) { 371 if (!ret) {
309 printk(KERN_CRIT "blocknr %Lu lookup failed\n", 372 printk(KERN_CRIT "blocknr %Lu lookup failed\n",
310 blocknr); 373 blocknr);
311 return -1; 374 return -1;
312 } 375 }
313 block_in_group = blocknr - cache->key.objectid; 376 block_in_group = blocknr - cache->key.objectid;
377 if (block_in_group > cache->key.offset || cache->key.objectid >
378 blocknr) {
379 if (radix == &info->block_group_data_radix)
380 radix = &info->block_group_radix;
381 else
382 radix = &info->block_group_data_radix;
383 ret = radix_tree_gang_lookup(radix, (void **)&cache,
384 blocknr, 1);
385 if (!ret) {
386 printk(KERN_CRIT "blocknr %Lu lookup failed\n",
387 blocknr);
388 return -1;
389 }
390 block_in_group = blocknr - cache->key.objectid;
391 if (block_in_group > cache->key.offset ||
392 cache->key.objectid > blocknr) {
393 BUG();
394 }
395 }
314 WARN_ON(block_in_group > cache->key.offset); 396 WARN_ON(block_in_group > cache->key.offset);
315 radix_tree_tag_set(&info->block_group_radix, 397 radix_tree_tag_set(radix, cache->key.objectid +
316 cache->key.objectid + cache->key.offset - 1, 398 cache->key.offset - 1,
317 BTRFS_BLOCK_GROUP_DIRTY); 399 BTRFS_BLOCK_GROUP_DIRTY);
318 400
319 old_val = btrfs_block_group_used(&cache->item); 401 old_val = btrfs_block_group_used(&cache->item);
@@ -346,6 +428,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
346{ 428{
347 unsigned long gang[8]; 429 unsigned long gang[8];
348 struct inode *btree_inode = root->fs_info->btree_inode; 430 struct inode *btree_inode = root->fs_info->btree_inode;
431 struct btrfs_block_group_cache *block_group;
349 u64 first = 0; 432 u64 first = 0;
350 int ret; 433 int ret;
351 int i; 434 int i;
@@ -360,6 +443,14 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
360 first = gang[0]; 443 first = gang[0];
361 for (i = 0; i < ret; i++) { 444 for (i = 0; i < ret; i++) {
362 clear_radix_bit(pinned_radix, gang[i]); 445 clear_radix_bit(pinned_radix, gang[i]);
446 block_group = lookup_block_group(root->fs_info,
447 gang[i]);
448 if (block_group) {
449 WARN_ON(block_group->pinned == 0);
450 block_group->pinned--;
451 if (gang[i] < block_group->last_alloc)
452 block_group->last_alloc = gang[i];
453 }
363 try_remove_page(btree_inode->i_mapping, 454 try_remove_page(btree_inode->i_mapping,
364 gang[i] << (PAGE_CACHE_SHIFT - 455 gang[i] << (PAGE_CACHE_SHIFT -
365 btree_inode->i_blkbits)); 456 btree_inode->i_blkbits));
@@ -420,10 +511,16 @@ static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending)
420 btrfs_block_release(root, bh); 511 btrfs_block_release(root, bh);
421 } 512 }
422 err = set_radix_bit(&root->fs_info->pinned_radix, blocknr); 513 err = set_radix_bit(&root->fs_info->pinned_radix, blocknr);
514 if (!err) {
515 struct btrfs_block_group_cache *cache;
516 cache = lookup_block_group(root->fs_info, blocknr);
517 if (cache)
518 cache->pinned++;
519 }
423 } else { 520 } else {
424 err = set_radix_bit(&root->fs_info->pending_del_radix, blocknr); 521 err = set_radix_bit(&root->fs_info->pending_del_radix, blocknr);
425 } 522 }
426 BUG_ON(err); 523 BUG_ON(err < 0);
427 return 0; 524 return 0;
428} 525}
429 526
@@ -502,6 +599,7 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
502 int i; 599 int i;
503 struct radix_tree_root *pending_radix; 600 struct radix_tree_root *pending_radix;
504 struct radix_tree_root *pinned_radix; 601 struct radix_tree_root *pinned_radix;
602 struct btrfs_block_group_cache *cache;
505 603
506 pending_radix = &extent_root->fs_info->pending_del_radix; 604 pending_radix = &extent_root->fs_info->pending_del_radix;
507 pinned_radix = &extent_root->fs_info->pinned_radix; 605 pinned_radix = &extent_root->fs_info->pinned_radix;
@@ -513,7 +611,17 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
513 break; 611 break;
514 for (i = 0; i < ret; i++) { 612 for (i = 0; i < ret; i++) {
515 wret = set_radix_bit(pinned_radix, gang[i]); 613 wret = set_radix_bit(pinned_radix, gang[i]);
516 BUG_ON(wret); 614 if (wret == 0) {
615 cache = lookup_block_group(extent_root->fs_info,
616 gang[i]);
617 if (cache)
618 cache->pinned++;
619 }
620 if (wret < 0) {
621 printk(KERN_CRIT "set_radix_bit, err %d\n",
622 wret);
623 BUG_ON(wret < 0);
624 }
517 wret = clear_radix_bit(pending_radix, gang[i]); 625 wret = clear_radix_bit(pending_radix, gang[i]);
518 BUG_ON(wret); 626 BUG_ON(wret);
519 wret = __free_extent(trans, extent_root, 627 wret = __free_extent(trans, extent_root,
@@ -563,6 +671,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
563 int slot = 0; 671 int slot = 0;
564 u64 last_block = 0; 672 u64 last_block = 0;
565 u64 test_block; 673 u64 test_block;
674 u64 orig_search_start = search_start;
566 int start_found; 675 int start_found;
567 struct btrfs_leaf *l; 676 struct btrfs_leaf *l;
568 struct btrfs_root * root = orig_root->fs_info->extent_root; 677 struct btrfs_root * root = orig_root->fs_info->extent_root;
@@ -572,6 +681,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
572 int fill_prealloc = 0; 681 int fill_prealloc = 0;
573 int level; 682 int level;
574 struct btrfs_block_group_cache *block_group; 683 struct btrfs_block_group_cache *block_group;
684 int full_scan = 0;
575 685
576 path = btrfs_alloc_path(); 686 path = btrfs_alloc_path();
577 ins->flags = 0; 687 ins->flags = 0;
@@ -583,10 +693,21 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
583 num_blocks = 1; 693 num_blocks = 1;
584 total_needed = (min(level + 1, BTRFS_MAX_LEVEL) + 2) * 3; 694 total_needed = (min(level + 1, BTRFS_MAX_LEVEL) + 2) * 3;
585 } 695 }
586 block_group = btrfs_find_block_group(root, trans->block_group, data); 696 if (search_start) {
697 block_group = lookup_block_group(info, search_start);
698 block_group = btrfs_find_block_group(root, block_group,
699 search_start, data);
700 } else {
701 block_group = btrfs_find_block_group(root,
702 trans->block_group, 0,
703 data);
704 }
705
706check_failed:
707 if (block_group->data != data)
708 WARN_ON(1);
587 if (block_group->last_alloc > search_start) 709 if (block_group->last_alloc > search_start)
588 search_start = block_group->last_alloc; 710 search_start = block_group->last_alloc;
589check_failed:
590 btrfs_init_path(path); 711 btrfs_init_path(path);
591 ins->objectid = search_start; 712 ins->objectid = search_start;
592 ins->offset = 0; 713 ins->offset = 0;
@@ -639,6 +760,13 @@ check_failed:
639 } 760 }
640 start_found = 1; 761 start_found = 1;
641 last_block = key.objectid + key.offset; 762 last_block = key.objectid + key.offset;
763 if (last_block >= block_group->key.objectid +
764 block_group->key.offset) {
765 btrfs_release_path(root, path);
766 search_start = block_group->key.objectid +
767 block_group->key.offset * 2;
768 goto new_group;
769 }
642next: 770next:
643 path->slots[0]++; 771 path->slots[0]++;
644 } 772 }
@@ -650,16 +778,17 @@ check_pending:
650 btrfs_release_path(root, path); 778 btrfs_release_path(root, path);
651 BUG_ON(ins->objectid < search_start); 779 BUG_ON(ins->objectid < search_start);
652 if (ins->objectid >= btrfs_super_total_blocks(info->disk_super)) { 780 if (ins->objectid >= btrfs_super_total_blocks(info->disk_super)) {
653 if (search_start == 0) 781 if (full_scan)
654 return -ENOSPC; 782 return -ENOSPC;
655 search_start = 0; 783 search_start = orig_search_start;
656 goto check_failed; 784 full_scan = 1;
785 goto new_group;
657 } 786 }
658 for (test_block = ins->objectid; 787 for (test_block = ins->objectid;
659 test_block < ins->objectid + num_blocks; test_block++) { 788 test_block < ins->objectid + num_blocks; test_block++) {
660 if (test_radix_bit(&info->pinned_radix, test_block)) { 789 if (test_radix_bit(&info->pinned_radix, test_block)) {
661 search_start = test_block + 1; 790 search_start = test_block + 1;
662 goto check_failed; 791 goto new_group;
663 } 792 }
664 } 793 }
665 if (!fill_prealloc && info->extent_tree_insert_nr) { 794 if (!fill_prealloc && info->extent_tree_insert_nr) {
@@ -670,7 +799,7 @@ check_pending:
670 ins->objectid <= last) { 799 ins->objectid <= last) {
671 search_start = last + 1; 800 search_start = last + 1;
672 WARN_ON(1); 801 WARN_ON(1);
673 goto check_failed; 802 goto new_group;
674 } 803 }
675 } 804 }
676 if (!fill_prealloc && info->extent_tree_prealloc_nr) { 805 if (!fill_prealloc && info->extent_tree_prealloc_nr) {
@@ -680,7 +809,7 @@ check_pending:
680 ins->objectid <= info->extent_tree_prealloc[0]) { 809 ins->objectid <= info->extent_tree_prealloc[0]) {
681 search_start = info->extent_tree_prealloc[0] + 1; 810 search_start = info->extent_tree_prealloc[0] + 1;
682 WARN_ON(1); 811 WARN_ON(1);
683 goto check_failed; 812 goto new_group;
684 } 813 }
685 } 814 }
686 if (fill_prealloc) { 815 if (fill_prealloc) {
@@ -696,14 +825,12 @@ check_pending:
696 } 825 }
697 if (total_found < total_needed) { 826 if (total_found < total_needed) {
698 search_start = test_block; 827 search_start = test_block;
699 goto check_failed; 828 goto new_group;
700 } 829 }
701 info->extent_tree_prealloc_nr = total_found; 830 info->extent_tree_prealloc_nr = total_found;
702 } 831 }
703 ret = radix_tree_gang_lookup(&info->block_group_radix, 832 block_group = lookup_block_group(info, ins->objectid);
704 (void **)&block_group, 833 if (block_group) {
705 ins->objectid, 1);
706 if (ret) {
707 block_group->last_alloc = ins->objectid; 834 block_group->last_alloc = ins->objectid;
708 if (!data) 835 if (!data)
709 trans->block_group = block_group; 836 trans->block_group = block_group;
@@ -711,6 +838,18 @@ check_pending:
711 ins->offset = num_blocks; 838 ins->offset = num_blocks;
712 btrfs_free_path(path); 839 btrfs_free_path(path);
713 return 0; 840 return 0;
841
842new_group:
843 if (search_start >= btrfs_super_total_blocks(info->disk_super)) {
844 search_start = orig_search_start;
845 full_scan = 1;
846 }
847 block_group = lookup_block_group(info, search_start);
848 if (!full_scan)
849 block_group = btrfs_find_block_group(root, block_group,
850 search_start, data);
851 goto check_failed;
852
714error: 853error:
715 btrfs_release_path(root, path); 854 btrfs_release_path(root, path);
716 btrfs_free_path(path); 855 btrfs_free_path(path);
@@ -794,7 +933,7 @@ struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
794 struct buffer_head *buf; 933 struct buffer_head *buf;
795 934
796 ret = btrfs_alloc_extent(trans, root, root->root_key.objectid, 935 ret = btrfs_alloc_extent(trans, root, root->root_key.objectid,
797 1, 0, (unsigned long)-1, &ins, 0); 936 1, hint, (unsigned long)-1, &ins, 0);
798 if (ret) { 937 if (ret) {
799 BUG(); 938 BUG();
800 return NULL; 939 return NULL;
@@ -984,21 +1123,19 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
984 return ret; 1123 return ret;
985} 1124}
986 1125
987int btrfs_free_block_groups(struct btrfs_fs_info *info) 1126static int free_block_group_radix(struct radix_tree_root *radix)
988{ 1127{
989 int ret; 1128 int ret;
990 struct btrfs_block_group_cache *cache[8]; 1129 struct btrfs_block_group_cache *cache[8];
991 int i; 1130 int i;
992 1131
993 while(1) { 1132 while(1) {
994 ret = radix_tree_gang_lookup(&info->block_group_radix, 1133 ret = radix_tree_gang_lookup(radix, (void **)cache, 0,
995 (void **)cache, 0,
996 ARRAY_SIZE(cache)); 1134 ARRAY_SIZE(cache));
997 if (!ret) 1135 if (!ret)
998 break; 1136 break;
999 for (i = 0; i < ret; i++) { 1137 for (i = 0; i < ret; i++) {
1000 radix_tree_delete(&info->block_group_radix, 1138 radix_tree_delete(radix, cache[i]->key.objectid +
1001 cache[i]->key.objectid +
1002 cache[i]->key.offset - 1); 1139 cache[i]->key.offset - 1);
1003 kfree(cache[i]); 1140 kfree(cache[i]);
1004 } 1141 }
@@ -1006,6 +1143,20 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
1006 return 0; 1143 return 0;
1007} 1144}
1008 1145
1146int btrfs_free_block_groups(struct btrfs_fs_info *info)
1147{
1148 int ret;
1149 int ret2;
1150
1151 ret = free_block_group_radix(&info->block_group_radix);
1152 ret2 = free_block_group_radix(&info->block_group_data_radix);
1153 if (ret)
1154 return ret;
1155 if (ret2)
1156 return ret2;
1157 return 0;
1158}
1159
1009int btrfs_read_block_groups(struct btrfs_root *root) 1160int btrfs_read_block_groups(struct btrfs_root *root)
1010{ 1161{
1011 struct btrfs_path *path; 1162 struct btrfs_path *path;
@@ -1013,13 +1164,16 @@ int btrfs_read_block_groups(struct btrfs_root *root)
1013 int err = 0; 1164 int err = 0;
1014 struct btrfs_block_group_item *bi; 1165 struct btrfs_block_group_item *bi;
1015 struct btrfs_block_group_cache *cache; 1166 struct btrfs_block_group_cache *cache;
1167 struct btrfs_fs_info *info = root->fs_info;
1168 struct radix_tree_root *radix;
1016 struct btrfs_key key; 1169 struct btrfs_key key;
1017 struct btrfs_key found_key; 1170 struct btrfs_key found_key;
1018 struct btrfs_leaf *leaf; 1171 struct btrfs_leaf *leaf;
1019 u64 group_size_blocks = BTRFS_BLOCK_GROUP_SIZE / root->blocksize; 1172 u64 group_size_blocks = BTRFS_BLOCK_GROUP_SIZE / root->blocksize;
1020 u64 used; 1173 u64 used;
1174 u64 nr = 0;
1021 1175
1022 root = root->fs_info->extent_root; 1176 root = info->extent_root;
1023 key.objectid = 0; 1177 key.objectid = 0;
1024 key.offset = group_size_blocks; 1178 key.offset = group_size_blocks;
1025 key.flags = 0; 1179 key.flags = 0;
@@ -1030,7 +1184,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
1030 return -ENOMEM; 1184 return -ENOMEM;
1031 1185
1032 while(1) { 1186 while(1) {
1033 ret = btrfs_search_slot(NULL, root->fs_info->extent_root, 1187 ret = btrfs_search_slot(NULL, info->extent_root,
1034 &key, path, 0, 0); 1188 &key, path, 0, 0);
1035 if (ret != 0) { 1189 if (ret != 0) {
1036 err = ret; 1190 err = ret;
@@ -1050,23 +1204,28 @@ int btrfs_read_block_groups(struct btrfs_root *root)
1050 memcpy(&cache->key, &found_key, sizeof(found_key)); 1204 memcpy(&cache->key, &found_key, sizeof(found_key));
1051 cache->last_alloc = cache->key.objectid; 1205 cache->last_alloc = cache->key.objectid;
1052 cache->first_free = cache->key.objectid; 1206 cache->first_free = cache->key.objectid;
1207 cache->pinned = 0;
1208 cache->data = (nr & 1);
1053 key.objectid = found_key.objectid + found_key.offset; 1209 key.objectid = found_key.objectid + found_key.offset;
1054 btrfs_release_path(root, path); 1210 btrfs_release_path(root, path);
1055 ret = radix_tree_insert(&root->fs_info->block_group_radix, 1211 if (nr & 1)
1056 found_key.objectid + 1212 radix = &info->block_group_data_radix;
1213 else
1214 radix = &info->block_group_radix;
1215 ret = radix_tree_insert(radix, found_key.objectid +
1057 found_key.offset - 1, 1216 found_key.offset - 1,
1058 (void *)cache); 1217 (void *)cache);
1059 BUG_ON(ret); 1218 BUG_ON(ret);
1060 used = btrfs_block_group_used(bi); 1219 used = btrfs_block_group_used(bi);
1061 if (used < (key.offset * 2) / 3) { 1220 if (used < (key.offset * 8) / 10) {
1062 radix_tree_tag_set(&root->fs_info->block_group_radix, 1221 radix_tree_tag_set(radix, found_key.objectid +
1063 found_key.objectid +
1064 found_key.offset - 1, 1222 found_key.offset - 1,
1065 BTRFS_BLOCK_GROUP_AVAIL); 1223 BTRFS_BLOCK_GROUP_AVAIL);
1066 } 1224 }
1067 if (key.objectid >= 1225 if (key.objectid >=
1068 btrfs_super_total_blocks(root->fs_info->disk_super)) 1226 btrfs_super_total_blocks(info->disk_super))
1069 break; 1227 break;
1228 nr++;
1070 } 1229 }
1071 1230
1072 btrfs_free_path(path); 1231 btrfs_free_path(path);