Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ade2e0b3 authored by Wang Shilong's avatar Wang Shilong Committed by Chris Mason
Browse files

Btrfs: fix to search previous metadata extent item since skinny metadata



There is a bug that using btrfs_previous_item() to search metadata extent item.
This is because in btrfs_previous_item(), we need type match, however, since
skinny metada was introduced by josef, we may mix this two types. So just
use btrfs_previous_item() is not working right.

To keep btrfs_previous_item() like normal tree search, i introduce another
function btrfs_previous_extent_item().

Signed-off-by: default avatarWang Shilong <wangsl.fnst@cn.fujitsu.com>
Signed-off-by: default avatarJosef Bacik <jbacik@fb.com>
Signed-off-by: default avatarChris Mason <clm@fb.com>
parent 7c76edb7
Loading
Loading
Loading
Loading
+43 −0
Original line number Original line Diff line number Diff line
@@ -5955,3 +5955,46 @@ int btrfs_previous_item(struct btrfs_root *root,
	}
	}
	return 1;
	return 1;
}
}

/*
 * search in extent tree to find a previous Metadata/Data extent item with
 * min objecitd.
 *
 * returns 0 if something is found, 1 if nothing was found and < 0 on error
 */
int btrfs_previous_extent_item(struct btrfs_root *root,
			struct btrfs_path *path, u64 min_objectid)
{
	struct btrfs_key found_key;
	struct extent_buffer *leaf;
	u32 nritems;
	int ret;

	while (1) {
		if (path->slots[0] == 0) {
			btrfs_set_path_blocking(path);
			ret = btrfs_prev_leaf(root, path);
			if (ret != 0)
				return ret;
		} else {
			path->slots[0]--;
		}
		leaf = path->nodes[0];
		nritems = btrfs_header_nritems(leaf);
		if (nritems == 0)
			return 1;
		if (path->slots[0] == nritems)
			path->slots[0]--;

		btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
		if (found_key.objectid < min_objectid)
			break;
		if (found_key.type == BTRFS_EXTENT_ITEM_KEY ||
		    found_key.type == BTRFS_METADATA_ITEM_KEY)
			return 0;
		if (found_key.objectid == min_objectid &&
		    found_key.type < BTRFS_EXTENT_ITEM_KEY)
			break;
	}
	return 1;
}
+2 −0
Original line number Original line Diff line number Diff line
@@ -3334,6 +3334,8 @@ int btrfs_comp_cpu_keys(struct btrfs_key *k1, struct btrfs_key *k2);
int btrfs_previous_item(struct btrfs_root *root,
int btrfs_previous_item(struct btrfs_root *root,
			struct btrfs_path *path, u64 min_objectid,
			struct btrfs_path *path, u64 min_objectid,
			int type);
			int type);
int btrfs_previous_extent_item(struct btrfs_root *root,
			struct btrfs_path *path, u64 min_objectid);
void btrfs_set_item_key_safe(struct btrfs_root *root, struct btrfs_path *path,
void btrfs_set_item_key_safe(struct btrfs_root *root, struct btrfs_path *path,
			     struct btrfs_key *new_key);
			     struct btrfs_key *new_key);
struct extent_buffer *btrfs_root_node(struct btrfs_root *root);
struct extent_buffer *btrfs_root_node(struct btrfs_root *root);
+1 −2
Original line number Original line Diff line number Diff line
@@ -2385,8 +2385,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
			goto out;
			goto out;


		if (ret > 0) {
		if (ret > 0) {
			ret = btrfs_previous_item(root, path, 0,
			ret = btrfs_previous_extent_item(root, path, 0);
						  BTRFS_EXTENT_ITEM_KEY);
			if (ret < 0)
			if (ret < 0)
				goto out;
				goto out;
			if (ret > 0) {
			if (ret > 0) {