|
16 | 16 | * Boston, MA 021110-1307, USA. |
17 | 17 | */ |
18 | 18 |
|
| 19 | +#include "kernel-lib/bitops.h" |
| 20 | +#include "kernel-lib/sizes.h" |
19 | 21 | #include "kernel-shared/ctree.h" |
20 | 22 | #include "kernel-shared/disk-io.h" |
21 | 23 | #include "kernel-shared/transaction.h" |
22 | 24 | #include "kernel-shared/print-tree.h" |
23 | | -#include "kernel-lib/bitops.h" |
| 25 | +#include "kernel-shared/tree-checker.h" |
| 26 | +#include "kernel-shared/volumes.h" |
24 | 27 | #include "crypto/crc32c.h" |
25 | 28 | #include "common/internal.h" |
26 | 29 | #include "common/messages.h" |
27 | 30 | #include "common/utils.h" |
28 | | -#include "kernel-lib/sizes.h" |
29 | | -#include "kernel-shared/volumes.h" |
30 | 31 | #include "check/repair.h" |
31 | 32 |
|
32 | 33 | static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root |
@@ -602,185 +603,6 @@ static inline unsigned int leaf_data_end(const struct extent_buffer *leaf) |
602 | 603 | return btrfs_item_offset(leaf, nr - 1); |
603 | 604 | } |
604 | 605 |
|
605 | | -static void generic_err(const struct extent_buffer *buf, int slot, |
606 | | - const char *fmt, ...) |
607 | | -{ |
608 | | - va_list args; |
609 | | - |
610 | | - fprintf(stderr, "corrupt %s: root=%lld block=%llu slot=%d, ", |
611 | | - btrfs_header_level(buf) == 0 ? "leaf": "node", |
612 | | - btrfs_header_owner(buf), btrfs_header_bytenr(buf), slot); |
613 | | - va_start(args, fmt); |
614 | | - vfprintf(stderr, fmt, args); |
615 | | - va_end(args); |
616 | | - fprintf(stderr, "\n"); |
617 | | -} |
618 | | - |
619 | | -enum btrfs_tree_block_status __btrfs_check_node(struct extent_buffer *node) |
620 | | -{ |
621 | | - struct btrfs_fs_info *fs_info = node->fs_info; |
622 | | - unsigned long nr = btrfs_header_nritems(node); |
623 | | - struct btrfs_key key, next_key; |
624 | | - int slot; |
625 | | - int level = btrfs_header_level(node); |
626 | | - u64 bytenr; |
627 | | - enum btrfs_tree_block_status ret = BTRFS_TREE_BLOCK_INVALID_NRITEMS; |
628 | | - |
629 | | - if (level <= 0 || level >= BTRFS_MAX_LEVEL) { |
630 | | - generic_err(node, 0, |
631 | | - "invalid level for node, have %d expect [1, %d]", |
632 | | - level, BTRFS_MAX_LEVEL - 1); |
633 | | - ret = BTRFS_TREE_BLOCK_INVALID_LEVEL; |
634 | | - goto fail; |
635 | | - } |
636 | | - if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(fs_info)) { |
637 | | - generic_err(node, 0, |
638 | | -"corrupt node: root=%llu block=%llu, nritems too %s, have %lu expect range [1,%u]", |
639 | | - btrfs_header_owner(node), node->start, |
640 | | - nr == 0 ? "small" : "large", nr, |
641 | | - BTRFS_NODEPTRS_PER_BLOCK(fs_info)); |
642 | | - ret = BTRFS_TREE_BLOCK_INVALID_NRITEMS; |
643 | | - goto fail; |
644 | | - } |
645 | | - |
646 | | - for (slot = 0; slot < nr - 1; slot++) { |
647 | | - bytenr = btrfs_node_blockptr(node, slot); |
648 | | - btrfs_node_key_to_cpu(node, &key, slot); |
649 | | - btrfs_node_key_to_cpu(node, &next_key, slot + 1); |
650 | | - |
651 | | - if (!bytenr) { |
652 | | - generic_err(node, slot, |
653 | | - "invalid NULL node pointer"); |
654 | | - ret = BTRFS_TREE_BLOCK_INVALID_BLOCKPTR; |
655 | | - goto fail; |
656 | | - } |
657 | | - if (!IS_ALIGNED(bytenr, fs_info->sectorsize)) { |
658 | | - generic_err(node, slot, |
659 | | - "unaligned pointer, have %llu should be aligned to %u", |
660 | | - bytenr, fs_info->sectorsize); |
661 | | - ret = BTRFS_TREE_BLOCK_INVALID_BLOCKPTR; |
662 | | - goto fail; |
663 | | - } |
664 | | - |
665 | | - if (btrfs_comp_cpu_keys(&key, &next_key) >= 0) { |
666 | | - generic_err(node, slot, |
667 | | - "bad key order, current (%llu %u %llu) next (%llu %u %llu)", |
668 | | - key.objectid, key.type, key.offset, |
669 | | - next_key.objectid, next_key.type, |
670 | | - next_key.offset); |
671 | | - ret = BTRFS_TREE_BLOCK_BAD_KEY_ORDER; |
672 | | - goto fail; |
673 | | - } |
674 | | - } |
675 | | - ret = BTRFS_TREE_BLOCK_CLEAN; |
676 | | -fail: |
677 | | - return ret; |
678 | | -} |
679 | | - |
680 | | -enum btrfs_tree_block_status __btrfs_check_leaf(struct extent_buffer *leaf) |
681 | | -{ |
682 | | - struct btrfs_fs_info *fs_info = leaf->fs_info; |
683 | | - /* No valid key type is 0, so all key should be larger than this key */ |
684 | | - struct btrfs_key prev_key = {0, 0, 0}; |
685 | | - struct btrfs_key key; |
686 | | - u32 nritems = btrfs_header_nritems(leaf); |
687 | | - int slot; |
688 | | - int ret; |
689 | | - |
690 | | - if (btrfs_header_level(leaf) != 0) { |
691 | | - generic_err(leaf, 0, |
692 | | - "invalid level for leaf, have %d expect 0", |
693 | | - btrfs_header_level(leaf)); |
694 | | - ret = BTRFS_TREE_BLOCK_INVALID_LEVEL; |
695 | | - goto fail; |
696 | | - } |
697 | | - |
698 | | - if (nritems == 0) |
699 | | - return 0; |
700 | | - |
701 | | - /* |
702 | | - * Check the following things to make sure this is a good leaf, and |
703 | | - * leaf users won't need to bother with similar sanity checks: |
704 | | - * |
705 | | - * 1) key ordering |
706 | | - * 2) item offset and size |
707 | | - * No overlap, no hole, all inside the leaf. |
708 | | - * 3) item content |
709 | | - * If possible, do comprehensive sanity check. |
710 | | - * NOTE: All checks must only rely on the item data itself. |
711 | | - */ |
712 | | - for (slot = 0; slot < nritems; slot++) { |
713 | | - u32 item_end_expected; |
714 | | - u64 item_data_end; |
715 | | - |
716 | | - btrfs_item_key_to_cpu(leaf, &key, slot); |
717 | | - |
718 | | - /* Make sure the keys are in the right order */ |
719 | | - if (btrfs_comp_cpu_keys(&prev_key, &key) >= 0) { |
720 | | - generic_err(leaf, slot, |
721 | | - "bad key order, prev (%llu %u %llu) current (%llu %u %llu)", |
722 | | - prev_key.objectid, prev_key.type, |
723 | | - prev_key.offset, key.objectid, key.type, |
724 | | - key.offset); |
725 | | - ret = BTRFS_TREE_BLOCK_BAD_KEY_ORDER; |
726 | | - goto fail; |
727 | | - } |
728 | | - |
729 | | - item_data_end = (u64)btrfs_item_offset(leaf, slot) + |
730 | | - btrfs_item_size(leaf, slot); |
731 | | - /* |
732 | | - * Make sure the offset and ends are right, remember that the |
733 | | - * item data starts at the end of the leaf and grows towards the |
734 | | - * front. |
735 | | - */ |
736 | | - if (slot == 0) |
737 | | - item_end_expected = BTRFS_LEAF_DATA_SIZE(fs_info); |
738 | | - else |
739 | | - item_end_expected = btrfs_item_offset(leaf, |
740 | | - slot - 1); |
741 | | - if (item_data_end != item_end_expected) { |
742 | | - generic_err(leaf, slot, |
743 | | - "unexpected item end, have %llu expect %u", |
744 | | - item_data_end, item_end_expected); |
745 | | - ret = BTRFS_TREE_BLOCK_INVALID_OFFSETS; |
746 | | - goto fail; |
747 | | - } |
748 | | - |
749 | | - /* |
750 | | - * Check to make sure that we don't point outside of the leaf, |
751 | | - * just in case all the items are consistent to each other, but |
752 | | - * all point outside of the leaf. |
753 | | - */ |
754 | | - if (item_data_end > BTRFS_LEAF_DATA_SIZE(fs_info)) { |
755 | | - generic_err(leaf, slot, |
756 | | - "slot end outside of leaf, have %llu expect range [0, %u]", |
757 | | - item_data_end, BTRFS_LEAF_DATA_SIZE(fs_info)); |
758 | | - ret = BTRFS_TREE_BLOCK_INVALID_OFFSETS; |
759 | | - goto fail; |
760 | | - } |
761 | | - |
762 | | - /* Also check if the item pointer overlaps with btrfs item. */ |
763 | | - if (btrfs_item_ptr_offset(leaf, slot) < |
764 | | - btrfs_item_nr_offset(leaf, slot) + sizeof(struct btrfs_item)) { |
765 | | - generic_err(leaf, slot, |
766 | | - "slot overlaps with its data, item end %lu data start %lu", |
767 | | - btrfs_item_nr_offset(leaf, slot) + |
768 | | - sizeof(struct btrfs_item), |
769 | | - btrfs_item_ptr_offset(leaf, slot)); |
770 | | - ret = BTRFS_TREE_BLOCK_INVALID_OFFSETS; |
771 | | - goto fail; |
772 | | - } |
773 | | - |
774 | | - prev_key.objectid = key.objectid; |
775 | | - prev_key.type = key.type; |
776 | | - prev_key.offset = key.offset; |
777 | | - } |
778 | | - |
779 | | - ret = BTRFS_TREE_BLOCK_CLEAN; |
780 | | -fail: |
781 | | - return ret; |
782 | | -} |
783 | | - |
784 | 606 | static int noinline check_block(struct btrfs_fs_info *fs_info, |
785 | 607 | struct btrfs_path *path, int level) |
786 | 608 | { |
|
0 commit comments