btrfs: reloc: add backref_cache::pending_edge and backref_cache::useless_node
These two new members will act the same as the existing local lists, @useless and @list in build_backref_tree(). Currently build_backref_tree() is only executed serially, thus moving such local list into backref_cache is still safe. Also since we're here, use list_first_entry() to replace a lot of list_entry() calls after !list_empty(). 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>
This commit is contained in:
parent
9569cc203d
commit
8478028933
|
@ -158,6 +158,12 @@ struct backref_cache {
|
||||||
|
|
||||||
int nr_nodes;
|
int nr_nodes;
|
||||||
int nr_edges;
|
int nr_edges;
|
||||||
|
|
||||||
|
/* The list of unchecked backref edges during backref cache build */
|
||||||
|
struct list_head pending_edge;
|
||||||
|
|
||||||
|
/* The list of useless backref nodes during backref cache build */
|
||||||
|
struct list_head useless_node;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -269,6 +275,8 @@ static void backref_cache_init(struct backref_cache *cache)
|
||||||
INIT_LIST_HEAD(&cache->changed);
|
INIT_LIST_HEAD(&cache->changed);
|
||||||
INIT_LIST_HEAD(&cache->detached);
|
INIT_LIST_HEAD(&cache->detached);
|
||||||
INIT_LIST_HEAD(&cache->leaves);
|
INIT_LIST_HEAD(&cache->leaves);
|
||||||
|
INIT_LIST_HEAD(&cache->pending_edge);
|
||||||
|
INIT_LIST_HEAD(&cache->useless_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void backref_cache_cleanup(struct backref_cache *cache)
|
static void backref_cache_cleanup(struct backref_cache *cache)
|
||||||
|
@ -292,6 +300,8 @@ static void backref_cache_cleanup(struct backref_cache *cache)
|
||||||
|
|
||||||
for (i = 0; i < BTRFS_MAX_LEVEL; i++)
|
for (i = 0; i < BTRFS_MAX_LEVEL; i++)
|
||||||
ASSERT(list_empty(&cache->pending[i]));
|
ASSERT(list_empty(&cache->pending[i]));
|
||||||
|
ASSERT(list_empty(&cache->pending_edge));
|
||||||
|
ASSERT(list_empty(&cache->useless_node));
|
||||||
ASSERT(list_empty(&cache->changed));
|
ASSERT(list_empty(&cache->changed));
|
||||||
ASSERT(list_empty(&cache->detached));
|
ASSERT(list_empty(&cache->detached));
|
||||||
ASSERT(RB_EMPTY_ROOT(&cache->rb_root));
|
ASSERT(RB_EMPTY_ROOT(&cache->rb_root));
|
||||||
|
@ -699,8 +709,6 @@ struct backref_node *build_backref_tree(struct reloc_control *rc,
|
||||||
struct backref_node *exist = NULL;
|
struct backref_node *exist = NULL;
|
||||||
struct backref_edge *edge;
|
struct backref_edge *edge;
|
||||||
struct rb_node *rb_node;
|
struct rb_node *rb_node;
|
||||||
LIST_HEAD(list); /* Pending edge list, upper node needs to be checked */
|
|
||||||
LIST_HEAD(useless);
|
|
||||||
int cowonly;
|
int cowonly;
|
||||||
int ret;
|
int ret;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
@ -764,7 +772,7 @@ again:
|
||||||
* check its backrefs
|
* check its backrefs
|
||||||
*/
|
*/
|
||||||
if (!exist->checked)
|
if (!exist->checked)
|
||||||
list_add_tail(&edge->list[UPPER], &list);
|
list_add_tail(&edge->list[UPPER], &cache->pending_edge);
|
||||||
} else {
|
} else {
|
||||||
exist = NULL;
|
exist = NULL;
|
||||||
}
|
}
|
||||||
|
@ -842,7 +850,8 @@ again:
|
||||||
* backrefs for the upper level block isn't
|
* backrefs for the upper level block isn't
|
||||||
* cached, add the block to pending list
|
* cached, add the block to pending list
|
||||||
*/
|
*/
|
||||||
list_add_tail(&edge->list[UPPER], &list);
|
list_add_tail(&edge->list[UPPER],
|
||||||
|
&cache->pending_edge);
|
||||||
} else {
|
} else {
|
||||||
upper = rb_entry(rb_node, struct backref_node,
|
upper = rb_entry(rb_node, struct backref_node,
|
||||||
rb_node);
|
rb_node);
|
||||||
|
@ -884,7 +893,7 @@ again:
|
||||||
cur->bytenr);
|
cur->bytenr);
|
||||||
if (should_ignore_root(root)) {
|
if (should_ignore_root(root)) {
|
||||||
btrfs_put_root(root);
|
btrfs_put_root(root);
|
||||||
list_add(&cur->list, &useless);
|
list_add(&cur->list, &cache->useless_node);
|
||||||
} else {
|
} else {
|
||||||
cur->root = root;
|
cur->root = root;
|
||||||
}
|
}
|
||||||
|
@ -930,7 +939,8 @@ again:
|
||||||
lower->bytenr);
|
lower->bytenr);
|
||||||
if (should_ignore_root(root)) {
|
if (should_ignore_root(root)) {
|
||||||
btrfs_put_root(root);
|
btrfs_put_root(root);
|
||||||
list_add(&lower->list, &useless);
|
list_add(&lower->list,
|
||||||
|
&cache->useless_node);
|
||||||
} else {
|
} else {
|
||||||
lower->root = root;
|
lower->root = root;
|
||||||
}
|
}
|
||||||
|
@ -979,7 +989,7 @@ again:
|
||||||
if (!upper->checked && need_check) {
|
if (!upper->checked && need_check) {
|
||||||
need_check = false;
|
need_check = false;
|
||||||
list_add_tail(&edge->list[UPPER],
|
list_add_tail(&edge->list[UPPER],
|
||||||
&list);
|
&cache->pending_edge);
|
||||||
} else {
|
} else {
|
||||||
if (upper->checked)
|
if (upper->checked)
|
||||||
need_check = true;
|
need_check = true;
|
||||||
|
@ -1017,8 +1027,9 @@ again:
|
||||||
WARN_ON(exist);
|
WARN_ON(exist);
|
||||||
|
|
||||||
/* the pending list isn't empty, take the first block to process */
|
/* the pending list isn't empty, take the first block to process */
|
||||||
if (!list_empty(&list)) {
|
if (!list_empty(&cache->pending_edge)) {
|
||||||
edge = list_entry(list.next, struct backref_edge, list[UPPER]);
|
edge = list_first_entry(&cache->pending_edge,
|
||||||
|
struct backref_edge, list[UPPER]);
|
||||||
list_del_init(&edge->list[UPPER]);
|
list_del_init(&edge->list[UPPER]);
|
||||||
cur = edge->node[UPPER];
|
cur = edge->node[UPPER];
|
||||||
goto again;
|
goto again;
|
||||||
|
@ -1039,10 +1050,11 @@ again:
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(edge, &node->upper, list[LOWER])
|
list_for_each_entry(edge, &node->upper, list[LOWER])
|
||||||
list_add_tail(&edge->list[UPPER], &list);
|
list_add_tail(&edge->list[UPPER], &cache->pending_edge);
|
||||||
|
|
||||||
while (!list_empty(&list)) {
|
while (!list_empty(&cache->pending_edge)) {
|
||||||
edge = list_entry(list.next, struct backref_edge, list[UPPER]);
|
edge = list_first_entry(&cache->pending_edge,
|
||||||
|
struct backref_edge, list[UPPER]);
|
||||||
list_del_init(&edge->list[UPPER]);
|
list_del_init(&edge->list[UPPER]);
|
||||||
upper = edge->node[UPPER];
|
upper = edge->node[UPPER];
|
||||||
if (upper->detached) {
|
if (upper->detached) {
|
||||||
|
@ -1050,7 +1062,7 @@ again:
|
||||||
lower = edge->node[LOWER];
|
lower = edge->node[LOWER];
|
||||||
free_backref_edge(cache, edge);
|
free_backref_edge(cache, edge);
|
||||||
if (list_empty(&lower->upper))
|
if (list_empty(&lower->upper))
|
||||||
list_add(&lower->list, &useless);
|
list_add(&lower->list, &cache->useless_node);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1090,7 +1102,7 @@ again:
|
||||||
list_add_tail(&edge->list[UPPER], &upper->lower);
|
list_add_tail(&edge->list[UPPER], &upper->lower);
|
||||||
|
|
||||||
list_for_each_entry(edge, &upper->upper, list[LOWER])
|
list_for_each_entry(edge, &upper->upper, list[LOWER])
|
||||||
list_add_tail(&edge->list[UPPER], &list);
|
list_add_tail(&edge->list[UPPER], &cache->pending_edge);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* process useless backref nodes. backref nodes for tree leaves
|
* process useless backref nodes. backref nodes for tree leaves
|
||||||
|
@ -1098,8 +1110,9 @@ again:
|
||||||
* tree blocks are left in the cache to avoid unnecessary backref
|
* tree blocks are left in the cache to avoid unnecessary backref
|
||||||
* lookup.
|
* lookup.
|
||||||
*/
|
*/
|
||||||
while (!list_empty(&useless)) {
|
while (!list_empty(&cache->useless_node)) {
|
||||||
upper = list_entry(useless.next, struct backref_node, list);
|
upper = list_first_entry(&cache->useless_node,
|
||||||
|
struct backref_node, list);
|
||||||
list_del_init(&upper->list);
|
list_del_init(&upper->list);
|
||||||
ASSERT(list_empty(&upper->upper));
|
ASSERT(list_empty(&upper->upper));
|
||||||
if (upper == node)
|
if (upper == node)
|
||||||
|
@ -1109,7 +1122,7 @@ again:
|
||||||
upper->lowest = 0;
|
upper->lowest = 0;
|
||||||
}
|
}
|
||||||
while (!list_empty(&upper->lower)) {
|
while (!list_empty(&upper->lower)) {
|
||||||
edge = list_entry(upper->lower.next,
|
edge = list_first_entry(&upper->lower,
|
||||||
struct backref_edge, list[UPPER]);
|
struct backref_edge, list[UPPER]);
|
||||||
list_del(&edge->list[UPPER]);
|
list_del(&edge->list[UPPER]);
|
||||||
list_del(&edge->list[LOWER]);
|
list_del(&edge->list[LOWER]);
|
||||||
|
@ -1117,7 +1130,7 @@ again:
|
||||||
free_backref_edge(cache, edge);
|
free_backref_edge(cache, edge);
|
||||||
|
|
||||||
if (list_empty(&lower->upper))
|
if (list_empty(&lower->upper))
|
||||||
list_add(&lower->list, &useless);
|
list_add(&lower->list, &cache->useless_node);
|
||||||
}
|
}
|
||||||
mark_block_processed(rc, upper);
|
mark_block_processed(rc, upper);
|
||||||
if (upper->level > 0) {
|
if (upper->level > 0) {
|
||||||
|
@ -1132,14 +1145,14 @@ out:
|
||||||
btrfs_backref_iter_free(iter);
|
btrfs_backref_iter_free(iter);
|
||||||
btrfs_free_path(path);
|
btrfs_free_path(path);
|
||||||
if (err) {
|
if (err) {
|
||||||
while (!list_empty(&useless)) {
|
while (!list_empty(&cache->useless_node)) {
|
||||||
lower = list_entry(useless.next,
|
lower = list_first_entry(&cache->useless_node,
|
||||||
struct backref_node, list);
|
struct backref_node, list);
|
||||||
list_del_init(&lower->list);
|
list_del_init(&lower->list);
|
||||||
}
|
}
|
||||||
while (!list_empty(&list)) {
|
while (!list_empty(&cache->pending_edge)) {
|
||||||
edge = list_first_entry(&list, struct backref_edge,
|
edge = list_first_entry(&cache->pending_edge,
|
||||||
list[UPPER]);
|
struct backref_edge, list[UPPER]);
|
||||||
list_del(&edge->list[UPPER]);
|
list_del(&edge->list[UPPER]);
|
||||||
list_del(&edge->list[LOWER]);
|
list_del(&edge->list[LOWER]);
|
||||||
lower = edge->node[LOWER];
|
lower = edge->node[LOWER];
|
||||||
|
@ -1152,20 +1165,21 @@ out:
|
||||||
*/
|
*/
|
||||||
if (list_empty(&lower->upper) &&
|
if (list_empty(&lower->upper) &&
|
||||||
RB_EMPTY_NODE(&lower->rb_node))
|
RB_EMPTY_NODE(&lower->rb_node))
|
||||||
list_add(&lower->list, &useless);
|
list_add(&lower->list, &cache->useless_node);
|
||||||
|
|
||||||
if (!RB_EMPTY_NODE(&upper->rb_node))
|
if (!RB_EMPTY_NODE(&upper->rb_node))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Add this guy's upper edges to the list to process */
|
/* Add this guy's upper edges to the list to process */
|
||||||
list_for_each_entry(edge, &upper->upper, list[LOWER])
|
list_for_each_entry(edge, &upper->upper, list[LOWER])
|
||||||
list_add_tail(&edge->list[UPPER], &list);
|
list_add_tail(&edge->list[UPPER],
|
||||||
|
&cache->pending_edge);
|
||||||
if (list_empty(&upper->upper))
|
if (list_empty(&upper->upper))
|
||||||
list_add(&upper->list, &useless);
|
list_add(&upper->list, &cache->useless_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!list_empty(&useless)) {
|
while (!list_empty(&cache->useless_node)) {
|
||||||
lower = list_entry(useless.next,
|
lower = list_first_entry(&cache->useless_node,
|
||||||
struct backref_node, list);
|
struct backref_node, list);
|
||||||
list_del_init(&lower->list);
|
list_del_init(&lower->list);
|
||||||
if (lower == node)
|
if (lower == node)
|
||||||
|
@ -1174,9 +1188,13 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
remove_backref_node(cache, node);
|
remove_backref_node(cache, node);
|
||||||
|
ASSERT(list_empty(&cache->useless_node) &&
|
||||||
|
list_empty(&cache->pending_edge));
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
ASSERT(!node || !node->detached);
|
ASSERT(!node || !node->detached);
|
||||||
|
ASSERT(list_empty(&cache->useless_node) &&
|
||||||
|
list_empty(&cache->pending_edge));
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue