diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/extent-tree.c | 256 |
1 files changed, 91 insertions, 165 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 2c214781fee..daff751ea6e 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; | 2611 | search: |
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 | ||
2619 | have_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 | } | 2680 | loop: |
2702 | new_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) { |
2706 | new_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 | } | ||
2762 | loop_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 | ||