diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-11-27 11:16:35 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:58 -0400 |
commit | ca6646264b7dab662d84435441164bb2a8e8885a (patch) | |
tree | 166c8be6d3b941fac96bceaea1db8d4616d7442c | |
parent | 448d640b668dae3928591e83f2bf4ca9f4c06e52 (diff) |
Btrfs: Add efficient dirty accounting to the extent_map tree
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/btrfs/disk-io.c | 7 | ||||
-rw-r--r-- | fs/btrfs/extent_map.c | 32 | ||||
-rw-r--r-- | fs/btrfs/extent_map.h | 1 |
3 files changed, 36 insertions, 4 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index de0552532d23..eef4ab56b9ca 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -210,7 +210,7 @@ static int btree_writepages(struct address_space *mapping, | |||
210 | { | 210 | { |
211 | struct extent_map_tree *tree; | 211 | struct extent_map_tree *tree; |
212 | tree = &BTRFS_I(mapping->host)->extent_tree; | 212 | tree = &BTRFS_I(mapping->host)->extent_tree; |
213 | if (wbc->sync_mode == WB_SYNC_NONE && current_is_pdflush()) { | 213 | if (wbc->sync_mode == WB_SYNC_NONE) { |
214 | u64 num_dirty; | 214 | u64 num_dirty; |
215 | u64 start = 0; | 215 | u64 start = 0; |
216 | unsigned long thresh = 96 * 1024 * 1024; | 216 | unsigned long thresh = 96 * 1024 * 1024; |
@@ -218,6 +218,11 @@ static int btree_writepages(struct address_space *mapping, | |||
218 | if (wbc->for_kupdate) | 218 | if (wbc->for_kupdate) |
219 | return 0; | 219 | return 0; |
220 | 220 | ||
221 | if (current_is_pdflush()) { | ||
222 | thresh = 96 * 1024 * 1024; | ||
223 | } else { | ||
224 | thresh = 8 * 1024 * 1024; | ||
225 | } | ||
221 | num_dirty = count_range_bits(tree, &start, thresh, EXTENT_DIRTY); | 226 | num_dirty = count_range_bits(tree, &start, thresh, EXTENT_DIRTY); |
222 | if (num_dirty < thresh) { | 227 | if (num_dirty < thresh) { |
223 | return 0; | 228 | return 0; |
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index b6a4974ecc23..06e437723dc3 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c | |||
@@ -42,6 +42,7 @@ struct extent_page_data { | |||
42 | struct extent_map_tree *tree; | 42 | struct extent_map_tree *tree; |
43 | get_extent_t *get_extent; | 43 | get_extent_t *get_extent; |
44 | }; | 44 | }; |
45 | |||
45 | int __init extent_map_init(void) | 46 | int __init extent_map_init(void) |
46 | { | 47 | { |
47 | extent_map_cache = btrfs_cache_create("extent_map", | 48 | extent_map_cache = btrfs_cache_create("extent_map", |
@@ -94,6 +95,7 @@ void extent_map_tree_init(struct extent_map_tree *tree, | |||
94 | tree->map.rb_node = NULL; | 95 | tree->map.rb_node = NULL; |
95 | tree->state.rb_node = NULL; | 96 | tree->state.rb_node = NULL; |
96 | tree->ops = NULL; | 97 | tree->ops = NULL; |
98 | tree->dirty_bytes = 0; | ||
97 | rwlock_init(&tree->lock); | 99 | rwlock_init(&tree->lock); |
98 | spin_lock_init(&tree->lru_lock); | 100 | spin_lock_init(&tree->lru_lock); |
99 | tree->mapping = mapping; | 101 | tree->mapping = mapping; |
@@ -414,6 +416,8 @@ static int insert_state(struct extent_map_tree *tree, | |||
414 | printk("end < start %Lu %Lu\n", end, start); | 416 | printk("end < start %Lu %Lu\n", end, start); |
415 | WARN_ON(1); | 417 | WARN_ON(1); |
416 | } | 418 | } |
419 | if (bits & EXTENT_DIRTY) | ||
420 | tree->dirty_bytes += end - start + 1; | ||
417 | state->state |= bits; | 421 | state->state |= bits; |
418 | state->start = start; | 422 | state->start = start; |
419 | state->end = end; | 423 | state->end = end; |
@@ -476,6 +480,12 @@ static int clear_state_bit(struct extent_map_tree *tree, | |||
476 | int delete) | 480 | int delete) |
477 | { | 481 | { |
478 | int ret = state->state & bits; | 482 | int ret = state->state & bits; |
483 | |||
484 | if ((bits & EXTENT_DIRTY) && (state->state & EXTENT_DIRTY)) { | ||
485 | u64 range = state->end - state->start + 1; | ||
486 | WARN_ON(range > tree->dirty_bytes); | ||
487 | tree->dirty_bytes -= range; | ||
488 | } | ||
479 | state->state &= ~bits; | 489 | state->state &= ~bits; |
480 | if (wake) | 490 | if (wake) |
481 | wake_up(&state->wq); | 491 | wake_up(&state->wq); |
@@ -668,6 +678,17 @@ out: | |||
668 | } | 678 | } |
669 | EXPORT_SYMBOL(wait_extent_bit); | 679 | EXPORT_SYMBOL(wait_extent_bit); |
670 | 680 | ||
681 | static void set_state_bits(struct extent_map_tree *tree, | ||
682 | struct extent_state *state, | ||
683 | int bits) | ||
684 | { | ||
685 | if ((bits & EXTENT_DIRTY) && !(state->state & EXTENT_DIRTY)) { | ||
686 | u64 range = state->end - state->start + 1; | ||
687 | tree->dirty_bytes += range; | ||
688 | } | ||
689 | state->state |= bits; | ||
690 | } | ||
691 | |||
671 | /* | 692 | /* |
672 | * set some bits on a range in the tree. This may require allocations | 693 | * set some bits on a range in the tree. This may require allocations |
673 | * or sleeping, so the gfp mask is used to indicate what is allowed. | 694 | * or sleeping, so the gfp mask is used to indicate what is allowed. |
@@ -727,7 +748,7 @@ again: | |||
727 | err = -EEXIST; | 748 | err = -EEXIST; |
728 | goto out; | 749 | goto out; |
729 | } | 750 | } |
730 | state->state |= bits; | 751 | set_state_bits(tree, state, bits); |
731 | start = state->end + 1; | 752 | start = state->end + 1; |
732 | merge_state(tree, state); | 753 | merge_state(tree, state); |
733 | goto search_again; | 754 | goto search_again; |
@@ -762,7 +783,7 @@ again: | |||
762 | if (err) | 783 | if (err) |
763 | goto out; | 784 | goto out; |
764 | if (state->end <= end) { | 785 | if (state->end <= end) { |
765 | state->state |= bits; | 786 | set_state_bits(tree, state, bits); |
766 | start = state->end + 1; | 787 | start = state->end + 1; |
767 | merge_state(tree, state); | 788 | merge_state(tree, state); |
768 | } else { | 789 | } else { |
@@ -808,7 +829,7 @@ again: | |||
808 | err = split_state(tree, state, prealloc, end + 1); | 829 | err = split_state(tree, state, prealloc, end + 1); |
809 | BUG_ON(err == -EEXIST); | 830 | BUG_ON(err == -EEXIST); |
810 | 831 | ||
811 | prealloc->state |= bits; | 832 | set_state_bits(tree, prealloc, bits); |
812 | merge_state(tree, prealloc); | 833 | merge_state(tree, prealloc); |
813 | prealloc = NULL; | 834 | prealloc = NULL; |
814 | goto out; | 835 | goto out; |
@@ -1116,6 +1137,11 @@ u64 count_range_bits(struct extent_map_tree *tree, | |||
1116 | int found = 0; | 1137 | int found = 0; |
1117 | 1138 | ||
1118 | write_lock_irq(&tree->lock); | 1139 | write_lock_irq(&tree->lock); |
1140 | if (bits == EXTENT_DIRTY) { | ||
1141 | *start = 0; | ||
1142 | total_bytes = tree->dirty_bytes; | ||
1143 | goto out; | ||
1144 | } | ||
1119 | /* | 1145 | /* |
1120 | * this search will find all the extents that end after | 1146 | * this search will find all the extents that end after |
1121 | * our range starts. | 1147 | * our range starts. |
diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h index 13c562f7cb6f..2ffc0c76338c 100644 --- a/fs/btrfs/extent_map.h +++ b/fs/btrfs/extent_map.h | |||
@@ -40,6 +40,7 @@ struct extent_map_tree { | |||
40 | struct rb_root map; | 40 | struct rb_root map; |
41 | struct rb_root state; | 41 | struct rb_root state; |
42 | struct address_space *mapping; | 42 | struct address_space *mapping; |
43 | u64 dirty_bytes; | ||
43 | rwlock_t lock; | 44 | rwlock_t lock; |
44 | struct extent_map_ops *ops; | 45 | struct extent_map_ops *ops; |
45 | spinlock_t lru_lock; | 46 | spinlock_t lru_lock; |