aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c95
1 files changed, 48 insertions, 47 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 0e20d1c42fca..c5ae51893f78 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -6,7 +6,7 @@
6 6
7static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root 7static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
8 *orig_root, u64 num_blocks, u64 search_start, u64 8 *orig_root, u64 num_blocks, u64 search_start, u64
9 search_end, struct btrfs_key *ins); 9 search_end, struct btrfs_key *ins, int data);
10static int finish_current_insert(struct btrfs_trans_handle *trans, struct 10static int finish_current_insert(struct btrfs_trans_handle *trans, struct
11 btrfs_root *extent_root); 11 btrfs_root *extent_root);
12static int del_pending_extents(struct btrfs_trans_handle *trans, struct 12static int del_pending_extents(struct btrfs_trans_handle *trans, struct
@@ -25,7 +25,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
25 int i; 25 int i;
26 int ret; 26 int ret;
27 int full_search = 0; 27 int full_search = 0;
28 if (hint) { 28 if (!data && hint) {
29 used = btrfs_block_group_used(&hint->item); 29 used = btrfs_block_group_used(&hint->item);
30 if (used < (hint->key.offset * 2) / 3) { 30 if (used < (hint->key.offset * 2) / 3) {
31 return hint; 31 return hint;
@@ -47,6 +47,14 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
47 if (!ret) 47 if (!ret)
48 break; 48 break;
49 for (i = 0; i < ret; i++) { 49 for (i = 0; i < ret; i++) {
50 last = cache[i]->key.objectid +
51 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;
50 used = btrfs_block_group_used(&cache[i]->item); 58 used = btrfs_block_group_used(&cache[i]->item);
51 if (used < (cache[i]->key.offset * 2) / 3) { 59 if (used < (cache[i]->key.offset * 2) / 3) {
52 info->block_group_cache = cache[i]; 60 info->block_group_cache = cache[i];
@@ -57,8 +65,6 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
57 cache[i]->key.objectid + 65 cache[i]->key.objectid +
58 cache[i]->key.offset - 1, 66 cache[i]->key.offset - 1,
59 BTRFS_BLOCK_GROUP_AVAIL); 67 BTRFS_BLOCK_GROUP_AVAIL);
60 last = cache[i]->key.objectid +
61 cache[i]->key.offset;
62 } 68 }
63 } 69 }
64 last = hint_last; 70 last = hint_last;
@@ -70,6 +76,14 @@ again:
70 if (!ret) 76 if (!ret)
71 break; 77 break;
72 for (i = 0; i < ret; i++) { 78 for (i = 0; i < ret; i++) {
79 last = cache[i]->key.objectid +
80 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;
73 used = btrfs_block_group_used(&cache[i]->item); 87 used = btrfs_block_group_used(&cache[i]->item);
74 if (used < cache[i]->key.offset) { 88 if (used < cache[i]->key.offset) {
75 info->block_group_cache = cache[i]; 89 info->block_group_cache = cache[i];
@@ -80,8 +94,6 @@ again:
80 cache[i]->key.objectid + 94 cache[i]->key.objectid +
81 cache[i]->key.offset - 1, 95 cache[i]->key.offset - 1,
82 BTRFS_BLOCK_GROUP_AVAIL); 96 BTRFS_BLOCK_GROUP_AVAIL);
83 last = cache[i]->key.objectid +
84 cache[i]->key.offset;
85 } 97 }
86 } 98 }
87 info->block_group_cache = NULL; 99 info->block_group_cache = NULL;
@@ -112,7 +124,7 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
112 u32 refs; 124 u32 refs;
113 125
114 find_free_extent(trans, root->fs_info->extent_root, 0, 0, (u64)-1, 126 find_free_extent(trans, root->fs_info->extent_root, 0, 0, (u64)-1,
115 &ins); 127 &ins, 0);
116 path = btrfs_alloc_path(); 128 path = btrfs_alloc_path();
117 BUG_ON(!path); 129 BUG_ON(!path);
118 btrfs_init_path(path); 130 btrfs_init_path(path);
@@ -225,7 +237,7 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans,
225 struct btrfs_block_group_item *bi; 237 struct btrfs_block_group_item *bi;
226 struct btrfs_key ins; 238 struct btrfs_key ins;
227 239
228 find_free_extent(trans, extent_root, 0, 0, (u64)-1, &ins); 240 find_free_extent(trans, extent_root, 0, 0, (u64)-1, &ins, 0);
229 ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1); 241 ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1);
230 BUG_ON(ret); 242 BUG_ON(ret);
231 bi = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], 243 bi = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0],
@@ -322,10 +334,18 @@ static int update_block_group(struct btrfs_trans_handle *trans,
322 return 0; 334 return 0;
323} 335}
324 336
337static int try_remove_page(struct address_space *mapping, unsigned long index)
338{
339 int ret;
340 ret = invalidate_mapping_pages(mapping, index, index);
341 return ret;
342}
343
325int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct 344int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
326 btrfs_root *root) 345 btrfs_root *root)
327{ 346{
328 unsigned long gang[8]; 347 unsigned long gang[8];
348 struct inode *btree_inode = root->fs_info->btree_inode;
329 u64 first = 0; 349 u64 first = 0;
330 int ret; 350 int ret;
331 int i; 351 int i;
@@ -340,6 +360,9 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
340 first = gang[0]; 360 first = gang[0];
341 for (i = 0; i < ret; i++) { 361 for (i = 0; i < ret; i++) {
342 clear_radix_bit(pinned_radix, gang[i]); 362 clear_radix_bit(pinned_radix, gang[i]);
363 try_remove_page(btree_inode->i_mapping,
364 gang[i] << (PAGE_CACHE_SHIFT -
365 btree_inode->i_blkbits));
343 } 366 }
344 } 367 }
345 return 0; 368 return 0;
@@ -424,7 +447,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
424 btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); 447 btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
425 key.offset = num_blocks; 448 key.offset = num_blocks;
426 449
427 find_free_extent(trans, root, 0, 0, (u64)-1, &ins); 450 find_free_extent(trans, root, 0, 0, (u64)-1, &ins, 0);
428 path = btrfs_alloc_path(); 451 path = btrfs_alloc_path();
429 BUG_ON(!path); 452 BUG_ON(!path);
430 btrfs_init_path(path); 453 btrfs_init_path(path);
@@ -531,7 +554,7 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
531 */ 554 */
532static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root 555static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
533 *orig_root, u64 num_blocks, u64 search_start, u64 556 *orig_root, u64 num_blocks, u64 search_start, u64
534 search_end, struct btrfs_key *ins) 557 search_end, struct btrfs_key *ins, int data)
535{ 558{
536 struct btrfs_path *path; 559 struct btrfs_path *path;
537 struct btrfs_key key; 560 struct btrfs_key key;
@@ -548,43 +571,21 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
548 int total_found = 0; 571 int total_found = 0;
549 int fill_prealloc = 0; 572 int fill_prealloc = 0;
550 int level; 573 int level;
551 int update_block_group = 0; 574 struct btrfs_block_group_cache *block_group;
552 struct btrfs_block_group_cache *hint_block_group;
553 575
554 path = btrfs_alloc_path(); 576 path = btrfs_alloc_path();
555 ins->flags = 0; 577 ins->flags = 0;
556 btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY); 578 btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY);
557 579
558 level = btrfs_header_level(btrfs_buffer_header(root->node)); 580 level = btrfs_header_level(btrfs_buffer_header(root->node));
559 /* find search start here */
560 if (0 && search_start && num_blocks) {
561 u64 used;
562 ret = radix_tree_gang_lookup(&info->block_group_radix,
563 (void **)&hint_block_group,
564 search_start, 1);
565 if (ret) {
566 used = btrfs_block_group_used(&hint_block_group->item);
567 if (used > (hint_block_group->key.offset * 9) / 10)
568 search_start = 0;
569 else if (search_start < hint_block_group->last_alloc)
570 search_start = hint_block_group->last_alloc;
571 } else {
572 search_start = 0;
573 }
574 }
575 if (num_blocks == 0) { 581 if (num_blocks == 0) {
576 fill_prealloc = 1; 582 fill_prealloc = 1;
577 num_blocks = 1; 583 num_blocks = 1;
578 total_needed = (min(level + 1, BTRFS_MAX_LEVEL) + 2) * 3; 584 total_needed = (min(level + 1, BTRFS_MAX_LEVEL) + 2) * 3;
579 } 585 }
580 if (1 || !search_start) { 586 block_group = btrfs_find_block_group(root, trans->block_group, data);
581 trans->block_group = btrfs_find_block_group(root, 587 if (block_group->last_alloc > search_start)
582 trans->block_group, 588 search_start = block_group->last_alloc;
583 0);
584 if (trans->block_group->last_alloc > search_start)
585 search_start = trans->block_group->last_alloc;
586 update_block_group = 1;
587 }
588check_failed: 589check_failed:
589 btrfs_init_path(path); 590 btrfs_init_path(path);
590 ins->objectid = search_start; 591 ins->objectid = search_start;
@@ -699,13 +700,13 @@ check_pending:
699 } 700 }
700 info->extent_tree_prealloc_nr = total_found; 701 info->extent_tree_prealloc_nr = total_found;
701 } 702 }
702 if (update_block_group) { 703 ret = radix_tree_gang_lookup(&info->block_group_radix,
703 ret = radix_tree_gang_lookup(&info->block_group_radix, 704 (void **)&block_group,
704 (void **)&trans->block_group, 705 ins->objectid, 1);
705 ins->objectid, 1); 706 if (ret) {
706 if (ret) { 707 block_group->last_alloc = ins->objectid;
707 trans->block_group->last_alloc = ins->objectid; 708 if (!data)
708 } 709 trans->block_group = block_group;
709 } 710 }
710 ins->offset = num_blocks; 711 ins->offset = num_blocks;
711 btrfs_free_path(path); 712 btrfs_free_path(path);
@@ -725,7 +726,7 @@ error:
725int btrfs_alloc_extent(struct btrfs_trans_handle *trans, 726int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
726 struct btrfs_root *root, u64 owner, 727 struct btrfs_root *root, u64 owner,
727 u64 num_blocks, u64 search_start, 728 u64 num_blocks, u64 search_start,
728 u64 search_end, struct btrfs_key *ins) 729 u64 search_end, struct btrfs_key *ins, int data)
729{ 730{
730 int ret; 731 int ret;
731 int pending_ret; 732 int pending_ret;
@@ -755,13 +756,13 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
755 } 756 }
756 /* do the real allocation */ 757 /* do the real allocation */
757 ret = find_free_extent(trans, root, num_blocks, search_start, 758 ret = find_free_extent(trans, root, num_blocks, search_start,
758 search_end, ins); 759 search_end, ins, data);
759 if (ret) 760 if (ret)
760 return ret; 761 return ret;
761 762
762 /* then do prealloc for the extent tree */ 763 /* then do prealloc for the extent tree */
763 ret = find_free_extent(trans, root, 0, ins->objectid + ins->offset, 764 ret = find_free_extent(trans, root, 0, ins->objectid + ins->offset,
764 search_end, &prealloc_key); 765 search_end, &prealloc_key, 0);
765 if (ret) 766 if (ret)
766 return ret; 767 return ret;
767 768
@@ -793,7 +794,7 @@ struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
793 struct buffer_head *buf; 794 struct buffer_head *buf;
794 795
795 ret = btrfs_alloc_extent(trans, root, root->root_key.objectid, 796 ret = btrfs_alloc_extent(trans, root, root->root_key.objectid,
796 1, hint, (unsigned long)-1, &ins); 797 1, 0, (unsigned long)-1, &ins, 0);
797 if (ret) { 798 if (ret) {
798 BUG(); 799 BUG();
799 return NULL; 800 return NULL;