diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-02-01 14:51:59 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:00 -0400 |
commit | 80ea96b1f3bd2431e0d71c9df6ab45c3de0c5840 (patch) | |
tree | 5071d30eba0f51c529a99bd16caa96dfe3c50cee /fs/btrfs/extent_io.c | |
parent | 4529ba495c6fd0d79247784d0df55ae6512fa883 (diff) |
Btrfs: Add a lookup cache to the extent state tree
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r-- | fs/btrfs/extent_io.c | 57 |
1 files changed, 40 insertions, 17 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 624aabc3e6f2..5f2fbf2054f2 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -90,6 +90,7 @@ void extent_io_tree_init(struct extent_io_tree *tree, | |||
90 | tree->mapping = mapping; | 90 | tree->mapping = mapping; |
91 | INIT_LIST_HEAD(&tree->buffer_lru); | 91 | INIT_LIST_HEAD(&tree->buffer_lru); |
92 | tree->lru_size = 0; | 92 | tree->lru_size = 0; |
93 | tree->last = NULL; | ||
93 | } | 94 | } |
94 | EXPORT_SYMBOL(extent_io_tree_init); | 95 | EXPORT_SYMBOL(extent_io_tree_init); |
95 | 96 | ||
@@ -158,16 +159,23 @@ static struct rb_node *tree_insert(struct rb_root *root, u64 offset, | |||
158 | return NULL; | 159 | return NULL; |
159 | } | 160 | } |
160 | 161 | ||
161 | static struct rb_node *__tree_search(struct rb_root *root, u64 offset, | 162 | static struct rb_node *__etree_search(struct extent_io_tree *tree, u64 offset, |
162 | struct rb_node **prev_ret, | 163 | struct rb_node **prev_ret, |
163 | struct rb_node **next_ret) | 164 | struct rb_node **next_ret) |
164 | { | 165 | { |
166 | struct rb_root *root = &tree->state; | ||
165 | struct rb_node * n = root->rb_node; | 167 | struct rb_node * n = root->rb_node; |
166 | struct rb_node *prev = NULL; | 168 | struct rb_node *prev = NULL; |
167 | struct rb_node *orig_prev = NULL; | 169 | struct rb_node *orig_prev = NULL; |
168 | struct tree_entry *entry; | 170 | struct tree_entry *entry; |
169 | struct tree_entry *prev_entry = NULL; | 171 | struct tree_entry *prev_entry = NULL; |
170 | 172 | ||
173 | if (tree->last) { | ||
174 | struct extent_state *state; | ||
175 | state = tree->last; | ||
176 | if (state->start <= offset && offset <= state->end) | ||
177 | return &tree->last->rb_node; | ||
178 | } | ||
171 | while(n) { | 179 | while(n) { |
172 | entry = rb_entry(n, struct tree_entry, rb_node); | 180 | entry = rb_entry(n, struct tree_entry, rb_node); |
173 | prev = n; | 181 | prev = n; |
@@ -177,8 +185,10 @@ static struct rb_node *__tree_search(struct rb_root *root, u64 offset, | |||
177 | n = n->rb_left; | 185 | n = n->rb_left; |
178 | else if (offset > entry->end) | 186 | else if (offset > entry->end) |
179 | n = n->rb_right; | 187 | n = n->rb_right; |
180 | else | 188 | else { |
189 | tree->last = rb_entry(n, struct extent_state, rb_node); | ||
181 | return n; | 190 | return n; |
191 | } | ||
182 | } | 192 | } |
183 | 193 | ||
184 | if (prev_ret) { | 194 | if (prev_ret) { |
@@ -202,14 +212,20 @@ static struct rb_node *__tree_search(struct rb_root *root, u64 offset, | |||
202 | return NULL; | 212 | return NULL; |
203 | } | 213 | } |
204 | 214 | ||
205 | static inline struct rb_node *tree_search(struct rb_root *root, u64 offset) | 215 | static inline struct rb_node *tree_search(struct extent_io_tree *tree, |
216 | u64 offset) | ||
206 | { | 217 | { |
207 | struct rb_node *prev = NULL; | 218 | struct rb_node *prev = NULL; |
208 | struct rb_node *ret; | 219 | struct rb_node *ret; |
209 | 220 | ||
210 | ret = __tree_search(root, offset, &prev, NULL); | 221 | ret = __etree_search(tree, offset, &prev, NULL); |
211 | if (!ret) | 222 | if (!ret) { |
223 | if (prev) { | ||
224 | tree->last = rb_entry(prev, struct extent_state, | ||
225 | rb_node); | ||
226 | } | ||
212 | return prev; | 227 | return prev; |
228 | } | ||
213 | return ret; | 229 | return ret; |
214 | } | 230 | } |
215 | 231 | ||
@@ -238,6 +254,8 @@ static int merge_state(struct extent_io_tree *tree, | |||
238 | other->state == state->state) { | 254 | other->state == state->state) { |
239 | state->start = other->start; | 255 | state->start = other->start; |
240 | other->tree = NULL; | 256 | other->tree = NULL; |
257 | if (tree->last == other) | ||
258 | tree->last = NULL; | ||
241 | rb_erase(&other->rb_node, &tree->state); | 259 | rb_erase(&other->rb_node, &tree->state); |
242 | free_extent_state(other); | 260 | free_extent_state(other); |
243 | } | 261 | } |
@@ -249,6 +267,8 @@ static int merge_state(struct extent_io_tree *tree, | |||
249 | other->state == state->state) { | 267 | other->state == state->state) { |
250 | other->start = state->start; | 268 | other->start = state->start; |
251 | state->tree = NULL; | 269 | state->tree = NULL; |
270 | if (tree->last == state) | ||
271 | tree->last = NULL; | ||
252 | rb_erase(&state->rb_node, &tree->state); | 272 | rb_erase(&state->rb_node, &tree->state); |
253 | free_extent_state(state); | 273 | free_extent_state(state); |
254 | } | 274 | } |
@@ -311,6 +331,7 @@ static int insert_state(struct extent_io_tree *tree, | |||
311 | return -EEXIST; | 331 | return -EEXIST; |
312 | } | 332 | } |
313 | state->tree = tree; | 333 | state->tree = tree; |
334 | tree->last = state; | ||
314 | merge_state(tree, state); | 335 | merge_state(tree, state); |
315 | return 0; | 336 | return 0; |
316 | } | 337 | } |
@@ -375,6 +396,8 @@ static int clear_state_bit(struct extent_io_tree *tree, | |||
375 | wake_up(&state->wq); | 396 | wake_up(&state->wq); |
376 | if (delete || state->state == 0) { | 397 | if (delete || state->state == 0) { |
377 | if (state->tree) { | 398 | if (state->tree) { |
399 | if (tree->last == state) | ||
400 | tree->last = NULL; | ||
378 | rb_erase(&state->rb_node, &tree->state); | 401 | rb_erase(&state->rb_node, &tree->state); |
379 | state->tree = NULL; | 402 | state->tree = NULL; |
380 | free_extent_state(state); | 403 | free_extent_state(state); |
@@ -422,7 +445,7 @@ again: | |||
422 | * this search will find the extents that end after | 445 | * this search will find the extents that end after |
423 | * our range starts | 446 | * our range starts |
424 | */ | 447 | */ |
425 | node = tree_search(&tree->state, start); | 448 | node = tree_search(tree, start); |
426 | if (!node) | 449 | if (!node) |
427 | goto out; | 450 | goto out; |
428 | state = rb_entry(node, struct extent_state, rb_node); | 451 | state = rb_entry(node, struct extent_state, rb_node); |
@@ -533,7 +556,7 @@ again: | |||
533 | * this search will find all the extents that end after | 556 | * this search will find all the extents that end after |
534 | * our range starts | 557 | * our range starts |
535 | */ | 558 | */ |
536 | node = tree_search(&tree->state, start); | 559 | node = tree_search(tree, start); |
537 | if (!node) | 560 | if (!node) |
538 | break; | 561 | break; |
539 | 562 | ||
@@ -612,7 +635,7 @@ again: | |||
612 | * this search will find all the extents that end after | 635 | * this search will find all the extents that end after |
613 | * our range starts. | 636 | * our range starts. |
614 | */ | 637 | */ |
615 | node = tree_search(&tree->state, start); | 638 | node = tree_search(tree, start); |
616 | if (!node) { | 639 | if (!node) { |
617 | err = insert_state(tree, prealloc, start, end, bits); | 640 | err = insert_state(tree, prealloc, start, end, bits); |
618 | prealloc = NULL; | 641 | prealloc = NULL; |
@@ -915,7 +938,7 @@ int find_first_extent_bit(struct extent_io_tree *tree, u64 start, | |||
915 | * this search will find all the extents that end after | 938 | * this search will find all the extents that end after |
916 | * our range starts. | 939 | * our range starts. |
917 | */ | 940 | */ |
918 | node = tree_search(&tree->state, start); | 941 | node = tree_search(tree, start); |
919 | if (!node || IS_ERR(node)) { | 942 | if (!node || IS_ERR(node)) { |
920 | goto out; | 943 | goto out; |
921 | } | 944 | } |
@@ -953,7 +976,7 @@ u64 find_lock_delalloc_range(struct extent_io_tree *tree, | |||
953 | * our range starts. | 976 | * our range starts. |
954 | */ | 977 | */ |
955 | search_again: | 978 | search_again: |
956 | node = tree_search(&tree->state, cur_start); | 979 | node = tree_search(tree, cur_start); |
957 | if (!node || IS_ERR(node)) { | 980 | if (!node || IS_ERR(node)) { |
958 | *end = (u64)-1; | 981 | *end = (u64)-1; |
959 | goto out; | 982 | goto out; |
@@ -1041,7 +1064,7 @@ u64 count_range_bits(struct extent_io_tree *tree, | |||
1041 | * this search will find all the extents that end after | 1064 | * this search will find all the extents that end after |
1042 | * our range starts. | 1065 | * our range starts. |
1043 | */ | 1066 | */ |
1044 | node = tree_search(&tree->state, cur_start); | 1067 | node = tree_search(tree, cur_start); |
1045 | if (!node || IS_ERR(node)) { | 1068 | if (!node || IS_ERR(node)) { |
1046 | goto out; | 1069 | goto out; |
1047 | } | 1070 | } |
@@ -1142,7 +1165,7 @@ int set_state_private(struct extent_io_tree *tree, u64 start, u64 private) | |||
1142 | * this search will find all the extents that end after | 1165 | * this search will find all the extents that end after |
1143 | * our range starts. | 1166 | * our range starts. |
1144 | */ | 1167 | */ |
1145 | node = tree_search(&tree->state, start); | 1168 | node = tree_search(tree, start); |
1146 | if (!node || IS_ERR(node)) { | 1169 | if (!node || IS_ERR(node)) { |
1147 | ret = -ENOENT; | 1170 | ret = -ENOENT; |
1148 | goto out; | 1171 | goto out; |
@@ -1169,7 +1192,7 @@ int get_state_private(struct extent_io_tree *tree, u64 start, u64 *private) | |||
1169 | * this search will find all the extents that end after | 1192 | * this search will find all the extents that end after |
1170 | * our range starts. | 1193 | * our range starts. |
1171 | */ | 1194 | */ |
1172 | node = tree_search(&tree->state, start); | 1195 | node = tree_search(tree, start); |
1173 | if (!node || IS_ERR(node)) { | 1196 | if (!node || IS_ERR(node)) { |
1174 | ret = -ENOENT; | 1197 | ret = -ENOENT; |
1175 | goto out; | 1198 | goto out; |
@@ -1200,7 +1223,7 @@ int test_range_bit(struct extent_io_tree *tree, u64 start, u64 end, | |||
1200 | unsigned long flags; | 1223 | unsigned long flags; |
1201 | 1224 | ||
1202 | spin_lock_irqsave(&tree->lock, flags); | 1225 | spin_lock_irqsave(&tree->lock, flags); |
1203 | node = tree_search(&tree->state, start); | 1226 | node = tree_search(tree, start); |
1204 | while (node && start <= end) { | 1227 | while (node && start <= end) { |
1205 | state = rb_entry(node, struct extent_state, rb_node); | 1228 | state = rb_entry(node, struct extent_state, rb_node); |
1206 | 1229 | ||
@@ -1348,7 +1371,7 @@ static int end_bio_extent_writepage(struct bio *bio, | |||
1348 | spin_lock_irqsave(&tree->lock, flags); | 1371 | spin_lock_irqsave(&tree->lock, flags); |
1349 | if (!state || state->end != end) { | 1372 | if (!state || state->end != end) { |
1350 | state = NULL; | 1373 | state = NULL; |
1351 | node = __tree_search(&tree->state, start, NULL, NULL); | 1374 | node = __etree_search(tree, start, NULL, NULL); |
1352 | if (node) { | 1375 | if (node) { |
1353 | state = rb_entry(node, struct extent_state, | 1376 | state = rb_entry(node, struct extent_state, |
1354 | rb_node); | 1377 | rb_node); |
@@ -1468,7 +1491,7 @@ static int end_bio_extent_readpage(struct bio *bio, | |||
1468 | spin_lock_irqsave(&tree->lock, flags); | 1491 | spin_lock_irqsave(&tree->lock, flags); |
1469 | if (!state || state->end != end) { | 1492 | if (!state || state->end != end) { |
1470 | state = NULL; | 1493 | state = NULL; |
1471 | node = __tree_search(&tree->state, start, NULL, NULL); | 1494 | node = __etree_search(tree, start, NULL, NULL); |
1472 | if (node) { | 1495 | if (node) { |
1473 | state = rb_entry(node, struct extent_state, | 1496 | state = rb_entry(node, struct extent_state, |
1474 | rb_node); | 1497 | rb_node); |
@@ -1631,7 +1654,7 @@ static int submit_one_bio(int rw, struct bio *bio) | |||
1631 | end = start + bvec->bv_len - 1; | 1654 | end = start + bvec->bv_len - 1; |
1632 | 1655 | ||
1633 | spin_lock_irq(&tree->lock); | 1656 | spin_lock_irq(&tree->lock); |
1634 | node = __tree_search(&tree->state, start, NULL, NULL); | 1657 | node = __etree_search(tree, start, NULL, NULL); |
1635 | BUG_ON(!node); | 1658 | BUG_ON(!node); |
1636 | state = rb_entry(node, struct extent_state, rb_node); | 1659 | state = rb_entry(node, struct extent_state, rb_node); |
1637 | while(state->end < end) { | 1660 | while(state->end < end) { |