aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-10-15 16:15:26 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:56 -0400
commit1a5bc167f6707542b79a55452075525620ed43f5 (patch)
tree9f87d9351928af0c5cffa057ed2df95c895d57d2 /fs/btrfs/extent-tree.c
parent96b5179d0d9b6368c203856f2ad6e8e12a8b2a2c (diff)
Btrfs: Change the remaining radix trees used by extent-tree.c to extent_map trees
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c193
1 files changed, 72 insertions, 121 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 4bc639565d1c..477466d167a4 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -188,13 +188,13 @@ again:
188 return start; 188 return start;
189 } 189 }
190out: 190out:
191 return max(cache->last_alloc, search_start); 191 return search_start;
192 192
193new_group: 193new_group:
194 cache = btrfs_lookup_block_group(root->fs_info, 194 cache = btrfs_lookup_block_group(root->fs_info,
195 last + cache->key.offset - 1); 195 last + cache->key.offset - 1);
196 if (!cache) { 196 if (!cache) {
197 return max((*cache_ret)->last_alloc, search_start); 197 return search_start;
198 } 198 }
199 cache = btrfs_find_block_group(root, cache, 199 cache = btrfs_find_block_group(root, cache,
200 last + cache->key.offset - 1, data, 0); 200 last + cache->key.offset - 1, data, 0);
@@ -247,16 +247,14 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
247 shint = btrfs_lookup_block_group(info, search_start); 247 shint = btrfs_lookup_block_group(info, search_start);
248 if (shint && shint->data == data) { 248 if (shint && shint->data == data) {
249 used = btrfs_block_group_used(&shint->item); 249 used = btrfs_block_group_used(&shint->item);
250 if (used + shint->pinned < 250 if (used < div_factor(shint->key.offset, factor)) {
251 div_factor(shint->key.offset, factor)) {
252 return shint; 251 return shint;
253 } 252 }
254 } 253 }
255 } 254 }
256 if (hint && hint->data == data) { 255 if (hint && hint->data == data) {
257 used = btrfs_block_group_used(&hint->item); 256 used = btrfs_block_group_used(&hint->item);
258 if (used + hint->pinned < 257 if (used < div_factor(hint->key.offset, factor)) {
259 div_factor(hint->key.offset, factor)) {
260 return hint; 258 return hint;
261 } 259 }
262 last = hint->key.offset * 3; 260 last = hint->key.offset * 3;
@@ -294,7 +292,7 @@ again:
294 else 292 else
295 free_check = div_factor(cache->key.offset, factor); 293 free_check = div_factor(cache->key.offset, factor);
296 294
297 if (used + cache->pinned < free_check) { 295 if (used < free_check) {
298 found_group = cache; 296 found_group = cache;
299 goto found; 297 goto found;
300 } 298 }
@@ -505,8 +503,6 @@ fail:
505 return ret; 503 return ret;
506 if (pending_ret) 504 if (pending_ret)
507 return pending_ret; 505 return pending_ret;
508 if (cache->data)
509 cache->last_alloc = cache->first_free;
510 return 0; 506 return 0;
511 507
512} 508}
@@ -588,8 +584,6 @@ static int update_block_group(struct btrfs_trans_handle *trans,
588 old_val = btrfs_block_group_used(&cache->item); 584 old_val = btrfs_block_group_used(&cache->item);
589 num = min(total, cache->key.offset - block_in_group); 585 num = min(total, cache->key.offset - block_in_group);
590 if (alloc) { 586 if (alloc) {
591 if (blocknr > cache->last_alloc)
592 cache->last_alloc = blocknr;
593 if (cache->data != data && 587 if (cache->data != data &&
594 old_val < (cache->key.offset >> 1)) { 588 old_val < (cache->key.offset >> 1)) {
595 int bit_to_clear; 589 int bit_to_clear;
@@ -617,8 +611,6 @@ static int update_block_group(struct btrfs_trans_handle *trans,
617 old_val += num; 611 old_val += num;
618 } else { 612 } else {
619 old_val -= num; 613 old_val -= num;
620 if (blocknr < cache->first_free)
621 cache->first_free = blocknr;
622 if (mark_free) { 614 if (mark_free) {
623 set_extent_dirty(&info->free_space_cache, 615 set_extent_dirty(&info->free_space_cache,
624 blocknr, blocknr + num - 1, 616 blocknr, blocknr + num - 1,
@@ -632,65 +624,47 @@ static int update_block_group(struct btrfs_trans_handle *trans,
632 return 0; 624 return 0;
633} 625}
634 626
635int btrfs_copy_pinned(struct btrfs_root *root, struct radix_tree_root *copy) 627int btrfs_copy_pinned(struct btrfs_root *root, struct extent_map_tree *copy)
636{ 628{
637 unsigned long gang[8];
638 u64 last = 0; 629 u64 last = 0;
639 struct radix_tree_root *pinned_radix = &root->fs_info->pinned_radix; 630 u64 start;
631 u64 end;
632 struct extent_map_tree *pinned_extents = &root->fs_info->pinned_extents;
640 int ret; 633 int ret;
641 int i;
642 634
643 while(1) { 635 while(1) {
644 ret = find_first_radix_bit(pinned_radix, gang, last, 636 ret = find_first_extent_bit(pinned_extents, last,
645 ARRAY_SIZE(gang)); 637 &start, &end, EXTENT_DIRTY);
646 if (!ret) 638 if (ret)
647 break; 639 break;
648 for (i = 0 ; i < ret; i++) { 640 set_extent_dirty(copy, start, end, GFP_NOFS);
649 set_radix_bit(copy, gang[i]); 641 last = end + 1;
650 last = gang[i] + 1;
651 }
652 } 642 }
653 ret = find_first_radix_bit(&root->fs_info->extent_ins_radix, gang, 0,
654 ARRAY_SIZE(gang));
655 WARN_ON(ret);
656 return 0; 643 return 0;
657} 644}
658 645
659int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, 646int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
660 struct btrfs_root *root, 647 struct btrfs_root *root,
661 struct radix_tree_root *unpin_radix) 648 struct extent_map_tree *unpin)
662{ 649{
663 unsigned long gang[8]; 650 u64 start;
664 struct btrfs_block_group_cache *block_group; 651 u64 end;
665 u64 first = 0;
666 int ret; 652 int ret;
667 int i; 653 struct extent_map_tree *pinned_extents = &root->fs_info->pinned_extents;
668 struct radix_tree_root *pinned_radix = &root->fs_info->pinned_radix;
669 struct extent_map_tree *free_space_cache; 654 struct extent_map_tree *free_space_cache;
670 655
671 free_space_cache = &root->fs_info->free_space_cache; 656 free_space_cache = &root->fs_info->free_space_cache;
672 657
673 while(1) { 658 while(1) {
674 ret = find_first_radix_bit(unpin_radix, gang, 0, 659 ret = find_first_extent_bit(unpin, 0, &start, &end,
675 ARRAY_SIZE(gang)); 660 EXTENT_DIRTY);
676 if (!ret) 661 if (ret)
677 break; 662 break;
678 if (!first) 663
679 first = gang[0]; 664 clear_extent_dirty(pinned_extents, start, end,
680 for (i = 0; i < ret; i++) { 665 GFP_NOFS);
681 clear_radix_bit(pinned_radix, gang[i]); 666 clear_extent_dirty(unpin, start, end, GFP_NOFS);
682 clear_radix_bit(unpin_radix, gang[i]); 667 set_extent_dirty(free_space_cache, start, end, GFP_NOFS);
683 block_group = btrfs_lookup_block_group(root->fs_info,
684 gang[i]);
685 if (block_group) {
686 WARN_ON(block_group->pinned == 0);
687 block_group->pinned--;
688 if (gang[i] < block_group->last_alloc)
689 block_group->last_alloc = gang[i];
690 set_extent_dirty(free_space_cache,
691 gang[i], gang[i], GFP_NOFS);
692 }
693 }
694 } 668 }
695 return 0; 669 return 0;
696} 670}
@@ -700,39 +674,36 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
700{ 674{
701 struct btrfs_key ins; 675 struct btrfs_key ins;
702 struct btrfs_extent_item extent_item; 676 struct btrfs_extent_item extent_item;
703 int i;
704 int ret; 677 int ret;
705 int err; 678 int err = 0;
706 unsigned long gang[8]; 679 u64 start;
680 u64 end;
707 struct btrfs_fs_info *info = extent_root->fs_info; 681 struct btrfs_fs_info *info = extent_root->fs_info;
708 682
709 btrfs_set_stack_extent_refs(&extent_item, 1); 683 btrfs_set_stack_extent_refs(&extent_item, 1);
710 ins.offset = 1;
711 btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); 684 btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY);
712 btrfs_set_stack_extent_owner(&extent_item, 685 btrfs_set_stack_extent_owner(&extent_item,
713 extent_root->root_key.objectid); 686 extent_root->root_key.objectid);
714 687
715 while(1) { 688 while(1) {
716 ret = find_first_radix_bit(&info->extent_ins_radix, gang, 0, 689 ret = find_first_extent_bit(&info->extent_ins, 0, &start,
717 ARRAY_SIZE(gang)); 690 &end, EXTENT_LOCKED);
718 if (!ret) 691 if (ret)
719 break; 692 break;
720 693
721 for (i = 0; i < ret; i++) { 694 ins.objectid = start;
722 ins.objectid = gang[i]; 695 ins.offset = end + 1 - start;
723 err = btrfs_insert_item(trans, extent_root, &ins, 696 err = btrfs_insert_item(trans, extent_root, &ins,
724 &extent_item, 697 &extent_item, sizeof(extent_item));
725 sizeof(extent_item)); 698 clear_extent_bits(&info->extent_ins, start, end, EXTENT_LOCKED,
726 clear_radix_bit(&info->extent_ins_radix, gang[i]); 699 GFP_NOFS);
727 WARN_ON(err);
728 }
729 } 700 }
730 return 0; 701 return 0;
731} 702}
732 703
733static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending) 704static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending)
734{ 705{
735 int err; 706 int err = 0;
736 struct extent_buffer *buf; 707 struct extent_buffer *buf;
737 708
738 if (!pending) { 709 if (!pending) {
@@ -748,16 +719,11 @@ static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending)
748 } 719 }
749 free_extent_buffer(buf); 720 free_extent_buffer(buf);
750 } 721 }
751 err = set_radix_bit(&root->fs_info->pinned_radix, blocknr); 722 set_extent_dirty(&root->fs_info->pinned_extents,
752 if (!err) { 723 blocknr, blocknr, GFP_NOFS);
753 struct btrfs_block_group_cache *cache;
754 cache = btrfs_lookup_block_group(root->fs_info,
755 blocknr);
756 if (cache)
757 cache->pinned++;
758 }
759 } else { 724 } else {
760 err = set_radix_bit(&root->fs_info->pending_del_radix, blocknr); 725 set_extent_bits(&root->fs_info->pending_del,
726 blocknr, blocknr, EXTENT_LOCKED, GFP_NOFS);
761 } 727 }
762 BUG_ON(err < 0); 728 BUG_ON(err < 0);
763 return 0; 729 return 0;
@@ -840,43 +806,28 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
840 btrfs_root *extent_root) 806 btrfs_root *extent_root)
841{ 807{
842 int ret; 808 int ret;
843 int wret;
844 int err = 0; 809 int err = 0;
845 unsigned long gang[4]; 810 u64 start;
846 int i; 811 u64 end;
847 struct radix_tree_root *pending_radix; 812 struct extent_map_tree *pending_del;
848 struct radix_tree_root *pinned_radix; 813 struct extent_map_tree *pinned_extents;
849 struct btrfs_block_group_cache *cache;
850 814
851 pending_radix = &extent_root->fs_info->pending_del_radix; 815 pending_del = &extent_root->fs_info->pending_del;
852 pinned_radix = &extent_root->fs_info->pinned_radix; 816 pinned_extents = &extent_root->fs_info->pinned_extents;
853 817
854 while(1) { 818 while(1) {
855 ret = find_first_radix_bit(pending_radix, gang, 0, 819 ret = find_first_extent_bit(pending_del, 0, &start, &end,
856 ARRAY_SIZE(gang)); 820 EXTENT_LOCKED);
857 if (!ret) 821 if (ret)
858 break; 822 break;
859 for (i = 0; i < ret; i++) { 823
860 wret = set_radix_bit(pinned_radix, gang[i]); 824 set_extent_dirty(pinned_extents, start, end, GFP_NOFS);
861 if (wret == 0) { 825 clear_extent_bits(pending_del, start, end, EXTENT_LOCKED,
862 cache = 826 GFP_NOFS);
863 btrfs_lookup_block_group(extent_root->fs_info, 827 ret = __free_extent(trans, extent_root,
864 gang[i]); 828 start, end + 1 - start, 0, 0);
865 if (cache) 829 if (ret)
866 cache->pinned++; 830 err = ret;
867 }
868 if (wret < 0) {
869 printk(KERN_CRIT "set_radix_bit, err %d\n",
870 wret);
871 BUG_ON(wret < 0);
872 }
873 wret = clear_radix_bit(pending_radix, gang[i]);
874 BUG_ON(wret);
875 wret = __free_extent(trans, extent_root,
876 gang[i], 1, 0, 0);
877 if (wret)
878 err = wret;
879 }
880 } 831 }
881 return err; 832 return err;
882} 833}
@@ -920,7 +871,6 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
920 u64 hole_size = 0; 871 u64 hole_size = 0;
921 int slot = 0; 872 int slot = 0;
922 u64 last_block = 0; 873 u64 last_block = 0;
923 u64 test_block;
924 u64 orig_search_start = search_start; 874 u64 orig_search_start = search_start;
925 int start_found; 875 int start_found;
926 struct extent_buffer *l; 876 struct extent_buffer *l;
@@ -1059,13 +1009,15 @@ check_pending:
1059 if (ins->objectid + num_blocks >= search_end) 1009 if (ins->objectid + num_blocks >= search_end)
1060 goto enospc; 1010 goto enospc;
1061 1011
1062 for (test_block = ins->objectid; 1012 if (test_range_bit(&info->extent_ins, ins->objectid,
1063 test_block < ins->objectid + num_blocks; test_block++) { 1013 ins->objectid + num_blocks -1, EXTENT_LOCKED, 0)) {
1064 if (test_radix_bit(&info->pinned_radix, test_block) || 1014 search_start = ins->objectid + num_blocks;
1065 test_radix_bit(&info->extent_ins_radix, test_block)) { 1015 goto new_group;
1066 search_start = test_block + 1; 1016 }
1067 goto new_group; 1017 if (test_range_bit(&info->pinned_extents, ins->objectid,
1068 } 1018 ins->objectid + num_blocks -1, EXTENT_DIRTY, 0)) {
1019 search_start = ins->objectid + num_blocks;
1020 goto new_group;
1069 } 1021 }
1070 if (exclude_nr > 0 && (ins->objectid + num_blocks > exclude_start && 1022 if (exclude_nr > 0 && (ins->objectid + num_blocks > exclude_start &&
1071 ins->objectid < exclude_start + exclude_nr)) { 1023 ins->objectid < exclude_start + exclude_nr)) {
@@ -1156,7 +1108,9 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1156 1108
1157 if (root == extent_root) { 1109 if (root == extent_root) {
1158 BUG_ON(num_blocks != 1); 1110 BUG_ON(num_blocks != 1);
1159 set_radix_bit(&root->fs_info->extent_ins_radix, ins->objectid); 1111 set_extent_bits(&root->fs_info->extent_ins, ins->objectid,
1112 ins->objectid + ins->offset - 1,
1113 EXTENT_LOCKED, GFP_NOFS);
1160 goto update_block; 1114 goto update_block;
1161 } 1115 }
1162 1116
@@ -1557,9 +1511,6 @@ int btrfs_read_block_groups(struct btrfs_root *root)
1557 btrfs_item_ptr_offset(leaf, path->slots[0]), 1511 btrfs_item_ptr_offset(leaf, path->slots[0]),
1558 sizeof(cache->item)); 1512 sizeof(cache->item));
1559 memcpy(&cache->key, &found_key, sizeof(found_key)); 1513 memcpy(&cache->key, &found_key, sizeof(found_key));
1560 cache->last_alloc = cache->key.objectid;
1561 cache->first_free = cache->key.objectid;
1562 cache->pinned = 0;
1563 cache->cached = 0; 1514 cache->cached = 0;
1564 1515
1565 key.objectid = found_key.objectid + found_key.offset; 1516 key.objectid = found_key.objectid + found_key.offset;