.. | .. |
---|
4 | 4 | #include <linux/slab.h> |
---|
5 | 5 | #include <linux/spinlock.h> |
---|
6 | 6 | #include "ctree.h" |
---|
| 7 | +#include "volumes.h" |
---|
7 | 8 | #include "extent_map.h" |
---|
8 | 9 | #include "compression.h" |
---|
9 | 10 | |
---|
.. | .. |
---|
34 | 35 | */ |
---|
35 | 36 | void extent_map_tree_init(struct extent_map_tree *tree) |
---|
36 | 37 | { |
---|
37 | | - tree->map = RB_ROOT; |
---|
| 38 | + tree->map = RB_ROOT_CACHED; |
---|
38 | 39 | INIT_LIST_HEAD(&tree->modified_extents); |
---|
39 | 40 | rwlock_init(&tree->lock); |
---|
40 | 41 | } |
---|
.. | .. |
---|
90 | 91 | return start + len; |
---|
91 | 92 | } |
---|
92 | 93 | |
---|
93 | | -static int tree_insert(struct rb_root *root, struct extent_map *em) |
---|
| 94 | +static int tree_insert(struct rb_root_cached *root, struct extent_map *em) |
---|
94 | 95 | { |
---|
95 | | - struct rb_node **p = &root->rb_node; |
---|
| 96 | + struct rb_node **p = &root->rb_root.rb_node; |
---|
96 | 97 | struct rb_node *parent = NULL; |
---|
97 | 98 | struct extent_map *entry = NULL; |
---|
98 | 99 | struct rb_node *orig_parent = NULL; |
---|
99 | 100 | u64 end = range_end(em->start, em->len); |
---|
| 101 | + bool leftmost = true; |
---|
100 | 102 | |
---|
101 | 103 | while (*p) { |
---|
102 | 104 | parent = *p; |
---|
103 | 105 | entry = rb_entry(parent, struct extent_map, rb_node); |
---|
104 | 106 | |
---|
105 | | - if (em->start < entry->start) |
---|
| 107 | + if (em->start < entry->start) { |
---|
106 | 108 | p = &(*p)->rb_left; |
---|
107 | | - else if (em->start >= extent_map_end(entry)) |
---|
| 109 | + } else if (em->start >= extent_map_end(entry)) { |
---|
108 | 110 | p = &(*p)->rb_right; |
---|
109 | | - else |
---|
| 111 | + leftmost = false; |
---|
| 112 | + } else { |
---|
110 | 113 | return -EEXIST; |
---|
| 114 | + } |
---|
111 | 115 | } |
---|
112 | 116 | |
---|
113 | 117 | orig_parent = parent; |
---|
.. | .. |
---|
130 | 134 | return -EEXIST; |
---|
131 | 135 | |
---|
132 | 136 | rb_link_node(&em->rb_node, orig_parent, p); |
---|
133 | | - rb_insert_color(&em->rb_node, root); |
---|
| 137 | + rb_insert_color_cached(&em->rb_node, root, leftmost); |
---|
134 | 138 | return 0; |
---|
135 | 139 | } |
---|
136 | 140 | |
---|
.. | .. |
---|
207 | 211 | if (!list_empty(&prev->list) || !list_empty(&next->list)) |
---|
208 | 212 | return 0; |
---|
209 | 213 | |
---|
| 214 | + ASSERT(next->block_start != EXTENT_MAP_DELALLOC && |
---|
| 215 | + prev->block_start != EXTENT_MAP_DELALLOC); |
---|
| 216 | + |
---|
| 217 | + if (prev->map_lookup || next->map_lookup) |
---|
| 218 | + ASSERT(test_bit(EXTENT_FLAG_FS_MAPPING, &prev->flags) && |
---|
| 219 | + test_bit(EXTENT_FLAG_FS_MAPPING, &next->flags)); |
---|
| 220 | + |
---|
210 | 221 | if (extent_map_end(prev) == next->start && |
---|
211 | 222 | prev->flags == next->flags && |
---|
212 | | - prev->bdev == next->bdev && |
---|
| 223 | + prev->map_lookup == next->map_lookup && |
---|
213 | 224 | ((next->block_start == EXTENT_MAP_HOLE && |
---|
214 | 225 | prev->block_start == EXTENT_MAP_HOLE) || |
---|
215 | 226 | (next->block_start == EXTENT_MAP_INLINE && |
---|
216 | 227 | prev->block_start == EXTENT_MAP_INLINE) || |
---|
217 | | - (next->block_start == EXTENT_MAP_DELALLOC && |
---|
218 | | - prev->block_start == EXTENT_MAP_DELALLOC) || |
---|
219 | 228 | (next->block_start < EXTENT_MAP_LAST_BYTE - 1 && |
---|
220 | 229 | next->block_start == extent_map_block_end(prev)))) { |
---|
221 | 230 | return 1; |
---|
.. | .. |
---|
253 | 262 | em->mod_start = merge->mod_start; |
---|
254 | 263 | em->generation = max(em->generation, merge->generation); |
---|
255 | 264 | |
---|
256 | | - rb_erase(&merge->rb_node, &tree->map); |
---|
| 265 | + rb_erase_cached(&merge->rb_node, &tree->map); |
---|
257 | 266 | RB_CLEAR_NODE(&merge->rb_node); |
---|
258 | 267 | free_extent_map(merge); |
---|
259 | 268 | } |
---|
.. | .. |
---|
265 | 274 | if (rb && mergable_maps(em, merge)) { |
---|
266 | 275 | em->len += merge->len; |
---|
267 | 276 | em->block_len += merge->block_len; |
---|
268 | | - rb_erase(&merge->rb_node, &tree->map); |
---|
| 277 | + rb_erase_cached(&merge->rb_node, &tree->map); |
---|
269 | 278 | RB_CLEAR_NODE(&merge->rb_node); |
---|
270 | 279 | em->mod_len = (merge->mod_start + merge->mod_len) - em->mod_start; |
---|
271 | 280 | em->generation = max(em->generation, merge->generation); |
---|
.. | .. |
---|
344 | 353 | try_merge_map(tree, em); |
---|
345 | 354 | } |
---|
346 | 355 | |
---|
| 356 | +static void extent_map_device_set_bits(struct extent_map *em, unsigned bits) |
---|
| 357 | +{ |
---|
| 358 | + struct map_lookup *map = em->map_lookup; |
---|
| 359 | + u64 stripe_size = em->orig_block_len; |
---|
| 360 | + int i; |
---|
| 361 | + |
---|
| 362 | + for (i = 0; i < map->num_stripes; i++) { |
---|
| 363 | + struct btrfs_bio_stripe *stripe = &map->stripes[i]; |
---|
| 364 | + struct btrfs_device *device = stripe->dev; |
---|
| 365 | + |
---|
| 366 | + set_extent_bits_nowait(&device->alloc_state, stripe->physical, |
---|
| 367 | + stripe->physical + stripe_size - 1, bits); |
---|
| 368 | + } |
---|
| 369 | +} |
---|
| 370 | + |
---|
| 371 | +static void extent_map_device_clear_bits(struct extent_map *em, unsigned bits) |
---|
| 372 | +{ |
---|
| 373 | + struct map_lookup *map = em->map_lookup; |
---|
| 374 | + u64 stripe_size = em->orig_block_len; |
---|
| 375 | + int i; |
---|
| 376 | + |
---|
| 377 | + for (i = 0; i < map->num_stripes; i++) { |
---|
| 378 | + struct btrfs_bio_stripe *stripe = &map->stripes[i]; |
---|
| 379 | + struct btrfs_device *device = stripe->dev; |
---|
| 380 | + |
---|
| 381 | + __clear_extent_bit(&device->alloc_state, stripe->physical, |
---|
| 382 | + stripe->physical + stripe_size - 1, bits, |
---|
| 383 | + 0, 0, NULL, GFP_NOWAIT, NULL); |
---|
| 384 | + } |
---|
| 385 | +} |
---|
| 386 | + |
---|
347 | 387 | /** |
---|
348 | 388 | * add_extent_mapping - add new extent map to the extent tree |
---|
349 | 389 | * @tree: tree to insert new map in |
---|
.. | .. |
---|
359 | 399 | { |
---|
360 | 400 | int ret = 0; |
---|
361 | 401 | |
---|
| 402 | + lockdep_assert_held_write(&tree->lock); |
---|
| 403 | + |
---|
362 | 404 | ret = tree_insert(&tree->map, em); |
---|
363 | 405 | if (ret) |
---|
364 | 406 | goto out; |
---|
365 | 407 | |
---|
366 | 408 | setup_extent_mapping(tree, em, modified); |
---|
| 409 | + if (test_bit(EXTENT_FLAG_FS_MAPPING, &em->flags)) { |
---|
| 410 | + extent_map_device_set_bits(em, CHUNK_ALLOCATED); |
---|
| 411 | + extent_map_device_clear_bits(em, CHUNK_TRIMMED); |
---|
| 412 | + } |
---|
367 | 413 | out: |
---|
368 | 414 | return ret; |
---|
369 | 415 | } |
---|
.. | .. |
---|
378 | 424 | struct rb_node *next = NULL; |
---|
379 | 425 | u64 end = range_end(start, len); |
---|
380 | 426 | |
---|
381 | | - rb_node = __tree_search(&tree->map, start, &prev, &next); |
---|
| 427 | + rb_node = __tree_search(&tree->map.rb_root, start, &prev, &next); |
---|
382 | 428 | if (!rb_node) { |
---|
383 | 429 | if (prev) |
---|
384 | 430 | rb_node = prev; |
---|
.. | .. |
---|
439 | 485 | * Removes @em from @tree. No reference counts are dropped, and no checks |
---|
440 | 486 | * are done to see if the range is in use |
---|
441 | 487 | */ |
---|
442 | | -int remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em) |
---|
| 488 | +void remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em) |
---|
443 | 489 | { |
---|
444 | | - int ret = 0; |
---|
445 | | - |
---|
446 | 490 | WARN_ON(test_bit(EXTENT_FLAG_PINNED, &em->flags)); |
---|
447 | | - rb_erase(&em->rb_node, &tree->map); |
---|
| 491 | + rb_erase_cached(&em->rb_node, &tree->map); |
---|
448 | 492 | if (!test_bit(EXTENT_FLAG_LOGGING, &em->flags)) |
---|
449 | 493 | list_del_init(&em->list); |
---|
| 494 | + if (test_bit(EXTENT_FLAG_FS_MAPPING, &em->flags)) |
---|
| 495 | + extent_map_device_clear_bits(em, CHUNK_ALLOCATED); |
---|
450 | 496 | RB_CLEAR_NODE(&em->rb_node); |
---|
451 | | - return ret; |
---|
452 | 497 | } |
---|
453 | 498 | |
---|
454 | 499 | void replace_extent_mapping(struct extent_map_tree *tree, |
---|
.. | .. |
---|
460 | 505 | ASSERT(extent_map_in_tree(cur)); |
---|
461 | 506 | if (!test_bit(EXTENT_FLAG_LOGGING, &cur->flags)) |
---|
462 | 507 | list_del_init(&cur->list); |
---|
463 | | - rb_replace_node(&cur->rb_node, &new->rb_node, &tree->map); |
---|
| 508 | + rb_replace_node_cached(&cur->rb_node, &new->rb_node, &tree->map); |
---|
464 | 509 | RB_CLEAR_NODE(&cur->rb_node); |
---|
465 | 510 | |
---|
466 | 511 | setup_extent_mapping(tree, new, modified); |
---|
.. | .. |
---|
486 | 531 | return container_of(prev, struct extent_map, rb_node); |
---|
487 | 532 | } |
---|
488 | 533 | |
---|
489 | | -/* helper for btfs_get_extent. Given an existing extent in the tree, |
---|
| 534 | +/* |
---|
| 535 | + * Helper for btrfs_get_extent. Given an existing extent in the tree, |
---|
490 | 536 | * the existing extent is the nearest extent to map_start, |
---|
491 | 537 | * and an extent that you want to insert, deal with overlap and insert |
---|
492 | 538 | * the best fitted new extent into the tree. |
---|