summaryrefslogtreecommitdiff
path: root/fs/btrfs/tree-checker.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@toxicpanda.com>2023-04-29 16:07:15 -0400
committerDavid Sterba <dsterba@suse.com>2023-06-19 13:59:25 +0200
commit924452c80e81ba96bfc64847e983862016345381 (patch)
tree63d7a6db5b453bbe4ce6b6b7c5e6e6aa109e7c82 /fs/btrfs/tree-checker.c
parentc8d5421563547a4b4ba6fcb9dae6b323dd02b75f (diff)
btrfs: extend btrfs_leaf_check to return btrfs_tree_block_status
Instead of blanket returning -EUCLEAN for all the failures in btrfs_check_leaf, use btrfs_tree_block_status and return the appropriate status for each failure. Rename the helper to __btrfs_check_leaf and then make a wrapper of btrfs_check_leaf that will return -EUCLEAN to non-clean error codes. This will allow us to have the __btrfs_check_leaf variant in btrfs-progs while keeping the behavior in the kernel consistent. Signed-off-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/tree-checker.c')
-rw-r--r--fs/btrfs/tree-checker.c36
1 files changed, 23 insertions, 13 deletions
diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
index 63a1086582a2..870b716b393f 100644
--- a/fs/btrfs/tree-checker.c
+++ b/fs/btrfs/tree-checker.c
@@ -1678,7 +1678,7 @@ static enum btrfs_tree_block_status check_leaf_item(struct extent_buffer *leaf,
return BTRFS_TREE_BLOCK_CLEAN;
}
-int btrfs_check_leaf(struct extent_buffer *leaf)
+enum btrfs_tree_block_status __btrfs_check_leaf(struct extent_buffer *leaf)
{
struct btrfs_fs_info *fs_info = leaf->fs_info;
/* No valid key type is 0, so all key should be larger than this key */
@@ -1691,7 +1691,7 @@ int btrfs_check_leaf(struct extent_buffer *leaf)
generic_err(leaf, 0,
"invalid level for leaf, have %d expect 0",
btrfs_header_level(leaf));
- return -EUCLEAN;
+ return BTRFS_TREE_BLOCK_INVALID_LEVEL;
}
/*
@@ -1714,32 +1714,32 @@ int btrfs_check_leaf(struct extent_buffer *leaf)
generic_err(leaf, 0,
"invalid root, root %llu must never be empty",
owner);
- return -EUCLEAN;
+ return BTRFS_TREE_BLOCK_INVALID_NRITEMS;
}
/* Unknown tree */
if (unlikely(owner == 0)) {
generic_err(leaf, 0,
"invalid owner, root 0 is not defined");
- return -EUCLEAN;
+ return BTRFS_TREE_BLOCK_INVALID_OWNER;
}
/* EXTENT_TREE_V2 can have empty extent trees. */
if (btrfs_fs_incompat(fs_info, EXTENT_TREE_V2))
- return 0;
+ return BTRFS_TREE_BLOCK_CLEAN;
if (unlikely(owner == BTRFS_EXTENT_TREE_OBJECTID)) {
generic_err(leaf, 0,
"invalid root, root %llu must never be empty",
owner);
- return -EUCLEAN;
+ return BTRFS_TREE_BLOCK_INVALID_NRITEMS;
}
- return 0;
+ return BTRFS_TREE_BLOCK_CLEAN;
}
if (unlikely(nritems == 0))
- return 0;
+ return BTRFS_TREE_BLOCK_CLEAN;
/*
* Check the following things to make sure this is a good leaf, and
@@ -1765,7 +1765,7 @@ int btrfs_check_leaf(struct extent_buffer *leaf)
prev_key.objectid, prev_key.type,
prev_key.offset, key.objectid, key.type,
key.offset);
- return -EUCLEAN;
+ return BTRFS_TREE_BLOCK_BAD_KEY_ORDER;
}
item_data_end = (u64)btrfs_item_offset(leaf, slot) +
@@ -1784,7 +1784,7 @@ int btrfs_check_leaf(struct extent_buffer *leaf)
generic_err(leaf, slot,
"unexpected item end, have %llu expect %u",
item_data_end, item_end_expected);
- return -EUCLEAN;
+ return BTRFS_TREE_BLOCK_INVALID_OFFSETS;
}
/*
@@ -1796,7 +1796,7 @@ int btrfs_check_leaf(struct extent_buffer *leaf)
generic_err(leaf, slot,
"slot end outside of leaf, have %llu expect range [0, %u]",
item_data_end, BTRFS_LEAF_DATA_SIZE(fs_info));
- return -EUCLEAN;
+ return BTRFS_TREE_BLOCK_INVALID_OFFSETS;
}
/* Also check if the item pointer overlaps with btrfs item. */
@@ -1807,7 +1807,7 @@ int btrfs_check_leaf(struct extent_buffer *leaf)
btrfs_item_nr_offset(leaf, slot) +
sizeof(struct btrfs_item),
btrfs_item_ptr_offset(leaf, slot));
- return -EUCLEAN;
+ return BTRFS_TREE_BLOCK_INVALID_OFFSETS;
}
/*
@@ -1823,7 +1823,7 @@ int btrfs_check_leaf(struct extent_buffer *leaf)
*/
ret = check_leaf_item(leaf, &key, slot, &prev_key);
if (unlikely(ret != BTRFS_TREE_BLOCK_CLEAN))
- return -EUCLEAN;
+ return ret;
}
prev_key.objectid = key.objectid;
@@ -1831,6 +1831,16 @@ int btrfs_check_leaf(struct extent_buffer *leaf)
prev_key.offset = key.offset;
}
+ return BTRFS_TREE_BLOCK_CLEAN;
+}
+
+int btrfs_check_leaf(struct extent_buffer *leaf)
+{
+ enum btrfs_tree_block_status ret;
+
+ ret = __btrfs_check_leaf(leaf);
+ if (unlikely(ret != BTRFS_TREE_BLOCK_CLEAN))
+ return -EUCLEAN;
return 0;
}
ALLOW_ERROR_INJECTION(btrfs_check_leaf, ERRNO);