diff options
| -rw-r--r-- | fs/btrfs/extent_io.c | 125 | ||||
| -rw-r--r-- | fs/btrfs/extent_io.h | 5 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 6 |
3 files changed, 100 insertions, 36 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 7c70613eb72c..c7a5e860fe21 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
| @@ -471,10 +471,14 @@ static int clear_state_bit(struct extent_io_tree *tree, | |||
| 471 | * bits were already set, or zero if none of the bits were already set. | 471 | * bits were already set, or zero if none of the bits were already set. |
| 472 | */ | 472 | */ |
| 473 | int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, | 473 | int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, |
| 474 | int bits, int wake, int delete, gfp_t mask) | 474 | int bits, int wake, int delete, |
| 475 | struct extent_state **cached_state, | ||
| 476 | gfp_t mask) | ||
| 475 | { | 477 | { |
| 476 | struct extent_state *state; | 478 | struct extent_state *state; |
| 479 | struct extent_state *cached; | ||
| 477 | struct extent_state *prealloc = NULL; | 480 | struct extent_state *prealloc = NULL; |
| 481 | struct rb_node *next_node; | ||
| 478 | struct rb_node *node; | 482 | struct rb_node *node; |
| 479 | u64 last_end; | 483 | u64 last_end; |
| 480 | int err; | 484 | int err; |
| @@ -488,6 +492,17 @@ again: | |||
| 488 | } | 492 | } |
| 489 | 493 | ||
| 490 | spin_lock(&tree->lock); | 494 | spin_lock(&tree->lock); |
| 495 | if (cached_state) { | ||
| 496 | cached = *cached_state; | ||
| 497 | *cached_state = NULL; | ||
| 498 | if (cached->tree && cached->start == start) { | ||
| 499 | atomic_dec(&cached->refs); | ||
| 500 | state = cached; | ||
| 501 | last_end = state->end; | ||
| 502 | goto found; | ||
| 503 | } | ||
| 504 | free_extent_state(cached); | ||
| 505 | } | ||
| 491 | /* | 506 | /* |
| 492 | * this search will find the extents that end after | 507 | * this search will find the extents that end after |
| 493 | * our range starts | 508 | * our range starts |
| @@ -496,6 +511,7 @@ again: | |||
| 496 | if (!node) | 511 | if (!node) |
| 497 | goto out; | 512 | goto out; |
| 498 | state = rb_entry(node, struct extent_state, rb_node); | 513 | state = rb_entry(node, struct extent_state, rb_node); |
| 514 | hit_next: | ||
| 499 | if (state->start > end) | 515 | if (state->start > end) |
| 500 | goto out; | 516 | goto out; |
| 501 | WARN_ON(state->end < start); | 517 | WARN_ON(state->end < start); |
| @@ -555,11 +571,21 @@ again: | |||
| 555 | prealloc = NULL; | 571 | prealloc = NULL; |
| 556 | goto out; | 572 | goto out; |
| 557 | } | 573 | } |
| 558 | 574 | found: | |
| 575 | if (state->end < end && prealloc && !need_resched()) | ||
| 576 | next_node = rb_next(&state->rb_node); | ||
| 577 | else | ||
| 578 | next_node = NULL; | ||
| 559 | set |= clear_state_bit(tree, state, bits, wake, delete); | 579 | set |= clear_state_bit(tree, state, bits, wake, delete); |
| 560 | if (last_end == (u64)-1) | 580 | if (last_end == (u64)-1) |
| 561 | goto out; | 581 | goto out; |
| 562 | start = last_end + 1; | 582 | start = last_end + 1; |
| 583 | if (start <= end && next_node) { | ||
| 584 | state = rb_entry(next_node, struct extent_state, | ||
| 585 | rb_node); | ||
| 586 | if (state->start == start) | ||
| 587 | goto hit_next; | ||
| 588 | } | ||
| 563 | goto search_again; | 589 | goto search_again; |
| 564 | 590 | ||
| 565 | out: | 591 | out: |
| @@ -653,6 +679,17 @@ static void set_state_bits(struct extent_io_tree *tree, | |||
| 653 | state->state |= bits; | 679 | state->state |= bits; |
| 654 | } | 680 | } |
| 655 | 681 | ||
| 682 | static void cache_state(struct extent_state *state, | ||
| 683 | struct extent_state **cached_ptr) | ||
| 684 | { | ||
| 685 | if (cached_ptr && !(*cached_ptr)) { | ||
| 686 | if (state->state & (EXTENT_IOBITS | EXTENT_BOUNDARY)) { | ||
| 687 | *cached_ptr = state; | ||
| 688 | atomic_inc(&state->refs); | ||
| 689 | } | ||
| 690 | } | ||
| 691 | } | ||
| 692 | |||
| 656 | /* | 693 | /* |
| 657 | * set some bits on a range in the tree. This may require allocations or | 694 | * set some bits on a range in the tree. This may require allocations or |
| 658 | * sleeping, so the gfp mask is used to indicate what is allowed. | 695 | * sleeping, so the gfp mask is used to indicate what is allowed. |
| @@ -666,6 +703,7 @@ static void set_state_bits(struct extent_io_tree *tree, | |||
| 666 | 703 | ||
| 667 | static int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, | 704 | static int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, |
| 668 | int bits, int exclusive_bits, u64 *failed_start, | 705 | int bits, int exclusive_bits, u64 *failed_start, |
| 706 | struct extent_state **cached_state, | ||
| 669 | gfp_t mask) | 707 | gfp_t mask) |
| 670 | { | 708 | { |
| 671 | struct extent_state *state; | 709 | struct extent_state *state; |
| @@ -712,6 +750,7 @@ hit_next: | |||
| 712 | goto out; | 750 | goto out; |
| 713 | } | 751 | } |
| 714 | set_state_bits(tree, state, bits); | 752 | set_state_bits(tree, state, bits); |
| 753 | cache_state(state, cached_state); | ||
| 715 | merge_state(tree, state); | 754 | merge_state(tree, state); |
| 716 | if (last_end == (u64)-1) | 755 | if (last_end == (u64)-1) |
| 717 | goto out; | 756 | goto out; |
| @@ -758,6 +797,7 @@ hit_next: | |||
| 758 | goto out; | 797 | goto out; |
| 759 | if (state->end <= end) { | 798 | if (state->end <= end) { |
| 760 | set_state_bits(tree, state, bits); | 799 | set_state_bits(tree, state, bits); |
| 800 | cache_state(state, cached_state); | ||
| 761 | merge_state(tree, state); | 801 | merge_state(tree, state); |
| 762 | if (last_end == (u64)-1) | 802 | if (last_end == (u64)-1) |
| 763 | goto out; | 803 | goto out; |
| @@ -782,6 +822,7 @@ hit_next: | |||
| 782 | this_end = last_start - 1; | 822 | this_end = last_start - 1; |
| 783 | err = insert_state(tree, prealloc, start, this_end, | 823 | err = insert_state(tree, prealloc, start, this_end, |
| 784 | bits); | 824 | bits); |
| 825 | cache_state(prealloc, cached_state); | ||
| 785 | prealloc = NULL; | 826 | prealloc = NULL; |
| 786 | BUG_ON(err == -EEXIST); | 827 | BUG_ON(err == -EEXIST); |
| 787 | if (err) | 828 | if (err) |
| @@ -805,6 +846,7 @@ hit_next: | |||
| 805 | BUG_ON(err == -EEXIST); | 846 | BUG_ON(err == -EEXIST); |
| 806 | 847 | ||
| 807 | set_state_bits(tree, prealloc, bits); | 848 | set_state_bits(tree, prealloc, bits); |
| 849 | cache_state(prealloc, cached_state); | ||
| 808 | merge_state(tree, prealloc); | 850 | merge_state(tree, prealloc); |
| 809 | prealloc = NULL; | 851 | prealloc = NULL; |
| 810 | goto out; | 852 | goto out; |
| @@ -833,26 +875,27 @@ int set_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end, | |||
| 833 | gfp_t mask) | 875 | gfp_t mask) |
| 834 | { | 876 | { |
| 835 | return set_extent_bit(tree, start, end, EXTENT_DIRTY, 0, NULL, | 877 | return set_extent_bit(tree, start, end, EXTENT_DIRTY, 0, NULL, |
| 836 | mask); | 878 | NULL, mask); |
| 837 | } | 879 | } |
| 838 | 880 | ||
| 839 | int set_extent_ordered(struct extent_io_tree *tree, u64 start, u64 end, | 881 | int set_extent_ordered(struct extent_io_tree *tree, u64 start, u64 end, |
| 840 | gfp_t mask) | 882 | gfp_t mask) |
| 841 | { | 883 | { |
| 842 | return set_extent_bit(tree, start, end, EXTENT_ORDERED, 0, NULL, mask); | 884 | return set_extent_bit(tree, start, end, EXTENT_ORDERED, 0, NULL, NULL, |
| 885 | mask); | ||
| 843 | } | 886 | } |
| 844 | 887 | ||
| 845 | int set_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, | 888 | int set_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, |
| 846 | int bits, gfp_t mask) | 889 | int bits, gfp_t mask) |
| 847 | { | 890 | { |
| 848 | return set_extent_bit(tree, start, end, bits, 0, NULL, | 891 | return set_extent_bit(tree, start, end, bits, 0, NULL, |
| 849 | mask); | 892 | NULL, mask); |
| 850 | } | 893 | } |
| 851 | 894 | ||
| 852 | int clear_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, | 895 | int clear_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, |
| 853 | int bits, gfp_t mask) | 896 | int bits, gfp_t mask) |
| 854 | { | 897 | { |
| 855 | return clear_extent_bit(tree, start, end, bits, 0, 0, mask); | 898 | return clear_extent_bit(tree, start, end, bits, 0, 0, NULL, mask); |
| 856 | } | 899 | } |
| 857 | 900 | ||
| 858 | int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end, | 901 | int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end, |
| @@ -860,46 +903,50 @@ int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end, | |||
| 860 | { | 903 | { |
| 861 | return set_extent_bit(tree, start, end, | 904 | return set_extent_bit(tree, start, end, |
| 862 | EXTENT_DELALLOC | EXTENT_DIRTY | EXTENT_UPTODATE, | 905 | EXTENT_DELALLOC | EXTENT_DIRTY | EXTENT_UPTODATE, |
| 863 | 0, NULL, mask); | 906 | 0, NULL, NULL, mask); |
