|
@@ -546,9 +546,10 @@ static int check_tree_block_fsid(struct btrfs_fs_info *fs_info,
|
|
|
}
|
|
|
|
|
|
#define CORRUPT(reason, eb, root, slot) \
|
|
|
- btrfs_crit(root->fs_info, "corrupt leaf, %s: block=%llu," \
|
|
|
- "root=%llu, slot=%d", reason, \
|
|
|
- btrfs_header_bytenr(eb), root->objectid, slot)
|
|
|
+ btrfs_crit(root->fs_info, "corrupt %s, %s: block=%llu," \
|
|
|
+ " root=%llu, slot=%d", \
|
|
|
+ btrfs_header_level(eb) == 0 ? "leaf" : "node",\
|
|
|
+ reason, btrfs_header_bytenr(eb), root->objectid, slot)
|
|
|
|
|
|
static noinline int check_leaf(struct btrfs_root *root,
|
|
|
struct extent_buffer *leaf)
|
|
@@ -635,6 +636,10 @@ static noinline int check_leaf(struct btrfs_root *root,
|
|
|
static int check_node(struct btrfs_root *root, struct extent_buffer *node)
|
|
|
{
|
|
|
unsigned long nr = btrfs_header_nritems(node);
|
|
|
+ struct btrfs_key key, next_key;
|
|
|
+ int slot;
|
|
|
+ u64 bytenr;
|
|
|
+ int ret = 0;
|
|
|
|
|
|
if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(root)) {
|
|
|
btrfs_crit(root->fs_info,
|
|
@@ -642,7 +647,26 @@ static int check_node(struct btrfs_root *root, struct extent_buffer *node)
|
|
|
node->start, root->objectid, nr);
|
|
|
return -EIO;
|
|
|
}
|
|
|
- return 0;
|
|
|
+
|
|
|
+ for (slot = 0; slot < nr - 1; slot++) {
|
|
|
+ bytenr = btrfs_node_blockptr(node, slot);
|
|
|
+ btrfs_node_key_to_cpu(node, &key, slot);
|
|
|
+ btrfs_node_key_to_cpu(node, &next_key, slot + 1);
|
|
|
+
|
|
|
+ if (!bytenr) {
|
|
|
+ CORRUPT("invalid item slot", node, root, slot);
|
|
|
+ ret = -EIO;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (btrfs_comp_cpu_keys(&key, &next_key) >= 0) {
|
|
|
+ CORRUPT("bad key order", node, root, slot);
|
|
|
+ ret = -EIO;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ }
|
|
|
+out:
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
|