Commit 562d4254 authored by Josef Bacik's avatar Josef Bacik Committed by David Sterba
Browse files

btrfs: factor out eb uptodate check from do_walk_down()



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: default avatarJosef Bacik <josef@toxicpanda.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 7fcee18d
Loading
Loading
Loading
Loading
+45 −20
Original line number Diff line number Diff line
@@ -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);
	ret = check_next_block_uptodate(trans, root, path, wc, next);
	if (ret)
		return ret;
		}
		btrfs_tree_lock(next);
		wc->lookup_info = 1;
	}

	level--;
	ASSERT(level == btrfs_header_level(next));