|
@@ -553,8 +553,9 @@ static noinline int check_leaf(struct btrfs_root *root,
|
|
|
struct extent_buffer *leaf)
|
|
|
{
|
|
|
struct btrfs_fs_info *fs_info = root->fs_info;
|
|
|
+ /* No valid key type is 0, so all key should be larger than this key */
|
|
|
+ struct btrfs_key prev_key = {0, 0, 0};
|
|
|
struct btrfs_key key;
|
|
|
- struct btrfs_key leaf_key;
|
|
|
u32 nritems = btrfs_header_nritems(leaf);
|
|
|
int slot;
|
|
|
|
|
@@ -587,7 +588,7 @@ static noinline int check_leaf(struct btrfs_root *root,
|
|
|
CORRUPT("non-root leaf's nritems is 0",
|
|
|
leaf, check_root, 0);
|
|
|
free_extent_buffer(eb);
|
|
|
- return -EIO;
|
|
|
+ return -EUCLEAN;
|
|
|
}
|
|
|
free_extent_buffer(eb);
|
|
|
}
|
|
@@ -597,28 +598,23 @@ static noinline int check_leaf(struct btrfs_root *root,
|
|
|
if (nritems == 0)
|
|
|
return 0;
|
|
|
|
|
|
- /* Check the 0 item */
|
|
|
- if (btrfs_item_offset_nr(leaf, 0) + btrfs_item_size_nr(leaf, 0) !=
|
|
|
- BTRFS_LEAF_DATA_SIZE(fs_info)) {
|
|
|
- CORRUPT("invalid item offset size pair", leaf, root, 0);
|
|
|
- return -EIO;
|
|
|
- }
|
|
|
-
|
|
|
/*
|
|
|
- * Check to make sure each items keys are in the correct order and their
|
|
|
- * offsets make sense. We only have to loop through nritems-1 because
|
|
|
- * we check the current slot against the next slot, which verifies the
|
|
|
- * next slot's offset+size makes sense and that the current's slot
|
|
|
- * offset is correct.
|
|
|
+ * Check the following things to make sure this is a good leaf, and
|
|
|
+ * leaf users won't need to bother with similar sanity checks:
|
|
|
+ *
|
|
|
+ * 1) key order
|
|
|
+ * 2) item offset and size
|
|
|
+ * No overlap, no hole, all inside the leaf.
|
|
|
*/
|
|
|
- for (slot = 0; slot < nritems - 1; slot++) {
|
|
|
- btrfs_item_key_to_cpu(leaf, &leaf_key, slot);
|
|
|
- btrfs_item_key_to_cpu(leaf, &key, slot + 1);
|
|
|
+ for (slot = 0; slot < nritems; slot++) {
|
|
|
+ u32 item_end_expected;
|
|
|
+
|
|
|
+ btrfs_item_key_to_cpu(leaf, &key, slot);
|
|
|
|
|
|
/* Make sure the keys are in the right order */
|
|
|
- if (btrfs_comp_cpu_keys(&leaf_key, &key) >= 0) {
|
|
|
+ if (btrfs_comp_cpu_keys(&prev_key, &key) >= 0) {
|
|
|
CORRUPT("bad key order", leaf, root, slot);
|
|
|
- return -EIO;
|
|
|
+ return -EUCLEAN;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -626,10 +622,14 @@ static noinline int check_leaf(struct btrfs_root *root,
|
|
|
* item data starts at the end of the leaf and grows towards the
|
|
|
* front.
|
|
|
*/
|
|
|
- if (btrfs_item_offset_nr(leaf, slot) !=
|
|
|
- btrfs_item_end_nr(leaf, slot + 1)) {
|
|
|
+ if (slot == 0)
|
|
|
+ item_end_expected = BTRFS_LEAF_DATA_SIZE(fs_info);
|
|
|
+ else
|
|
|
+ item_end_expected = btrfs_item_offset_nr(leaf,
|
|
|
+ slot - 1);
|
|
|
+ if (btrfs_item_end_nr(leaf, slot) != item_end_expected) {
|
|
|
CORRUPT("slot offset bad", leaf, root, slot);
|
|
|
- return -EIO;
|
|
|
+ return -EUCLEAN;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -640,8 +640,12 @@ static noinline int check_leaf(struct btrfs_root *root,
|
|
|
if (btrfs_item_end_nr(leaf, slot) >
|
|
|
BTRFS_LEAF_DATA_SIZE(fs_info)) {
|
|
|
CORRUPT("slot end outside of leaf", leaf, root, slot);
|
|
|
- return -EIO;
|
|
|
+ return -EUCLEAN;
|
|
|
}
|
|
|
+
|
|
|
+ prev_key.objectid = key.objectid;
|
|
|
+ prev_key.type = key.type;
|
|
|
+ prev_key.offset = key.offset;
|
|
|
}
|
|
|
|
|
|
return 0;
|