diff options
author | Liu Bo <bo.liu@linux.alibaba.com> | 2018-08-22 15:51:52 -0400 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2018-10-15 11:23:33 -0400 |
commit | 07e1ce096db3605f3e0c98695df66a51e2be9f05 (patch) | |
tree | 3e4a910cd136c1b6666d3be7e33b826dbd016db6 | |
parent | 03a1d4c891634dd5b98da865fb783e8b22d4d027 (diff) |
Btrfs: extent_map: use rb_first_cached
rb_first_cached() trades an extra pointer "leftmost" for doing the
same job as rb_first() but in O(1).
As evict_inode_truncate_pages() removes all extent mapping by always
looking for the first rb entry, it's helpful to use rb_first_cached
instead.
For more details about the optimization see patch "Btrfs: delayed-refs:
use rb_first_cached for href_root".
Tested-by: Holger Hoffstätte <holger@applied-asynchrony.com>
Signed-off-by: Liu Bo <bo.liu@linux.alibaba.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r-- | fs/btrfs/extent_map.c | 27 | ||||
-rw-r--r-- | fs/btrfs/extent_map.h | 2 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 4 | ||||
-rw-r--r-- | fs/btrfs/tests/extent-map-tests.c | 4 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 4 |
5 files changed, 22 insertions, 19 deletions
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index 2382b949cef8..7eea8b6e2cd3 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c | |||
@@ -34,7 +34,7 @@ void __cold extent_map_exit(void) | |||
34 | */ | 34 | */ |
35 | void extent_map_tree_init(struct extent_map_tree *tree) | 35 | void extent_map_tree_init(struct extent_map_tree *tree) |
36 | { | 36 | { |
37 | tree->map = RB_ROOT; | 37 | tree->map = RB_ROOT_CACHED; |
38 | INIT_LIST_HEAD(&tree->modified_extents); | 38 | INIT_LIST_HEAD(&tree->modified_extents); |
39 | rwlock_init(&tree->lock); | 39 | rwlock_init(&tree->lock); |
40 | } | 40 | } |
@@ -90,24 +90,27 @@ static u64 range_end(u64 start, u64 len) | |||
90 | return start + len; | 90 | return start + len; |
91 | } | 91 | } |
92 | 92 | ||
93 | static int tree_insert(struct rb_root *root, struct extent_map *em) | 93 | static int tree_insert(struct rb_root_cached *root, struct extent_map *em) |
94 | { | 94 | { |
95 | struct rb_node **p = &root->rb_node; | 95 | struct rb_node **p = &root->rb_root.rb_node; |
96 | struct rb_node *parent = NULL; | 96 | struct rb_node *parent = NULL; |
97 | struct extent_map *entry = NULL; | 97 | struct extent_map *entry = NULL; |
98 | struct rb_node *orig_parent = NULL; | 98 | struct rb_node *orig_parent = NULL; |
99 | u64 end = range_end(em->start, em->len); | 99 | u64 end = range_end(em->start, em->len); |
100 | bool leftmost = true; | ||
100 | 101 | ||
101 | while (*p) { | 102 | while (*p) { |
102 | parent = *p; | 103 | parent = *p; |
103 | entry = rb_entry(parent, struct extent_map, rb_node); | 104 | entry = rb_entry(parent, struct extent_map, rb_node); |
104 | 105 | ||
105 | if (em->start < entry->start) | 106 | if (em->start < entry->start) { |
106 | p = &(*p)->rb_left; | 107 | p = &(*p)->rb_left; |
107 | else if (em->start >= extent_map_end(entry)) | 108 | } else if (em->start >= extent_map_end(entry)) { |
108 | p = &(*p)->rb_right; | 109 | p = &(*p)->rb_right; |
109 | else | 110 | leftmost = false; |
111 | } else { | ||
110 | return -EEXIST; | 112 | return -EEXIST; |
113 | } | ||
111 | } | 114 | } |
112 | 115 | ||
113 | orig_parent = parent; | 116 | orig_parent = parent; |
@@ -130,7 +133,7 @@ static int tree_insert(struct rb_root *root, struct extent_map *em) | |||
130 | return -EEXIST; | 133 | return -EEXIST; |
131 | 134 | ||
132 | rb_link_node(&em->rb_node, orig_parent, p); | 135 | rb_link_node(&em->rb_node, orig_parent, p); |
133 | rb_insert_color(&em->rb_node, root); | 136 | rb_insert_color_cached(&em->rb_node, root, leftmost); |
134 | return 0; | 137 | return 0; |
135 | } | 138 | } |
136 | 139 | ||
@@ -242,7 +245,7 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em) | |||
242 | em->mod_start = merge->mod_start; | 245 | em->mod_start = merge->mod_start; |
243 | em->generation = max(em->generation, merge->generation); | 246 | em->generation = max(em->generation, merge->generation); |
244 | 247 | ||
245 | rb_erase(&merge->rb_node, &tree->map); | 248 | rb_erase_cached(&merge->rb_node, &tree->map); |
246 | RB_CLEAR_NODE(&merge->rb_node); | 249 | RB_CLEAR_NODE(&merge->rb_node); |
247 | free_extent_map(merge); | 250 | free_extent_map(merge); |
248 | } | 251 | } |
@@ -254,7 +257,7 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em) | |||
254 | if (rb && mergable_maps(em, merge)) { | 257 | if (rb && mergable_maps(em, merge)) { |
255 | em->len += merge->len; | 258 | em->len += merge->len; |
256 | em->block_len += merge->block_len; | 259 | em->block_len += merge->block_len; |
257 | rb_erase(&merge->rb_node, &tree->map); | 260 | rb_erase_cached(&merge->rb_node, &tree->map); |
258 | RB_CLEAR_NODE(&merge->rb_node); | 261 | RB_CLEAR_NODE(&merge->rb_node); |
259 | em->mod_len = (merge->mod_start + merge->mod_len) - em->mod_start; | 262 | em->mod_len = (merge->mod_start + merge->mod_len) - em->mod_start; |
260 | em->generation = max(em->generation, merge->generation); | 263 | em->generation = max(em->generation, merge->generation); |
@@ -367,7 +370,7 @@ __lookup_extent_mapping(struct extent_map_tree *tree, | |||
367 | struct rb_node *next = NULL; | 370 | struct rb_node *next = NULL; |
368 | u64 end = range_end(start, len); | 371 | u64 end = range_end(start, len); |
369 | 372 | ||
370 | rb_node = __tree_search(&tree->map, start, &prev, &next); | 373 | rb_node = __tree_search(&tree->map.rb_root, start, &prev, &next); |
371 | if (!rb_node) { | 374 | if (!rb_node) { |
372 | if (prev) | 375 | if (prev) |
373 | rb_node = prev; | 376 | rb_node = prev; |
@@ -431,7 +434,7 @@ struct extent_map *search_extent_mapping(struct extent_map_tree *tree, | |||
431 | void remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em) | 434 | void remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em) |
432 | { | 435 | { |
433 | WARN_ON(test_bit(EXTENT_FLAG_PINNED, &em->flags)); | 436 | WARN_ON(test_bit(EXTENT_FLAG_PINNED, &em->flags)); |
434 | rb_erase(&em->rb_node, &tree->map); | 437 | rb_erase_cached(&em->rb_node, &tree->map); |
435 | if (!test_bit(EXTENT_FLAG_LOGGING, &em->flags)) | 438 | if (!test_bit(EXTENT_FLAG_LOGGING, &em->flags)) |
436 | list_del_init(&em->list); | 439 | list_del_init(&em->list); |
437 | RB_CLEAR_NODE(&em->rb_node); | 440 | RB_CLEAR_NODE(&em->rb_node); |
@@ -446,7 +449,7 @@ void replace_extent_mapping(struct extent_map_tree *tree, | |||
446 | ASSERT(extent_map_in_tree(cur)); | 449 | ASSERT(extent_map_in_tree(cur)); |
447 | if (!test_bit(EXTENT_FLAG_LOGGING, &cur->flags)) | 450 | if (!test_bit(EXTENT_FLAG_LOGGING, &cur->flags)) |
448 | list_del_init(&cur->list); | 451 | list_del_init(&cur->list); |
449 | rb_replace_node(&cur->rb_node, &new->rb_node, &tree->map); | 452 | rb_replace_node_cached(&cur->rb_node, &new->rb_node, &tree->map); |
450 | RB_CLEAR_NODE(&cur->rb_node); | 453 | RB_CLEAR_NODE(&cur->rb_node); |
451 | 454 | ||
452 | setup_extent_mapping(tree, new, modified); | 455 | setup_extent_mapping(tree, new, modified); |
diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h index a7ceb30449fc..31977ffd6190 100644 --- a/fs/btrfs/extent_map.h +++ b/fs/btrfs/extent_map.h | |||
@@ -49,7 +49,7 @@ struct extent_map { | |||
49 | }; | 49 | }; |
50 | 50 | ||
51 | struct extent_map_tree { | 51 | struct extent_map_tree { |
52 | struct rb_root map; | 52 | struct rb_root_cached map; |
53 | struct list_head modified_extents; | 53 | struct list_head modified_extents; |
54 | rwlock_t lock; | 54 | rwlock_t lock; |
55 | }; | 55 | }; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 8ba7e5d5071e..dd2140d3e354 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -5222,10 +5222,10 @@ static void evict_inode_truncate_pages(struct inode *inode) | |||
5222 | truncate_inode_pages_final(&inode->i_data); | 5222 | truncate_inode_pages_final(&inode->i_data); |
5223 | 5223 | ||
5224 | write_lock(&map_tree->lock); | 5224 | write_lock(&map_tree->lock); |
5225 | while (!RB_EMPTY_ROOT(&map_tree->map)) { | 5225 | while (!RB_EMPTY_ROOT(&map_tree->map.rb_root)) { |
5226 | struct extent_map *em; | 5226 | struct extent_map *em; |
5227 | 5227 | ||
5228 | node = rb_first(&map_tree->map); | 5228 | node = rb_first_cached(&map_tree->map); |
5229 | em = rb_entry(node, struct extent_map, rb_node); | 5229 | em = rb_entry(node, struct extent_map, rb_node); |
5230 | clear_bit(EXTENT_FLAG_PINNED, &em->flags); | 5230 | clear_bit(EXTENT_FLAG_PINNED, &em->flags); |
5231 | clear_bit(EXTENT_FLAG_LOGGING, &em->flags); | 5231 | clear_bit(EXTENT_FLAG_LOGGING, &em->flags); |
diff --git a/fs/btrfs/tests/extent-map-tests.c b/fs/btrfs/tests/extent-map-tests.c index 385a5316e4bf..bf15d3a7f20e 100644 --- a/fs/btrfs/tests/extent-map-tests.c +++ b/fs/btrfs/tests/extent-map-tests.c | |||
@@ -12,8 +12,8 @@ static void free_extent_map_tree(struct extent_map_tree *em_tree) | |||
12 | struct extent_map *em; | 12 | struct extent_map *em; |
13 | struct rb_node *node; | 13 | struct rb_node *node; |
14 | 14 | ||
15 | while (!RB_EMPTY_ROOT(&em_tree->map)) { | 15 | while (!RB_EMPTY_ROOT(&em_tree->map.rb_root)) { |
16 | node = rb_first(&em_tree->map); | 16 | node = rb_first_cached(&em_tree->map); |
17 | em = rb_entry(node, struct extent_map, rb_node); | 17 | em = rb_entry(node, struct extent_map, rb_node); |
18 | remove_extent_mapping(em_tree, em); | 18 | remove_extent_mapping(em_tree, em); |
19 | 19 | ||
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 86c2330ac83f..909c578506ee 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -1613,7 +1613,7 @@ static u64 find_next_chunk(struct btrfs_fs_info *fs_info) | |||
1613 | 1613 | ||
1614 | em_tree = &fs_info->mapping_tree.map_tree; | 1614 | em_tree = &fs_info->mapping_tree.map_tree; |
1615 | read_lock(&em_tree->lock); | 1615 | read_lock(&em_tree->lock); |
1616 | n = rb_last(&em_tree->map); | 1616 | n = rb_last(&em_tree->map.rb_root); |
1617 | if (n) { | 1617 | if (n) { |
1618 | em = rb_entry(n, struct extent_map, rb_node); | 1618 | em = rb_entry(n, struct extent_map, rb_node); |
1619 | ret = em->start + em->len; | 1619 | ret = em->start + em->len; |
@@ -7445,7 +7445,7 @@ static int verify_chunk_dev_extent_mapping(struct btrfs_fs_info *fs_info) | |||
7445 | int ret = 0; | 7445 | int ret = 0; |
7446 | 7446 | ||
7447 | read_lock(&em_tree->lock); | 7447 | read_lock(&em_tree->lock); |
7448 | for (node = rb_first(&em_tree->map); node; node = rb_next(node)) { | 7448 | for (node = rb_first_cached(&em_tree->map); node; node = rb_next(node)) { |
7449 | em = rb_entry(node, struct extent_map, rb_node); | 7449 | em = rb_entry(node, struct extent_map, rb_node); |
7450 | if (em->map_lookup->num_stripes != | 7450 | if (em->map_lookup->num_stripes != |
7451 | em->map_lookup->verified_stripes) { | 7451 | em->map_lookup->verified_stripes) { |