diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-10-15 16:15:26 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:56 -0400 |
commit | 1a5bc167f6707542b79a55452075525620ed43f5 (patch) | |
tree | 9f87d9351928af0c5cffa057ed2df95c895d57d2 /fs/btrfs/extent-tree.c | |
parent | 96b5179d0d9b6368c203856f2ad6e8e12a8b2a2c (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.c | 193 |
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 | } |
190 | out: | 190 | out: |
191 | return max(cache->last_alloc, search_start); | 191 | return search_start; |
192 | 192 | ||
193 | new_group: | 193 | new_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 | ||
635 | int btrfs_copy_pinned(struct btrfs_root *root, struct radix_tree_root *copy) | 627 | int 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 | ||
659 | int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, | 646 | int 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 | ||
733 | static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending) | 704 | static 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; |