aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@redhat.com>2009-04-03 10:14:19 -0400
committerChris Mason <chris.mason@oracle.com>2009-04-03 10:14:19 -0400
commit2552d17e328044d1811cae733087a1fb9aac2eb6 (patch)
tree21101d10ccfa4f44d150bc570c2080160e332305 /fs/btrfs
parent70cb074345832b75cf422ed729706345511773b3 (diff)
Btrfs: clean up find_free_extent
I've replaced the strange looping constructs with a list_for_each_entry on space_info->block_groups. If we have a hint we just jump into the loop with the block group and start looking for space. If we don't find anything we start at the beginning and start looking. We never come out of the loop with a ref on the block_group _unless_ we found space to use, then we drop it after we set the trans block_group. Signed-off-by: Josef Bacik <jbacik@redhat.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/extent-tree.c256
1 files changed, 91 insertions, 165 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 2c214781fee6..daff751ea6e2 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2556,14 +2556,10 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
2556 struct btrfs_root *root = orig_root->fs_info->extent_root; 2556 struct btrfs_root *root = orig_root->fs_info->extent_root;
2557 u64 total_needed = num_bytes; 2557 u64 total_needed = num_bytes;
2558 u64 *last_ptr = NULL; 2558 u64 *last_ptr = NULL;
2559 u64 last_wanted = 0;
2560 struct btrfs_block_group_cache *block_group = NULL; 2559 struct btrfs_block_group_cache *block_group = NULL;
2561 int chunk_alloc_done = 0;
2562 int empty_cluster = 2 * 1024 * 1024; 2560 int empty_cluster = 2 * 1024 * 1024;
2563 int allowed_chunk_alloc = 0; 2561 int allowed_chunk_alloc = 0;
2564 struct list_head *head = NULL, *cur = NULL; 2562 int using_hint = 0;
2565 int loop = 0;
2566 int extra_loop = 0;
2567 struct btrfs_space_info *space_info; 2563 struct btrfs_space_info *space_info;
2568 2564
2569 WARN_ON(num_bytes < root->sectorsize); 2565 WARN_ON(num_bytes < root->sectorsize);
@@ -2571,6 +2567,8 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
2571 ins->objectid = 0; 2567 ins->objectid = 0;
2572 ins->offset = 0; 2568 ins->offset = 0;
2573 2569
2570 space_info = __find_space_info(root->fs_info, data);
2571
2574 if (orig_root->ref_cows || empty_size) 2572 if (orig_root->ref_cows || empty_size)
2575 allowed_chunk_alloc = 1; 2573 allowed_chunk_alloc = 1;
2576 2574
@@ -2584,10 +2582,9 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
2584 last_ptr = &root->fs_info->last_data_alloc; 2582 last_ptr = &root->fs_info->last_data_alloc;
2585 2583
2586 if (last_ptr) { 2584 if (last_ptr) {
2587 if (*last_ptr) { 2585 if (*last_ptr)
2588 hint_byte = *last_ptr; 2586 hint_byte = *last_ptr;
2589 last_wanted = *last_ptr; 2587 else
2590 } else
2591 empty_size += empty_cluster; 2588 empty_size += empty_cluster;
2592 } else { 2589 } else {
2593 empty_cluster = 0; 2590 empty_cluster = 0;
@@ -2595,187 +2592,125 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
2595 search_start = max(search_start, first_logical_byte(root, 0)); 2592 search_start = max(search_start, first_logical_byte(root, 0));
2596 search_start = max(search_start, hint_byte); 2593 search_start = max(search_start, hint_byte);
2597 2594
2598 if (last_wanted && search_start != last_wanted) { 2595 if (search_start == hint_byte) {
2599 last_wanted = 0; 2596 using_hint = 1;
2597 block_group = btrfs_lookup_block_group(root->fs_info,
2598 search_start);
2599 if (block_group && block_group_bits(block_group, data)) {
2600 total_needed += empty_size;
2601 down_read(&space_info->groups_sem);
2602 goto have_block_group;
2603 } else if (block_group) {
2604 put_block_group(block_group);
2605 }
2606
2600 empty_size += empty_cluster; 2607 empty_size += empty_cluster;
2608 using_hint = 0;
2601 } 2609 }
2602 2610
2603 total_needed += empty_size; 2611search:
2604 block_group = btrfs_lookup_block_group(root->fs_info, search_start);
2605 if (!block_group)
2606 block_group = btrfs_lookup_first_block_group(root->fs_info,
2607 search_start);
2608 space_info = __find_space_info(root->fs_info, data);
2609
2610 down_read(&space_info->groups_sem); 2612 down_read(&space_info->groups_sem);
2611 while (1) { 2613 list_for_each_entry(block_group, &space_info->block_groups, list) {
2612 struct btrfs_free_space *free_space; 2614 struct btrfs_free_space *free_space;
2613 /*
2614 * the only way this happens if our hint points to a block
2615 * group thats not of the proper type, while looping this
2616 * should never happen
2617 */
2618 if (empty_size)
2619 extra_loop = 1;
2620 2615
2621 if (!block_group) 2616 atomic_inc(&block_group->count);
2622 goto new_group_no_lock; 2617 search_start = block_group->key.objectid;
2623 2618
2619have_block_group:
2624 if (unlikely(!block_group->cached)) { 2620 if (unlikely(!block_group->cached)) {
2625 mutex_lock(&block_group->cache_mutex); 2621 mutex_lock(&block_group->cache_mutex);
2626 ret = cache_block_group(root, block_group); 2622 ret = cache_block_group(root, block_group);
2627 mutex_unlock(&block_group->cache_mutex); 2623 mutex_unlock(&block_group->cache_mutex);
2628 if (ret) 2624 if (ret) {
2625 put_block_group(block_group);
2629 break; 2626 break;
2627 }
2630 } 2628 }
2631 2629
2632 mutex_lock(&block_group->alloc_mutex); 2630 mutex_lock(&block_group->alloc_mutex);
2633 if (unlikely(!block_group_bits(block_group, data)))
2634 goto new_group;
2635 2631
2636 if (unlikely(block_group->ro)) 2632 if (unlikely(block_group->ro))
2637 goto new_group; 2633 goto loop;
2638 2634
2639 free_space = btrfs_find_free_space(block_group, search_start, 2635 free_space = btrfs_find_free_space(block_group, search_start,
2640 total_needed); 2636 total_needed);
2641 if (free_space) { 2637 if (!free_space)
2642 u64 start = block_group->key.objectid; 2638 goto loop;
2643 u64 end = block_group->key.objectid +
2644 block_group->key.offset;
2645 2639
2646 search_start = stripe_align(root, free_space->offset); 2640 search_start = stripe_align(root, free_space->offset);
2647 2641
2648 /* move on to the next group */ 2642 /* move on to the next group */
2649 if (search_start + num_bytes >= search_end) 2643 if (search_start + num_bytes >= search_end)
2650 goto new_group; 2644 goto loop;
2651 2645
2652 /* move on to the next group */ 2646 /* move on to the next group */
2653 if (search_start + num_bytes > end) 2647 if (search_start + num_bytes >
2654 goto new_group; 2648 block_group->key.objectid + block_group->key.offset)
2649 goto loop;
2655 2650
2656 if (last_wanted && search_start != last_wanted) { 2651 if (using_hint && search_start > hint_byte)
2657 total_needed += empty_cluster; 2652 goto loop;
2658 empty_size += empty_cluster;
2659 last_wanted = 0;
2660 /*
2661 * if search_start is still in this block group
2662 * then we just re-search this block group
2663 */
2664 if (search_start >= start &&
2665 search_start < end) {
2666 mutex_unlock(&block_group->alloc_mutex);
2667 continue;
2668 }
2669 2653
2670 /* else we go to the next block group */ 2654 if (exclude_nr > 0 &&
2671 goto new_group; 2655 (search_start + num_bytes > exclude_start &&
2672 } 2656 search_start < exclude_start + exclude_nr)) {
2657 search_start = exclude_start + exclude_nr;
2673 2658
2674 if (exclude_nr > 0 && 2659 /*
2675 (search_start + num_bytes > exclude_start && 2660 * if search_start is still in this block group
2676 search_start < exclude_start + exclude_nr)) { 2661 * then we just re-search this block group
2677 search_start = exclude_start + exclude_nr; 2662 */
2678 /* 2663 if (search_start >= block_group->key.objectid &&
2679 * if search_start is still in this block group 2664 search_start < (block_group->key.objectid +
2680 * then we just re-search this block group 2665 block_group->key.offset)) {
2681 */ 2666 mutex_unlock(&block_group->alloc_mutex);
2682 if (search_start >= start && 2667 goto have_block_group;
2683 search_start < end) {
2684 mutex_unlock(&block_group->alloc_mutex);
2685 last_wanted = 0;
2686 continue;
2687 }
2688
2689 /* else we go to the next block group */
2690 goto new_group;
2691 } 2668 }
2669 goto loop;
2670 }
2692 2671
2693 ins->objectid = search_start; 2672 ins->objectid = search_start;
2694 ins->offset = num_bytes; 2673 ins->offset = num_bytes;
2695 2674
2696 btrfs_remove_free_space_lock(block_group, search_start, 2675 btrfs_remove_free_space_lock(block_group, search_start,
2697 num_bytes); 2676 num_bytes);
2698 /* we are all good, lets return */ 2677 /* we are all good, lets return */
2699 mutex_unlock(&block_group->alloc_mutex); 2678 mutex_unlock(&block_group->alloc_mutex);
2700 break; 2679 break;
2701 } 2680loop:
2702new_group:
2703 mutex_unlock(&block_group->alloc_mutex); 2681 mutex_unlock(&block_group->alloc_mutex);
2704 put_block_group(block_group); 2682 put_block_group(block_group);
2705 block_group = NULL; 2683 if (using_hint) {
2706new_group_no_lock: 2684 empty_size += empty_cluster;
2707 /* don't try to compare new allocations against the 2685 total_needed += empty_cluster;
2708 * last allocation any more 2686 using_hint = 0;
2709 */ 2687 up_read(&space_info->groups_sem);
2710 last_wanted = 0; 2688 goto search;
2711
2712 /*
2713 * Here's how this works.
2714 * loop == 0: we were searching a block group via a hint
2715 * and didn't find anything, so we start at
2716 * the head of the block groups and keep searching
2717 * loop == 1: we're searching through all of the block groups
2718 * if we hit the head again we have searched
2719 * all of the block groups for this space and we
2720 * need to try and allocate, if we cant error out.
2721 * loop == 2: we allocated more space and are looping through
2722 * all of the block groups again.
2723 */
2724 if (loop == 0) {
2725 head = &space_info->block_groups;
2726 cur = head->next;
2727 loop++;
2728 } else if (loop == 1 && cur == head) {
2729 int keep_going;
2730
2731 /* at this point we give up on the empty_size
2732 * allocations and just try to allocate the min
2733 * space.
2734 *
2735 * The extra_loop field was set if an empty_size
2736 * allocation was attempted above, and if this
2737 * is try we need to try the loop again without
2738 * the additional empty_size.
2739 */
2740 total_needed -= empty_size;
2741 empty_size = 0;
2742 keep_going = extra_loop;
2743 loop++;
2744
2745 if (allowed_chunk_alloc && !chunk_alloc_done) {
2746 up_read(&space_info->groups_sem);
2747 ret = do_chunk_alloc(trans, root, num_bytes +
2748 2 * 1024 * 1024, data, 1);
2749 down_read(&space_info->groups_sem);
2750 if (ret < 0)
2751 goto loop_check;
2752 head = &space_info->block_groups;
2753 /*
2754 * we've allocated a new chunk, keep
2755 * trying
2756 */
2757 keep_going = 1;
2758 chunk_alloc_done = 1;
2759 } else if (!allowed_chunk_alloc) {
2760 space_info->force_alloc = 1;
2761 }
2762loop_check:
2763 if (keep_going) {
2764 cur = head->next;
2765 extra_loop = 0;
2766 } else {
2767 break;
2768 }
2769 } else if (cur == head) {
2770 break;
2771 } 2689 }
2690 }
2691 up_read(&space_info->groups_sem);
2772 2692
2773 block_group = list_entry(cur, struct btrfs_block_group_cache, 2693 if (!ins->objectid && (empty_size || allowed_chunk_alloc)) {
2774 list); 2694 int try_again = empty_size;
2775 atomic_inc(&block_group->count);
2776 2695
2777 search_start = block_group->key.objectid; 2696 total_needed -= empty_size;
2778 cur = cur->next; 2697 empty_size = 0;
2698
2699 if (allowed_chunk_alloc) {
2700 ret = do_chunk_alloc(trans, root, num_bytes +
2701 2 * 1024 * 1024, data, 1);
2702 if (!ret)
2703 try_again = 1;
2704 allowed_chunk_alloc = 0;
2705 } else {
2706 space_info->force_alloc = 1;
2707 }
2708
2709 if (try_again)
2710 goto search;
2711 ret = -ENOSPC;
2712 } else if (!ins->objectid) {
2713 ret = -ENOSPC;
2779 } 2714 }
2780 2715
2781 /* we found what we needed */ 2716 /* we found what we needed */
@@ -2785,19 +2720,10 @@ loop_check:
2785 2720
2786 if (last_ptr) 2721 if (last_ptr)
2787 *last_ptr = ins->objectid + ins->offset; 2722 *last_ptr = ins->objectid + ins->offset;
2723 put_block_group(block_group);
2788 ret = 0; 2724 ret = 0;
2789 } else if (!ret) {
2790 printk(KERN_ERR "btrfs searching for %llu bytes, "
2791 "num_bytes %llu, loop %d, allowed_alloc %d\n",
2792 (unsigned long long)total_needed,
2793 (unsigned long long)num_bytes,
2794 loop, allowed_chunk_alloc);
2795 ret = -ENOSPC;
2796 } 2725 }
2797 if (block_group)
2798 put_block_group(block_group);
2799 2726
2800 up_read(&space_info->groups_sem);
2801 return ret; 2727 return ret;
2802} 2728}
2803 2729