diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/disk-io.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index edda47162752..474209f50844 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -613,6 +613,19 @@ static noinline int check_leaf(struct btrfs_root *root, | |||
613 | return 0; | 613 | return 0; |
614 | } | 614 | } |
615 | 615 | ||
616 | static int check_node(struct btrfs_root *root, struct extent_buffer *node) | ||
617 | { | ||
618 | unsigned long nr = btrfs_header_nritems(node); | ||
619 | |||
620 | if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(root)) { | ||
621 | btrfs_crit(root->fs_info, | ||
622 | "corrupt node: block %llu root %llu nritems %lu", | ||
623 | node->start, root->objectid, nr); | ||
624 | return -EIO; | ||
625 | } | ||
626 | return 0; | ||
627 | } | ||
628 | |||
616 | static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio, | 629 | static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio, |
617 | u64 phy_offset, struct page *page, | 630 | u64 phy_offset, struct page *page, |
618 | u64 start, u64 end, int mirror) | 631 | u64 start, u64 end, int mirror) |
@@ -683,6 +696,9 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio, | |||
683 | ret = -EIO; | 696 | ret = -EIO; |
684 | } | 697 | } |
685 | 698 | ||
699 | if (found_level > 0 && check_node(root, eb)) | ||
700 | ret = -EIO; | ||
701 | |||
686 | if (!ret) | 702 | if (!ret) |
687 | set_extent_buffer_uptodate(eb); | 703 | set_extent_buffer_uptodate(eb); |
688 | err: | 704 | err: |