Commit 0d73a11c authored by Josef Bacik's avatar Josef Bacik Committed by David Sterba

btrfs: ref-verify: pass down tree block level when building refs

I noticed that sometimes I would have the wrong level printed out with
ref-verify while testing some error injection related problems.  This is
because we only get the level from the main extent item, but our
references could go off the current leaf into another, and at that point
we lose our level.

Fix this by keeping track of the last tree block level that we found,
the same way we keep track of our bytenr and num_bytes, in case we
happen to wander into another leaf while still processing the references
for a bytenr.
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 1fec12a5
...@@ -495,14 +495,15 @@ static int process_extent_item(struct btrfs_fs_info *fs_info, ...@@ -495,14 +495,15 @@ static int process_extent_item(struct btrfs_fs_info *fs_info,
} }
static int process_leaf(struct btrfs_root *root, static int process_leaf(struct btrfs_root *root,
struct btrfs_path *path, u64 *bytenr, u64 *num_bytes) struct btrfs_path *path, u64 *bytenr, u64 *num_bytes,
int *tree_block_level)
{ {
struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_fs_info *fs_info = root->fs_info;
struct extent_buffer *leaf = path->nodes[0]; struct extent_buffer *leaf = path->nodes[0];
struct btrfs_extent_data_ref *dref; struct btrfs_extent_data_ref *dref;
struct btrfs_shared_data_ref *sref; struct btrfs_shared_data_ref *sref;
u32 count; u32 count;
int i = 0, tree_block_level = 0, ret = 0; int i = 0, ret = 0;
struct btrfs_key key; struct btrfs_key key;
int nritems = btrfs_header_nritems(leaf); int nritems = btrfs_header_nritems(leaf);
...@@ -515,15 +516,15 @@ static int process_leaf(struct btrfs_root *root, ...@@ -515,15 +516,15 @@ static int process_leaf(struct btrfs_root *root,
case BTRFS_METADATA_ITEM_KEY: case BTRFS_METADATA_ITEM_KEY:
*bytenr = key.objectid; *bytenr = key.objectid;
ret = process_extent_item(fs_info, path, &key, i, ret = process_extent_item(fs_info, path, &key, i,
&tree_block_level); tree_block_level);
break; break;
case BTRFS_TREE_BLOCK_REF_KEY: case BTRFS_TREE_BLOCK_REF_KEY:
ret = add_tree_block(fs_info, key.offset, 0, ret = add_tree_block(fs_info, key.offset, 0,
key.objectid, tree_block_level); key.objectid, *tree_block_level);
break; break;
case BTRFS_SHARED_BLOCK_REF_KEY: case BTRFS_SHARED_BLOCK_REF_KEY:
ret = add_tree_block(fs_info, 0, key.offset, ret = add_tree_block(fs_info, 0, key.offset,
key.objectid, tree_block_level); key.objectid, *tree_block_level);
break; break;
case BTRFS_EXTENT_DATA_REF_KEY: case BTRFS_EXTENT_DATA_REF_KEY:
dref = btrfs_item_ptr(leaf, i, dref = btrfs_item_ptr(leaf, i,
...@@ -549,7 +550,8 @@ static int process_leaf(struct btrfs_root *root, ...@@ -549,7 +550,8 @@ static int process_leaf(struct btrfs_root *root,
/* Walk down to the leaf from the given level */ /* Walk down to the leaf from the given level */
static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path, static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path,
int level, u64 *bytenr, u64 *num_bytes) int level, u64 *bytenr, u64 *num_bytes,
int *tree_block_level)
{ {
struct extent_buffer *eb; struct extent_buffer *eb;
int ret = 0; int ret = 0;
...@@ -565,7 +567,8 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path, ...@@ -565,7 +567,8 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path,
path->slots[level-1] = 0; path->slots[level-1] = 0;
path->locks[level-1] = BTRFS_READ_LOCK; path->locks[level-1] = BTRFS_READ_LOCK;
} else { } else {
ret = process_leaf(root, path, bytenr, num_bytes); ret = process_leaf(root, path, bytenr, num_bytes,
tree_block_level);
if (ret) if (ret)
break; break;
} }
...@@ -974,6 +977,7 @@ int btrfs_build_ref_tree(struct btrfs_fs_info *fs_info) ...@@ -974,6 +977,7 @@ int btrfs_build_ref_tree(struct btrfs_fs_info *fs_info)
{ {
struct btrfs_path *path; struct btrfs_path *path;
struct extent_buffer *eb; struct extent_buffer *eb;
int tree_block_level = 0;
u64 bytenr = 0, num_bytes = 0; u64 bytenr = 0, num_bytes = 0;
int ret, level; int ret, level;
...@@ -998,7 +1002,7 @@ int btrfs_build_ref_tree(struct btrfs_fs_info *fs_info) ...@@ -998,7 +1002,7 @@ int btrfs_build_ref_tree(struct btrfs_fs_info *fs_info)
* different leaf from the original extent item. * different leaf from the original extent item.
*/ */
ret = walk_down_tree(fs_info->extent_root, path, level, ret = walk_down_tree(fs_info->extent_root, path, level,
&bytenr, &num_bytes); &bytenr, &num_bytes, &tree_block_level);
if (ret) if (ret)
break; break;
ret = walk_up_tree(path, &level); ret = walk_up_tree(path, &level);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment