btrfs: factor out eb uptodate check from do_walk_down()
authorJosef Bacik <josef@toxicpanda.com>
Tue, 7 May 2024 18:12:06 +0000 (14:12 -0400)
committerDavid Sterba <dsterba@suse.com>
Thu, 11 Jul 2024 13:33:24 +0000 (15:33 +0200)
do_walk_down() already has a bunch of things going on, and there's a bit
of code related to reading in the next eb if we decide we need it.  Move
this code off into it's own helper to clean up do_walk_down() a little
bit.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/extent-tree.c

index e72b7e8..4a516ad 100644 (file)
@@ -5409,6 +5409,48 @@ static int check_ref_exists(struct btrfs_trans_handle *trans,
        return 1;
 }
 
+/*
+ * We may not have an uptodate block, so if we are going to walk down into this
+ * block we need to drop the lock, read it off of the disk, re-lock it and
+ * return to continue dropping the snapshot.
+ */
+static int check_next_block_uptodate(struct btrfs_trans_handle *trans,
+                                    struct btrfs_root *root,
+                                    struct btrfs_path *path,
+                                    struct walk_control *wc,
+                                    struct extent_buffer *next)
+{
+       struct btrfs_tree_parent_check check = { 0 };
+       u64 generation;
+       int level = wc->level;
+       int ret;
+
+       btrfs_assert_tree_write_locked(next);
+
+       generation = btrfs_node_ptr_generation(path->nodes[level], path->slots[level]);
+
+       if (btrfs_buffer_uptodate(next, generation, 0))
+               return 0;
+
+       check.level = level - 1;
+       check.transid = generation;
+       check.owner_root = btrfs_root_id(root);
+       check.has_first_key = true;
+       btrfs_node_key_to_cpu(path->nodes[level], &check.first_key, path->slots[level]);
+
+       btrfs_tree_unlock(next);
+       if (level == 1)
+               reada_walk_down(trans, root, wc, path);
+       ret = btrfs_read_extent_buffer(next, &check);
+       if (ret) {
+               free_extent_buffer(next);
+               return ret;
+       }
+       btrfs_tree_lock(next);
+       wc->lookup_info = 1;
+       return 0;
+}
+
 /*
  * helper to process tree block pointer.
  *
@@ -5431,7 +5473,6 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
        u64 bytenr;
        u64 generation;
        u64 owner_root = 0;
-       struct btrfs_tree_parent_check check = { 0 };
        struct btrfs_key key;
        struct extent_buffer *next;
        int level = wc->level;
@@ -5453,13 +5494,6 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
 
        bytenr = btrfs_node_blockptr(path->nodes[level], path->slots[level]);
 
-       check.level = level - 1;
-       check.transid = generation;
-       check.owner_root = btrfs_root_id(root);
-       check.has_first_key = true;
-       btrfs_node_key_to_cpu(path->nodes[level], &check.first_key,
-                             path->slots[level]);
-
        next = btrfs_find_create_tree_block(fs_info, bytenr, btrfs_root_id(root),
                                            level - 1);
        if (IS_ERR(next))
@@ -5507,18 +5541,9 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
                        goto skip;
        }
 
-       if (!btrfs_buffer_uptodate(next, generation, 0)) {
-               btrfs_tree_unlock(next);
-               if (level == 1)
-                       reada_walk_down(trans, root, wc, path);
-               ret = btrfs_read_extent_buffer(next, &check);
-               if (ret) {
-                       free_extent_buffer(next);
-                       return ret;
-               }
-               btrfs_tree_lock(next);
-               wc->lookup_info = 1;
-       }
+       ret = check_next_block_uptodate(trans, root, path, wc, next);
+       if (ret)
+               return ret;
 
        level--;
        ASSERT(level == btrfs_header_level(next));