summaryrefslogtreecommitdiff
path: root/fs/btrfs/backref.c
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@suse.com>2022-11-01 19:15:48 +0300
committerDavid Sterba <dsterba@suse.com>2022-12-05 20:00:50 +0300
commit1baea6f18abf34037169d3b0c585356abb395376 (patch)
treef0028743045c3e55dff4d78580155587fb916407 /fs/btrfs/backref.c
parenta2c8d27e5ee810b7149b42b88ddf7298e5b8dfe0 (diff)
downloadlinux-1baea6f18abf34037169d3b0c585356abb395376.tar.xz
btrfs: reuse roots ulist on each leaf iteration for iterate_extent_inodes()
At iterate_extent_inodes() we collect a ulist of leaves for a given extent with a call to btrfs_find_all_leafs() and then we enter a loop where we iterate over all the collected leaves. Each iteration of that loop does a call to btrfs_find_all_roots_safe(), to determine all roots from which a leaf is accessible, and that results in allocating and releasing a ulist to store the root IDs. Instead of allocating and releasing the roots ulist on every iteration, allocate a ulist before entering the loop and keep using it on each iteration, reinitializing the ulist at the end of each iteration. Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/backref.c')
-rw-r--r--fs/btrfs/backref.c46
1 files changed, 31 insertions, 15 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index a1a00a7bdba5..dc276ce3afe0 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -1674,32 +1674,36 @@ int btrfs_find_all_leafs(struct btrfs_backref_walk_ctx *ctx)
* the current while iterating. The process stops when we reach the end of the
* list.
*
- * Found roots are added to @ctx->roots, which is allocated by this function and
- * @ctx->roots should be NULL when calling this function. This function also
- * requires @ctx->refs to be NULL, as it uses it for allocating a ulist to do
- * temporary work, and frees it before returning.
+ * Found roots are added to @ctx->roots, which is allocated by this function if
+ * it points to NULL, in which case the caller is responsible for freeing it
+ * after it's not needed anymore.
+ * This function requires @ctx->refs to be NULL, as it uses it for allocating a
+ * ulist to do temporary work, and frees it before returning.
*
- * Returns 0 on success, < 0 on error. On error @ctx->roots is always NULL.
+ * Returns 0 on success, < 0 on error.
*/
static int btrfs_find_all_roots_safe(struct btrfs_backref_walk_ctx *ctx)
{
const u64 orig_bytenr = ctx->bytenr;
const bool orig_ignore_extent_item_pos = ctx->ignore_extent_item_pos;
+ bool roots_ulist_allocated = false;
struct ulist_iterator uiter;
int ret = 0;
ASSERT(ctx->refs == NULL);
- ASSERT(ctx->roots == NULL);
ctx->refs = ulist_alloc(GFP_NOFS);
if (!ctx->refs)
return -ENOMEM;
- ctx->roots = ulist_alloc(GFP_NOFS);
if (!ctx->roots) {
- ulist_free(ctx->refs);
- ctx->refs = NULL;
- return -ENOMEM;
+ ctx->roots = ulist_alloc(GFP_NOFS);
+ if (!ctx->roots) {
+ ulist_free(ctx->refs);
+ ctx->refs = NULL;
+ return -ENOMEM;
+ }
+ roots_ulist_allocated = true;
}
ctx->ignore_extent_item_pos = true;
@@ -1710,8 +1714,10 @@ static int btrfs_find_all_roots_safe(struct btrfs_backref_walk_ctx *ctx)
ret = find_parent_nodes(ctx, NULL);
if (ret < 0 && ret != -ENOENT) {
- ulist_free(ctx->roots);
- ctx->roots = NULL;
+ if (roots_ulist_allocated) {
+ ulist_free(ctx->roots);
+ ctx->roots = NULL;
+ }
break;
}
ret = 0;
@@ -2295,6 +2301,11 @@ int iterate_extent_inodes(struct btrfs_backref_walk_ctx *ctx,
ctx->bytenr);
ASSERT(ctx->trans == NULL);
+ ASSERT(ctx->roots == NULL);
+
+ ctx->roots = ulist_alloc(GFP_NOFS);
+ if (!ctx->roots)
+ return -ENOMEM;
if (!search_commit_root) {
struct btrfs_trans_handle *trans;
@@ -2302,8 +2313,11 @@ int iterate_extent_inodes(struct btrfs_backref_walk_ctx *ctx,
trans = btrfs_attach_transaction(ctx->fs_info->tree_root);
if (IS_ERR(trans)) {
if (PTR_ERR(trans) != -ENOENT &&
- PTR_ERR(trans) != -EROFS)
+ PTR_ERR(trans) != -EROFS) {
+ ulist_free(ctx->roots);
+ ctx->roots = NULL;
return PTR_ERR(trans);
+ }
trans = NULL;
}
ctx->trans = trans;
@@ -2344,8 +2358,7 @@ int iterate_extent_inodes(struct btrfs_backref_walk_ctx *ctx,
root_node->val, ctx->bytenr,
iterate, user_ctx);
}
- ulist_free(ctx->roots);
- ctx->roots = NULL;
+ ulist_reinit(ctx->roots);
}
free_leaf_list(refs);
@@ -2358,6 +2371,9 @@ out:
up_read(&ctx->fs_info->commit_root_sem);
}
+ ulist_free(ctx->roots);
+ ctx->roots = NULL;
+
return ret;
}