summaryrefslogtreecommitdiff
path: root/fs/btrfs/backref.c
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@suse.com>2022-10-11 15:17:03 +0300
committerDavid Sterba <dsterba@suse.com>2022-12-05 20:00:39 +0300
commit84a7949d409753c90dc3477b8cfc18e983b09078 (patch)
tree4664da13ee756480dc54dda8b0fc9955f7b8cedb /fs/btrfs/backref.c
parent61dbb952f0a5f587c983d88853212e969d2d4ede (diff)
downloadlinux-84a7949d409753c90dc3477b8cfc18e983b09078.tar.xz
btrfs: move ulists to data extent sharedness check context
When calling btrfs_is_data_extent_shared() we pass two ulists that were allocated by the caller. This is because the single caller, fiemap, calls btrfs_is_data_extent_shared() multiple times and the ulists can be reused, instead of allocating new ones before each call and freeing them after each call. Now that we have a context structure/object that we pass to btrfs_is_data_extent_shared(), we can move those ulists to it, and hide their allocation and the context's allocation in a helper function, as well as the freeing of the ulists and the context object. This allows to reduce the number of parameters passed to btrfs_is_data_extent_shared(), the need to pass the ulists from extent_fiemap() to fiemap_process_hole() and having the caller deal with allocating and releasing the ulists. Also rename one of the ulists from 'tmp' / 'tmp_ulist' to 'refs', since that's a much better name as it reflects what the list is used for (and matching the argument name for find_parent_nodes()). 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.c43
1 files changed, 32 insertions, 11 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 693c99ad4afb..4caff3052da7 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -1655,6 +1655,30 @@ static void store_backref_shared_cache(struct btrfs_backref_share_check_ctx *ctx
}
}
+struct btrfs_backref_share_check_ctx *btrfs_alloc_backref_share_check_ctx(void)
+{
+ struct btrfs_backref_share_check_ctx *ctx;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return NULL;
+
+ ulist_init(&ctx->refs);
+ ulist_init(&ctx->roots);
+
+ return ctx;
+}
+
+void btrfs_free_backref_share_ctx(struct btrfs_backref_share_check_ctx *ctx)
+{
+ if (!ctx)
+ return;
+
+ ulist_release(&ctx->refs);
+ ulist_release(&ctx->roots);
+ kfree(ctx);
+}
+
/*
* Check if a data extent is shared or not.
*
@@ -1662,8 +1686,6 @@ static void store_backref_shared_cache(struct btrfs_backref_share_check_ctx *ctx
* @bytenr: Logical bytenr of the extent we are checking.
* @extent_gen: Generation of the extent (file extent item) or 0 if it is
* not known.
- * @roots: List of roots this extent is shared among.
- * @tmp: Temporary list used for iteration.
* @ctx: A backref sharedness check context.
*
* btrfs_is_data_extent_shared uses the backref walking code but will short
@@ -1679,7 +1701,6 @@ static void store_backref_shared_cache(struct btrfs_backref_share_check_ctx *ctx
*/
int btrfs_is_data_extent_shared(struct btrfs_inode *inode, u64 bytenr,
u64 extent_gen,
- struct ulist *roots, struct ulist *tmp,
struct btrfs_backref_share_check_ctx *ctx)
{
struct btrfs_root *root = inode->root;
@@ -1697,8 +1718,8 @@ int btrfs_is_data_extent_shared(struct btrfs_inode *inode, u64 bytenr,
};
int level;
- ulist_init(roots);
- ulist_init(tmp);
+ ulist_init(&ctx->roots);
+ ulist_init(&ctx->refs);
trans = btrfs_join_transaction_nostart(root);
if (IS_ERR(trans)) {
@@ -1720,8 +1741,8 @@ int btrfs_is_data_extent_shared(struct btrfs_inode *inode, u64 bytenr,
bool is_shared;
bool cached;
- ret = find_parent_nodes(trans, fs_info, bytenr, elem.seq, tmp,
- roots, NULL, &shared, false);
+ ret = find_parent_nodes(trans, fs_info, bytenr, elem.seq, &ctx->refs,
+ &ctx->roots, NULL, &shared, false);
if (ret == BACKREF_FOUND_SHARED) {
/* this is the only condition under which we return 1 */
ret = 1;
@@ -1760,13 +1781,13 @@ int btrfs_is_data_extent_shared(struct btrfs_inode *inode, u64 bytenr,
* deal with), we can not use it if we have multiple leaves
* (which implies multiple paths).
*/
- if (level == -1 && tmp->nnodes > 1)
+ if (level == -1 && ctx->refs.nnodes > 1)
ctx->use_path_cache = false;
if (level >= 0)
store_backref_shared_cache(ctx, root, bytenr,
level, false);
- node = ulist_next(tmp, &uiter);
+ node = ulist_next(&ctx->refs, &uiter);
if (!node)
break;
bytenr = node->val;
@@ -1789,8 +1810,8 @@ int btrfs_is_data_extent_shared(struct btrfs_inode *inode, u64 bytenr,
up_read(&fs_info->commit_root_sem);
}
out:
- ulist_release(roots);
- ulist_release(tmp);
+ ulist_release(&ctx->roots);
+ ulist_release(&ctx->refs);
return ret;
}