From: Qu Wenruo <wqu@suse.com>
To: linux-btrfs@vger.kernel.org
Cc: Josef Bacik <josef@toxicpanda.com>
Subject: [PATCH 12/40] btrfs: relocation: Remove the open-coded goto loop for breadth-first search
Date: Mon, 23 Mar 2020 18:23:48 +0800 [thread overview]
Message-ID: <20200323102416.112862-13-wqu@suse.com> (raw)
In-Reply-To: <20200323102416.112862-1-wqu@suse.com>
build_backref_tree() uses "goto again;" to implement a breadth-first
search to build backref cache.
This patch will extract most of its work into a wrapper,
handle_one_tree_block(), and use a do {} while() loop to implement the same
thing.
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
---
fs/btrfs/relocation.c | 170 ++++++++++++++++++++++--------------------
1 file changed, 89 insertions(+), 81 deletions(-)
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index ad5cca49a6e3..77837ba25a67 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -957,77 +957,31 @@ static int handle_indirect_tree_backref(struct backref_cache *cache,
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.
- *
- * the basic idea of this function is check backrefs of a given block
- * to find upper level blocks that reference the block, and then check
- * backrefs of these upper level blocks recursively. the recursion stop
- * when tree root is reached or backrefs for the block is cached.
- *
- * NOTE: if we find backrefs for a block are cached, we know backrefs
- * for all upper level blocks that directly/indirectly reference the
- * block are also cached.
- */
-static noinline_for_stack
-struct backref_node *build_backref_tree(struct reloc_control *rc,
- struct btrfs_key *node_key,
- int level, u64 bytenr)
+static int handle_one_tree_block(struct backref_cache *cache,
+ struct btrfs_path *path,
+ struct btrfs_backref_iter *iter,
+ struct btrfs_key *node_key,
+ struct backref_node *cur)
{
- struct btrfs_backref_iter *iter;
- struct backref_cache *cache = &rc->backref_cache;
- struct btrfs_path *path; /* For searching parent of TREE_BLOCK_REF */
- struct backref_node *cur;
- struct backref_node *upper;
- struct backref_node *lower;
- struct backref_node *node = NULL;
- struct backref_node *exist = NULL;
+ struct btrfs_fs_info *fs_info = cache->fs_info;
struct backref_edge *edge;
- struct rb_node *rb_node;
- int cowonly;
+ struct backref_node *exist;
int ret;
- int err = 0;
-
- iter = btrfs_backref_iter_alloc(rc->extent_root->fs_info, GFP_NOFS);
- if (!iter)
- return ERR_PTR(-ENOMEM);
- path = btrfs_alloc_path();
- if (!path) {
- err = -ENOMEM;
- goto out;
- }
- path->reada = READA_FORWARD;
-
- node = alloc_backref_node(cache, bytenr, level);
- if (!node) {
- err = -ENOMEM;
- goto out;
- }
- node->lowest = 1;
- cur = node;
-again:
ret = btrfs_backref_iter_start(iter, cur->bytenr);
- if (ret < 0) {
- err = ret;
- goto out;
- }
-
+ if (ret < 0)
+ return ret;
/*
* We skip the first btrfs_tree_block_info, as we don't use the key
* stored in it, but fetch it from the tree block.
*/
if (btrfs_backref_has_tree_block_info(iter)) {
ret = btrfs_backref_iter_next(iter);
- if (ret < 0) {
- err = ret;
+ if (ret < 0)
goto out;
- }
/* No extra backref? This means the tree block is corrupted */
if (ret > 0) {
- err = -EUCLEAN;
+ ret = -EUCLEAN;
goto out;
}
}
@@ -1070,7 +1024,7 @@ struct backref_node *build_backref_tree(struct reloc_control *rc,
type = btrfs_get_extent_inline_ref_type(eb, iref,
BTRFS_REF_TYPE_BLOCK);
if (type == BTRFS_REF_TYPE_INVALID) {
- err = -EUCLEAN;
+ ret = -EUCLEAN;
goto out;
}
key.type = type;
@@ -1096,16 +1050,13 @@ struct backref_node *build_backref_tree(struct reloc_control *rc,
/* SHARED_BLOCK_REF means key.offset is the parent bytenr */
if (key.type == BTRFS_SHARED_BLOCK_REF_KEY) {
ret = handle_direct_tree_backref(cache, &key, cur);
- if (ret < 0) {
- err = ret;
+ if (ret < 0)
goto out;
- }
continue;
} else if (unlikely(key.type == BTRFS_EXTENT_REF_V0_KEY)) {
- err = -EINVAL;
- btrfs_print_v0_err(rc->extent_root->fs_info);
- btrfs_handle_fs_error(rc->extent_root->fs_info, err,
- NULL);
+ ret = -EINVAL;
+ btrfs_print_v0_err(fs_info);
+ btrfs_handle_fs_error(fs_info, ret, NULL);
goto out;
} else if (key.type != BTRFS_TREE_BLOCK_REF_KEY) {
continue;
@@ -1118,30 +1069,87 @@ struct backref_node *build_backref_tree(struct reloc_control *rc,
*/
ret = handle_indirect_tree_backref(cache, path, &key, node_key,
cur);
- if (ret < 0) {
- err = ret;
+ if (ret < 0)
goto out;
- }
- }
- if (ret < 0) {
- err = ret;
- goto out;
}
ret = 0;
- btrfs_backref_iter_release(iter);
-
cur->checked = 1;
WARN_ON(exist);
+out:
+ btrfs_backref_iter_release(iter);
+ return ret;
+}
- /* the pending list isn't empty, take the first block to process */
- if (!list_empty(&cache->pending_edge)) {
- edge = list_entry(cache->pending_edge.next,
- struct backref_edge, list[UPPER]);
- list_del_init(&edge->list[UPPER]);
- cur = edge->node[UPPER];
- goto again;
+/*
+ * 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.
+ *
+ * the basic idea of this function is check backrefs of a given block
+ * to find upper level blocks that reference the block, and then check
+ * backrefs of these upper level blocks recursively. the recursion stop
+ * when tree root is reached or backrefs for the block is cached.
+ *
+ * NOTE: if we find backrefs for a block are cached, we know backrefs
+ * for all upper level blocks that directly/indirectly reference the
+ * block are also cached.
+ */
+static noinline_for_stack
+struct backref_node *build_backref_tree(struct reloc_control *rc,
+ struct btrfs_key *node_key,
+ int level, u64 bytenr)
+{
+ struct btrfs_backref_iter *iter;
+ struct backref_cache *cache = &rc->backref_cache;
+ struct btrfs_path *path; /* For searching parent of TREE_BLOCK_REF */
+ struct backref_node *cur;
+ struct backref_node *upper;
+ struct backref_node *lower;
+ struct backref_node *node = NULL;
+ struct backref_edge *edge;
+ struct rb_node *rb_node;
+ int cowonly;
+ int ret;
+ int err = 0;
+
+ iter = btrfs_backref_iter_alloc(rc->extent_root->fs_info, GFP_NOFS);
+ if (!iter)
+ return ERR_PTR(-ENOMEM);
+ path = btrfs_alloc_path();
+ if (!path) {
+ err = -ENOMEM;
+ goto out;
+ }
+ path->reada = READA_FORWARD;
+
+ node = alloc_backref_node(cache, bytenr, level);
+ if (!node) {
+ err = -ENOMEM;
+ goto out;
}
+ node->lowest = 1;
+ cur = node;
+
+ /* Breadth-first search to build backref cache */
+ do {
+ ret = handle_one_tree_block(cache, path, iter, node_key, cur);
+ if (ret < 0) {
+ err = ret;
+ goto out;
+ }
+ edge = list_first_entry_or_null(&cache->pending_edge,
+ struct backref_edge, list[UPPER]);
+ /*
+ * the pending list isn't empty, take the first block to
+ * process
+ */
+ if (edge) {
+ list_del_init(&edge->list[UPPER]);
+ cur = edge->node[UPPER];
+ }
+ } while (edge);
+
/*
* everything goes well, connect backref nodes and insert backref nodes
* into the cache.
--
2.25.2
next prev parent reply other threads:[~2020-03-23 10:25 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-03-23 10:23 [PATCH 00/40] btrfs: qgroup: Use backref cache based backref walk for commit roots Qu Wenruo
2020-03-23 10:23 ` [PATCH 01/40] btrfs: backref: Introduce the skeleton of btrfs_backref_iter Qu Wenruo
2020-03-23 12:51 ` Josef Bacik
2020-03-23 10:23 ` [PATCH 02/40] btrfs: backref: Implement btrfs_backref_iter_next() Qu Wenruo
2020-03-23 10:23 ` [PATCH 03/40] btrfs: relocation: Use btrfs_backref_iter infrastructure Qu Wenruo
2020-03-23 10:23 ` [PATCH 04/40] btrfs: relocation: Rename mark_block_processed() and __mark_block_processed() Qu Wenruo
2020-03-23 10:23 ` [PATCH 05/40] btrfs: relocation: Add backref_cache::pending_edge and backref_cache::useless_node members Qu Wenruo
2020-03-23 10:23 ` [PATCH 06/40] btrfs: relocation: Add backref_cache::fs_info member Qu Wenruo
2020-03-23 10:23 ` [PATCH 07/40] btrfs: relocation: Make reloc root search specific for relocation backref cache Qu Wenruo
2020-03-23 10:23 ` [PATCH 08/40] btrfs: relocation: Refactor direct tree backref processing into its own function Qu Wenruo
2020-03-23 10:23 ` [PATCH 09/40] btrfs: relocation: Refactor indirect " Qu Wenruo
2020-03-23 10:23 ` [PATCH 10/40] btrfs: relocation: Use wrapper to replace open-coded edge linking Qu Wenruo
2020-03-23 10:23 ` [PATCH 11/40] btrfs: relocation: Specify essential members for alloc_backref_node() Qu Wenruo
2020-03-23 10:23 ` Qu Wenruo [this message]
2020-03-23 10:23 ` [PATCH 13/40] btrfs: relocation: Refactor the finishing part of upper linkage into finish_upper_links() Qu Wenruo
2020-03-23 10:23 ` [PATCH 14/40] btrfs: relocation: Refactor the useless nodes handling into its own function Qu Wenruo
2020-03-23 10:23 ` [PATCH 15/40] btrfs: relocation: Add btrfs_ prefix for backref_node/edge/cache Qu Wenruo
2020-03-23 10:23 ` [PATCH 16/40] btrfs: Move btrfs_backref_(node|edge|cache) structures to backref.h Qu Wenruo
2020-03-23 10:23 ` [PATCH 17/40] btrfs: Rename tree_entry to simple_node and export it Qu Wenruo
2020-03-23 10:23 ` [PATCH 18/40] btrfs: Rename backref_cache_init() to btrfs_backref_cache_init() and move it to backref.c Qu Wenruo
2020-03-23 10:23 ` [PATCH 19/40] btrfs: Rename alloc_backref_node() to btrfs_backref_alloc_node() and move it backref.c Qu Wenruo
2020-03-23 10:23 ` [PATCH 20/40] btrfs: Rename alloc_backref_edge() to btrfs_backref_alloc_edge() " Qu Wenruo
2020-03-23 10:23 ` [PATCH 21/40] btrfs: Rename link_backref_edge() to btrfs_backref_link_edge() and move it backref.h Qu Wenruo
2020-03-23 10:23 ` [PATCH 22/40] btrfs: Rename free_backref_(node|edge) to btrfs_backref_free_(node|edge) and move them to backref.h Qu Wenruo
2020-03-23 10:23 ` [PATCH 23/40] btrfs: Rename drop_backref_node() to btrfs_backref_drop_node() and move its needed facilities " Qu Wenruo
2020-03-23 10:24 ` [PATCH 24/40] btrfs: Rename remove_backref_node() to btrfs_backref_cleanup_node() and move it to backref.c Qu Wenruo
2020-03-23 10:24 ` [PATCH 25/40] btrfs: Rename backref_cache_cleanup() to btrfs_backref_release_cache() " Qu Wenruo
2020-03-23 10:24 ` [PATCH 26/40] btrfs: Rename backref_tree_panic() to btrfs_backref_panic(), " Qu Wenruo
2020-03-23 10:24 ` [PATCH 27/40] btrfs: Rename should_ignore_root() to btrfs_should_ignore_reloc_root() and export it Qu Wenruo
2020-03-23 10:24 ` [PATCH 28/40] btrfs: relocation: Open-code read_fs_root() for handle_indirect_tree_backref() Qu Wenruo
2020-03-23 10:24 ` [PATCH 29/40] btrfs: Rename handle_one_tree_block() to btrfs_backref_add_tree_node() and move it to backref.c Qu Wenruo
2020-03-23 10:24 ` [PATCH 30/40] btrfs: Rename finish_upper_links() to btrfs_backref_finish_upper_links() " Qu Wenruo
2020-03-23 10:24 ` [PATCH 31/40] btrfs: relocation: Move error handling of build_backref_tree() " Qu Wenruo
2020-03-23 10:24 ` [PATCH 32/40] btrfs: relocation: Use btrfs_find_all_leaves() to locate parent tree leaves of a data extent Qu Wenruo
2020-03-23 10:24 ` [PATCH 33/40] btrfs: backref: Only ignore reloc roots for indrect backref resolve if the backref cache is for reloction purpose Qu Wenruo
2020-03-23 10:24 ` [PATCH 34/40] btrfs: qgroup: Introduce qgroup backref cache Qu Wenruo
2020-03-23 10:24 ` [PATCH 35/40] btrfs: qgroup: Introduce qgroup_backref_cache_build() function Qu Wenruo
2020-03-23 10:24 ` [PATCH 36/40] btrfs: qgroup: Introduce a function to iterate through backref_cache to find all parents for specified node Qu Wenruo
2020-03-23 10:24 ` [PATCH 37/40] btrfs: qgroup: Introduce helpers to get needed tree block info Qu Wenruo
2020-03-23 10:24 ` [PATCH 38/40] btrfs: qgroup: Introduce verification for function to ensure old roots ulist matches btrfs_find_all_roots() result Qu Wenruo
2020-03-23 10:24 ` [PATCH 39/40] btrfs: qgroup: Introduce a new function to get old_roots ulist using backref cache Qu Wenruo
2020-03-23 10:24 ` [PATCH 40/40] btrfs: qgroup: Use backref cache to speed up old_roots search Qu Wenruo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200323102416.112862-13-wqu@suse.com \
--to=wqu@suse.com \
--cc=josef@toxicpanda.com \
--cc=linux-btrfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox