aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent_io.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2009-09-23 19:51:09 -0400
committerChris Mason <chris.mason@oracle.com>2009-09-23 20:30:52 -0400
commit42daec299b8b6b9605976d0ee1266b343a31cbcc (patch)
tree6813d5d2b30c346413e329f0ad4d6f2262991311 /fs/btrfs/extent_io.c
parent7ce618db9878689f87897b673fa3329070860fc7 (diff)
Btrfs: fix errors handling cached state in set/clear_extent_bit
Both set and clear_extent_bit allow passing a cached state struct to reduce rbtree search times. clear_extent_bit was improperly bypassing some of the checks around making sure the extent state fields were correct for a given operation. The fix used here (from Yan Zheng) is to use the hit_next goto target instead of jumping all the way down to start clearing bits without making sure the cached state was exactly correct for the operation we were doing. This also fixes up the setting of the start variable for both ops in the case where we find an overlapping extent that begins before the range we want to change. In both cases we were incorrectly going backwards from the original requested change. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r--fs/btrfs/extent_io.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 7e16c6d8153f..b9506548853b 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -495,11 +495,11 @@ again:
495 if (cached_state) { 495 if (cached_state) {
496 cached = *cached_state; 496 cached = *cached_state;
497 *cached_state = NULL; 497 *cached_state = NULL;
498 if (cached->tree && cached->start == start) { 498 cached_state = NULL;
499 if (cached && cached->tree && cached->start == start) {
499 atomic_dec(&cached->refs); 500 atomic_dec(&cached->refs);
500 state = cached; 501 state = cached;
501 last_end = state->end; 502 goto hit_next;
502 goto found;
503 } 503 }
504 free_extent_state(cached); 504 free_extent_state(cached);
505 } 505 }
@@ -547,8 +547,6 @@ hit_next:
547 if (last_end == (u64)-1) 547 if (last_end == (u64)-1)
548 goto out; 548 goto out;
549 start = last_end + 1; 549 start = last_end + 1;
550 } else {
551 start = state->start;
552 } 550 }
553 goto search_again; 551 goto search_again;
554 } 552 }
@@ -566,16 +564,18 @@ hit_next:
566 564
567 if (wake) 565 if (wake)
568 wake_up(&state->wq); 566 wake_up(&state->wq);
567
569 set |= clear_state_bit(tree, prealloc, bits, 568 set |= clear_state_bit(tree, prealloc, bits,
570 wake, delete); 569 wake, delete);
571 prealloc = NULL; 570 prealloc = NULL;
572 goto out; 571 goto out;
573 } 572 }
574found: 573
575 if (state->end < end && prealloc && !need_resched()) 574 if (state->end < end && prealloc && !need_resched())
576 next_node = rb_next(&state->rb_node); 575 next_node = rb_next(&state->rb_node);
577 else 576 else
578 next_node = NULL; 577 next_node = NULL;
578
579 set |= clear_state_bit(tree, state, bits, wake, delete); 579 set |= clear_state_bit(tree, state, bits, wake, delete);
580 if (last_end == (u64)-1) 580 if (last_end == (u64)-1)
581 goto out; 581 goto out;
@@ -712,6 +712,7 @@ static int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
712 int err = 0; 712 int err = 0;
713 u64 last_start; 713 u64 last_start;
714 u64 last_end; 714 u64 last_end;
715
715again: 716again:
716 if (!prealloc && (mask & __GFP_WAIT)) { 717 if (!prealloc && (mask & __GFP_WAIT)) {
717 prealloc = alloc_extent_state(mask); 718 prealloc = alloc_extent_state(mask);
@@ -756,6 +757,7 @@ hit_next:
756 err = -EEXIST; 757 err = -EEXIST;
757 goto out; 758 goto out;
758 } 759 }
760
759 set_state_bits(tree, state, bits); 761 set_state_bits(tree, state, bits);
760 cache_state(state, cached_state); 762 cache_state(state, cached_state);
761 merge_state(tree, state); 763 merge_state(tree, state);
@@ -809,8 +811,6 @@ hit_next:
809 if (last_end == (u64)-1) 811 if (last_end == (u64)-1)
810 goto out; 812 goto out;
811 start = last_end + 1; 813 start = last_end + 1;
812 } else {
813 start = state->start;
814 } 814 }
815 goto search_again; 815 goto search_again;
816 } 816 }