diff mbox series

[12/18] btrfs: reuse roots ulist on each leaf iteration for iterate_extent_inodes()

Message ID d5cc4e67f439b02572fa5899b95a08c6f83967f0.1667315100.git.fdmanana@suse.com (mailing list archive)
State New, archived
Headers show
Series btrfs: make send scale and perform better with shared extents | expand

Commit Message

Filipe Manana Nov. 1, 2022, 4:15 p.m. UTC
From: Filipe Manana <fdmanana@suse.com>

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>
---
 fs/btrfs/backref.c | 46 +++++++++++++++++++++++++++++++---------------
 1 file changed, 31 insertions(+), 15 deletions(-)
diff mbox series

Patch

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 @@  int iterate_extent_inodes(struct btrfs_backref_walk_ctx *ctx,
 		up_read(&ctx->fs_info->commit_root_sem);
 	}
 
+	ulist_free(ctx->roots);
+	ctx->roots = NULL;
+
 	return ret;
 }