diff options
author | Qu Wenruo <wqu@suse.com> | 2020-02-26 06:08:36 +0100 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2020-05-25 11:25:18 +0200 |
commit | 29db137b6bb2f79851d86fa267ad8d6e6540a855 (patch) | |
tree | c0f3285ebde067f5c4b7253be87cd1789fbcf2dc /fs/btrfs/relocation.c | |
parent | btrfs: reloc: refactor finishing part of upper linkage into finish_upper_links() (diff) | |
download | linux-29db137b6bb2f79851d86fa267ad8d6e6540a855.tar.xz linux-29db137b6bb2f79851d86fa267ad8d6e6540a855.zip |
btrfs: reloc: refactor useless nodes handling into its own function
This patch will also add some comment for the cleanup.
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/relocation.c')
-rw-r--r-- | fs/btrfs/relocation.c | 113 |
1 files changed, 76 insertions, 37 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 29d53400c64c..96da33a9b692 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -1193,6 +1193,80 @@ static int finish_upper_links(struct backref_cache *cache, } /* + * For useless nodes, do two major clean ups: + * + * - Cleanup the children edges and nodes + * If child node is also orphan (no parent) during cleanup, then the child + * node will also be cleaned up. + * + * - Freeing up leaves (level 0), keeps nodes detached + * For nodes, the node is still cached as "detached" + * + * Return false if @node is not in the @useless_nodes list. + * Return true if @node is in the @useless_nodes list. + */ +static bool handle_useless_nodes(struct reloc_control *rc, + struct backref_node *node) +{ + struct backref_cache *cache = &rc->backref_cache; + struct list_head *useless_node = &cache->useless_node; + bool ret = false; + + while (!list_empty(useless_node)) { + struct backref_node *cur; + + cur = list_first_entry(useless_node, struct backref_node, + list); + list_del_init(&cur->list); + + /* Only tree root nodes can be added to @useless_nodes */ + ASSERT(list_empty(&cur->upper)); + + if (cur == node) + ret = true; + + /* The node is the lowest node */ + if (cur->lowest) { + list_del_init(&cur->lower); + cur->lowest = 0; + } + + /* Cleanup the lower edges */ + while (!list_empty(&cur->lower)) { + struct backref_edge *edge; + struct backref_node *lower; + + edge = list_entry(cur->lower.next, + struct backref_edge, list[UPPER]); + list_del(&edge->list[UPPER]); + list_del(&edge->list[LOWER]); + lower = edge->node[LOWER]; + free_backref_edge(cache, edge); + + /* Child node is also orphan, queue for cleanup */ + if (list_empty(&lower->upper)) + list_add(&lower->list, useless_node); + } + /* Mark this block processed for relocation */ + mark_block_processed(rc, cur); + + /* + * Backref nodes for tree leaves are deleted from the cache. + * Backref nodes for upper level tree blocks are left in the + * cache to avoid unnecessary backref lookup. + */ + if (cur->level > 0) { + list_add(&cur->list, &cache->detached); + cur->detached = 1; + } else { + rb_erase(&cur->rb_node, &cache->rb_root); + free_backref_node(cache, cur); + } + } + return ret; +} + +/* * Build backref tree for a given tree block. Root of the backref tree * corresponds the tree block, leaves of the backref tree correspond roots of * b-trees that reference the tree block. @@ -1266,43 +1340,8 @@ static noinline_for_stack struct backref_node *build_backref_tree( goto out; } - /* - * process useless backref nodes. backref nodes for tree leaves - * are deleted from the cache. backref nodes for upper level - * tree blocks are left in the cache to avoid unnecessary backref - * lookup. - */ - while (!list_empty(&cache->useless_node)) { - upper = list_first_entry(&cache->useless_node, - struct backref_node, list); - list_del_init(&upper->list); - ASSERT(list_empty(&upper->upper)); - if (upper == node) - node = NULL; - if (upper->lowest) { - list_del_init(&upper->lower); - upper->lowest = 0; - } - while (!list_empty(&upper->lower)) { - edge = list_first_entry(&upper->lower, - struct backref_edge, list[UPPER]); - list_del(&edge->list[UPPER]); - list_del(&edge->list[LOWER]); - lower = edge->node[LOWER]; - free_backref_edge(cache, edge); - - if (list_empty(&lower->upper)) - list_add(&lower->list, &cache->useless_node); - } - mark_block_processed(rc, upper); - if (upper->level > 0) { - list_add(&upper->list, &cache->detached); - upper->detached = 1; - } else { - rb_erase(&upper->rb_node, &cache->rb_root); - free_backref_node(cache, upper); - } - } + if (handle_useless_nodes(rc, node)) + node = NULL; out: btrfs_backref_iter_free(iter); btrfs_free_path(path); |