diff options
Diffstat (limited to 'fs/btrfs/disk-io.c')
| -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: |
