mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-15 01:24:33 +00:00
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>
This commit is contained in:
parent
03a1d4c891
commit
07e1ce096d
@ -34,7 +34,7 @@ void __cold extent_map_exit(void)
|
|||||||
*/
|
*/
|
||||||
void extent_map_tree_init(struct extent_map_tree *tree)
|
void extent_map_tree_init(struct extent_map_tree *tree)
|
||||||
{
|
{
|
||||||
tree->map = RB_ROOT;
|
tree->map = RB_ROOT_CACHED;
|
||||||
INIT_LIST_HEAD(&tree->modified_extents);
|
INIT_LIST_HEAD(&tree->modified_extents);
|
||||||
rwlock_init(&tree->lock);
|
rwlock_init(&tree->lock);
|
||||||
}
|
}
|
||||||
@ -90,24 +90,27 @@ static u64 range_end(u64 start, u64 len)
|
|||||||
return start + len;
|
return start + len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tree_insert(struct rb_root *root, struct extent_map *em)
|
static int tree_insert(struct rb_root_cached *root, struct extent_map *em)
|
||||||
{
|
{
|
||||||
struct rb_node **p = &root->rb_node;
|
struct rb_node **p = &root->rb_root.rb_node;
|
||||||
struct rb_node *parent = NULL;
|
struct rb_node *parent = NULL;
|
||||||
struct extent_map *entry = NULL;
|
struct extent_map *entry = NULL;
|
||||||
struct rb_node *orig_parent = NULL;
|
struct rb_node *orig_parent = NULL;
|
||||||
u64 end = range_end(em->start, em->len);
|
u64 end = range_end(em->start, em->len);
|
||||||
|
bool leftmost = true;
|
||||||
|
|
||||||
while (*p) {
|
while (*p) {
|
||||||
parent = *p;
|
parent = *p;
|
||||||
entry = rb_entry(parent, struct extent_map, rb_node);
|
entry = rb_entry(parent, struct extent_map, rb_node);
|
||||||
|
|
||||||
if (em->start < entry->start)
|
if (em->start < entry->start) {
|
||||||
p = &(*p)->rb_left;
|
p = &(*p)->rb_left;
|
||||||
else if (em->start >= extent_map_end(entry))
|
} else if (em->start >= extent_map_end(entry)) {
|
||||||
p = &(*p)->rb_right;
|
p = &(*p)->rb_right;
|
||||||
else
|
leftmost = false;
|
||||||
|
} else {
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
orig_parent = parent;
|
orig_parent = parent;
|
||||||
@ -130,7 +133,7 @@ static int tree_insert(struct rb_root *root, struct extent_map *em)
|
|||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
|
|
||||||
rb_link_node(&em->rb_node, orig_parent, p);
|
rb_link_node(&em->rb_node, orig_parent, p);
|
||||||
rb_insert_color(&em->rb_node, root);
|
rb_insert_color_cached(&em->rb_node, root, leftmost);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +245,7 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
|
|||||||
em->mod_start = merge->mod_start;
|
em->mod_start = merge->mod_start;
|
||||||
em->generation = max(em->generation, merge->generation);
|
em->generation = max(em->generation, merge->generation);
|
||||||
|
|
||||||
rb_erase(&merge->rb_node, &tree->map);
|
rb_erase_cached(&merge->rb_node, &tree->map);
|
||||||
RB_CLEAR_NODE(&merge->rb_node);
|
RB_CLEAR_NODE(&merge->rb_node);
|
||||||
free_extent_map(merge);
|
free_extent_map(merge);
|
||||||
}
|
}
|
||||||
@ -254,7 +257,7 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
|
|||||||
if (rb && mergable_maps(em, merge)) {
|
if (rb && mergable_maps(em, merge)) {
|
||||||
em->len += merge->len;
|
em->len += merge->len;
|
||||||
em->block_len += merge->block_len;
|
em->block_len += merge->block_len;
|
||||||
rb_erase(&merge->rb_node, &tree->map);
|
rb_erase_cached(&merge->rb_node, &tree->map);
|
||||||
RB_CLEAR_NODE(&merge->rb_node);
|
RB_CLEAR_NODE(&merge->rb_node);
|
||||||
em->mod_len = (merge->mod_start + merge->mod_len) - em->mod_start;
|
em->mod_len = (merge->mod_start + merge->mod_len) - em->mod_start;
|
||||||
em->generation = max(em->generation, merge->generation);
|
em->generation = max(em->generation, merge->generation);
|
||||||
@ -367,7 +370,7 @@ __lookup_extent_mapping(struct extent_map_tree *tree,
|
|||||||
struct rb_node *next = NULL;
|
struct rb_node *next = NULL;
|
||||||
u64 end = range_end(start, len);
|
u64 end = range_end(start, len);
|
||||||
|
|
||||||
rb_node = __tree_search(&tree->map, start, &prev, &next);
|
rb_node = __tree_search(&tree->map.rb_root, start, &prev, &next);
|
||||||
if (!rb_node) {
|
if (!rb_node) {
|
||||||
if (prev)
|
if (prev)
|
||||||
rb_node = prev;
|
rb_node = prev;
|
||||||
@ -431,7 +434,7 @@ struct extent_map *search_extent_mapping(struct extent_map_tree *tree,
|
|||||||
void remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em)
|
void remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em)
|
||||||
{
|
{
|
||||||
WARN_ON(test_bit(EXTENT_FLAG_PINNED, &em->flags));
|
WARN_ON(test_bit(EXTENT_FLAG_PINNED, &em->flags));
|
||||||
rb_erase(&em->rb_node, &tree->map);
|
rb_erase_cached(&em->rb_node, &tree->map);
|
||||||
if (!test_bit(EXTENT_FLAG_LOGGING, &em->flags))
|
if (!test_bit(EXTENT_FLAG_LOGGING, &em->flags))
|
||||||
list_del_init(&em->list);
|
list_del_init(&em->list);
|
||||||
RB_CLEAR_NODE(&em->rb_node);
|
RB_CLEAR_NODE(&em->rb_node);
|
||||||
@ -446,7 +449,7 @@ void replace_extent_mapping(struct extent_map_tree *tree,
|
|||||||
ASSERT(extent_map_in_tree(cur));
|
ASSERT(extent_map_in_tree(cur));
|
||||||
if (!test_bit(EXTENT_FLAG_LOGGING, &cur->flags))
|
if (!test_bit(EXTENT_FLAG_LOGGING, &cur->flags))
|
||||||
list_del_init(&cur->list);
|
list_del_init(&cur->list);
|
||||||
rb_replace_node(&cur->rb_node, &new->rb_node, &tree->map);
|
rb_replace_node_cached(&cur->rb_node, &new->rb_node, &tree->map);
|
||||||
RB_CLEAR_NODE(&cur->rb_node);
|
RB_CLEAR_NODE(&cur->rb_node);
|
||||||
|
|
||||||
setup_extent_mapping(tree, new, modified);
|
setup_extent_mapping(tree, new, modified);
|
||||||
|
@ -49,7 +49,7 @@ struct extent_map {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct extent_map_tree {
|
struct extent_map_tree {
|
||||||
struct rb_root map;
|
struct rb_root_cached map;
|
||||||
struct list_head modified_extents;
|
struct list_head modified_extents;
|
||||||
rwlock_t lock;
|
rwlock_t lock;
|
||||||
};
|
};
|
||||||
|
@ -5222,10 +5222,10 @@ static void evict_inode_truncate_pages(struct inode *inode)
|
|||||||
truncate_inode_pages_final(&inode->i_data);
|
truncate_inode_pages_final(&inode->i_data);
|
||||||
|
|
||||||
write_lock(&map_tree->lock);
|
write_lock(&map_tree->lock);
|
||||||
while (!RB_EMPTY_ROOT(&map_tree->map)) {
|
while (!RB_EMPTY_ROOT(&map_tree->map.rb_root)) {
|
||||||
struct extent_map *em;
|
struct extent_map *em;
|
||||||
|
|
||||||
node = rb_first(&map_tree->map);
|
node = rb_first_cached(&map_tree->map);
|
||||||
em = rb_entry(node, struct extent_map, rb_node);
|
em = rb_entry(node, struct extent_map, rb_node);
|
||||||
clear_bit(EXTENT_FLAG_PINNED, &em->flags);
|
clear_bit(EXTENT_FLAG_PINNED, &em->flags);
|
||||||
clear_bit(EXTENT_FLAG_LOGGING, &em->flags);
|
clear_bit(EXTENT_FLAG_LOGGING, &em->flags);
|
||||||
|
@ -12,8 +12,8 @@ static void free_extent_map_tree(struct extent_map_tree *em_tree)
|
|||||||
struct extent_map *em;
|
struct extent_map *em;
|
||||||
struct rb_node *node;
|
struct rb_node *node;
|
||||||
|
|
||||||
while (!RB_EMPTY_ROOT(&em_tree->map)) {
|
while (!RB_EMPTY_ROOT(&em_tree->map.rb_root)) {
|
||||||
node = rb_first(&em_tree->map);
|
node = rb_first_cached(&em_tree->map);
|
||||||
em = rb_entry(node, struct extent_map, rb_node);
|
em = rb_entry(node, struct extent_map, rb_node);
|
||||||
remove_extent_mapping(em_tree, em);
|
remove_extent_mapping(em_tree, em);
|
||||||
|
|
||||||
|
@ -1613,7 +1613,7 @@ static u64 find_next_chunk(struct btrfs_fs_info *fs_info)
|
|||||||
|
|
||||||
em_tree = &fs_info->mapping_tree.map_tree;
|
em_tree = &fs_info->mapping_tree.map_tree;
|
||||||
read_lock(&em_tree->lock);
|
read_lock(&em_tree->lock);
|
||||||
n = rb_last(&em_tree->map);
|
n = rb_last(&em_tree->map.rb_root);
|
||||||
if (n) {
|
if (n) {
|
||||||
em = rb_entry(n, struct extent_map, rb_node);
|
em = rb_entry(n, struct extent_map, rb_node);
|
||||||
ret = em->start + em->len;
|
ret = em->start + em->len;
|
||||||
@ -7445,7 +7445,7 @@ static int verify_chunk_dev_extent_mapping(struct btrfs_fs_info *fs_info)
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
read_lock(&em_tree->lock);
|
read_lock(&em_tree->lock);
|
||||||
for (node = rb_first(&em_tree->map); node; node = rb_next(node)) {
|
for (node = rb_first_cached(&em_tree->map); node; node = rb_next(node)) {
|
||||||
em = rb_entry(node, struct extent_map, rb_node);
|
em = rb_entry(node, struct extent_map, rb_node);
|
||||||
if (em->map_lookup->num_stripes !=
|
if (em->map_lookup->num_stripes !=
|
||||||
em->map_lookup->verified_stripes) {
|
em->map_lookup->verified_stripes) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user