btrfs: move ulists to data extent sharedness check context
authorFilipe Manana <fdmanana@suse.com>
Tue, 11 Oct 2022 12:17:03 +0000 (13:17 +0100)
committerDavid Sterba <dsterba@suse.com>
Mon, 5 Dec 2022 17:00:39 +0000 (18:00 +0100)
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>
fs/btrfs/backref.c
fs/btrfs/backref.h
fs/btrfs/extent_io.c

index 693c99ad4afb315a0f1a4c4a51cf112de3f6ce41..4caff3052da77f8bb9b55cfbff8d61e7f5480abf 100644 (file)
@@ -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;
 }
 
index e3a2b45a76e3f893b99ae87249283414e6297562..8da0ba6b94a448f91b6ee4065169e111ef7ea32a 100644 (file)
@@ -24,6 +24,9 @@ struct btrfs_backref_shared_cache_entry {
 };
 
 struct btrfs_backref_share_check_ctx {
+       /* Ulists used during backref walking. */
+       struct ulist refs;
+       struct ulist roots;
        /*
         * A path from a root to a leaf that has a file extent item pointing to
         * a given data extent should never exceed the maximum b+tree height.
@@ -35,6 +38,9 @@ struct btrfs_backref_share_check_ctx {
 typedef int (iterate_extent_inodes_t)(u64 inum, u64 offset, u64 root,
                void *ctx);
 
+struct btrfs_backref_share_check_ctx *btrfs_alloc_backref_share_check_ctx(void);
+void btrfs_free_backref_share_ctx(struct btrfs_backref_share_check_ctx *ctx);
+
 int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
                        struct btrfs_path *path, struct btrfs_key *found_key,
                        u64 *flags);
@@ -79,7 +85,6 @@ int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid,
                          u64 *found_off);
 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);
 
 int __init btrfs_prelim_ref_init(void);
index 365ad00a594286e23ffdae407ee877f21a48c7b1..e25e54d2216f222a6731ae2a436919be620dada7 100644 (file)
@@ -3708,7 +3708,6 @@ static int fiemap_process_hole(struct btrfs_inode *inode,
                               struct btrfs_backref_share_check_ctx *backref_ctx,
                               u64 disk_bytenr, u64 extent_offset,
                               u64 extent_gen,
-                              struct ulist *roots, struct ulist *tmp_ulist,
                               u64 start, u64 end)
 {
        const u64 i_size = i_size_read(&inode->vfs_inode);
@@ -3752,10 +3751,9 @@ static int fiemap_process_hole(struct btrfs_inode *inode,
                if (prealloc_len > 0) {
                        if (!checked_extent_shared && fieinfo->fi_extents_max) {
                                ret = btrfs_is_data_extent_shared(inode,
-                                                         disk_bytenr,
-                                                         extent_gen, roots,
-                                                         tmp_ulist,
-                                                         backref_ctx);
+                                                                 disk_bytenr,
+                                                                 extent_gen,
+                                                                 backref_ctx);
                                if (ret < 0)
                                        return ret;
                                else if (ret > 0)
@@ -3803,8 +3801,7 @@ static int fiemap_process_hole(struct btrfs_inode *inode,
                if (!checked_extent_shared && fieinfo->fi_extents_max) {
                        ret = btrfs_is_data_extent_shared(inode,
                                                          disk_bytenr,
-                                                         extent_gen, roots,
-                                                         tmp_ulist,
+                                                         extent_gen,
                                                          backref_ctx);
                        if (ret < 0)
                                return ret;
@@ -3905,8 +3902,6 @@ int extent_fiemap(struct btrfs_inode *inode, struct fiemap_extent_info *fieinfo,
        struct btrfs_path *path;
        struct fiemap_cache cache = { 0 };
        struct btrfs_backref_share_check_ctx *backref_ctx;
-       struct ulist *roots;
-       struct ulist *tmp_ulist;
        u64 last_extent_end;
        u64 prev_extent_end;
        u64 lockstart;
@@ -3914,11 +3909,9 @@ int extent_fiemap(struct btrfs_inode *inode, struct fiemap_extent_info *fieinfo,
        bool stopped = false;
        int ret;
 
-       backref_ctx = kzalloc(sizeof(*backref_ctx), GFP_KERNEL);
+       backref_ctx = btrfs_alloc_backref_share_check_ctx();
        path = btrfs_alloc_path();
-       roots = ulist_alloc(GFP_KERNEL);
-       tmp_ulist = ulist_alloc(GFP_KERNEL);
-       if (!backref_ctx || !path || !roots || !tmp_ulist) {
+       if (!backref_ctx || !path) {
                ret = -ENOMEM;
                goto out;
        }
@@ -3979,7 +3972,6 @@ int extent_fiemap(struct btrfs_inode *inode, struct fiemap_extent_info *fieinfo,
 
                        ret = fiemap_process_hole(inode, fieinfo, &cache,
                                                  backref_ctx, 0, 0, 0,
-                                                 roots, tmp_ulist,
                                                  prev_extent_end, range_end);
                        if (ret < 0) {
                                goto out_unlock;
@@ -4021,13 +4013,12 @@ int extent_fiemap(struct btrfs_inode *inode, struct fiemap_extent_info *fieinfo,
                        ret = fiemap_process_hole(inode, fieinfo, &cache,
                                                  backref_ctx,
                                                  disk_bytenr, extent_offset,
-                                                 extent_gen, roots, tmp_ulist,
-                                                 key.offset, extent_end - 1);
+                                                 extent_gen, key.offset,
+                                                 extent_end - 1);
                } else if (disk_bytenr == 0) {
                        /* We have an explicit hole. */
                        ret = fiemap_process_hole(inode, fieinfo, &cache,
                                                  backref_ctx, 0, 0, 0,
-                                                 roots, tmp_ulist,
                                                  key.offset, extent_end - 1);
                } else {
                        /* We have a regular extent. */
@@ -4035,8 +4026,6 @@ int extent_fiemap(struct btrfs_inode *inode, struct fiemap_extent_info *fieinfo,
                                ret = btrfs_is_data_extent_shared(inode,
                                                                  disk_bytenr,
                                                                  extent_gen,
-                                                                 roots,
-                                                                 tmp_ulist,
                                                                  backref_ctx);
                                if (ret < 0)
                                        goto out_unlock;
@@ -4087,8 +4076,7 @@ check_eof_delalloc:
 
        if (!stopped && prev_extent_end < lockend) {
                ret = fiemap_process_hole(inode, fieinfo, &cache, backref_ctx,
-                                         0, 0, 0, roots, tmp_ulist,
-                                         prev_extent_end, lockend - 1);
+                                         0, 0, 0, prev_extent_end, lockend - 1);
                if (ret < 0)
                        goto out_unlock;
                prev_extent_end = lockend;
@@ -4119,10 +4107,8 @@ check_eof_delalloc:
 out_unlock:
        unlock_extent(&inode->io_tree, lockstart, lockend, &cached_state);
 out:
-       kfree(backref_ctx);
+       btrfs_free_backref_share_ctx(backref_ctx);
        btrfs_free_path(path);
-       ulist_free(roots);
-       ulist_free(tmp_ulist);
        return ret;
 }