.. | .. |
---|
9 | 9 | #include "xfs_format.h" |
---|
10 | 10 | #include "xfs_trans_resv.h" |
---|
11 | 11 | #include "xfs_mount.h" |
---|
12 | | -#include "xfs_defer.h" |
---|
13 | 12 | #include "xfs_btree.h" |
---|
14 | | -#include "xfs_bit.h" |
---|
15 | | -#include "xfs_log_format.h" |
---|
16 | | -#include "xfs_trans.h" |
---|
17 | 13 | #include "xfs_sb.h" |
---|
18 | | -#include "xfs_inode.h" |
---|
19 | 14 | #include "xfs_alloc.h" |
---|
20 | 15 | #include "xfs_ialloc.h" |
---|
21 | 16 | #include "xfs_rmap.h" |
---|
22 | | -#include "scrub/xfs_scrub.h" |
---|
23 | 17 | #include "scrub/scrub.h" |
---|
24 | 18 | #include "scrub/common.h" |
---|
25 | | -#include "scrub/trace.h" |
---|
26 | 19 | |
---|
27 | 20 | /* Superblock */ |
---|
28 | 21 | |
---|
.. | .. |
---|
32 | 25 | struct xfs_scrub *sc, |
---|
33 | 26 | struct xfs_buf *bp) |
---|
34 | 27 | { |
---|
35 | | - struct xfs_owner_info oinfo; |
---|
36 | 28 | struct xfs_mount *mp = sc->mp; |
---|
37 | 29 | xfs_agnumber_t agno = sc->sm->sm_agno; |
---|
38 | 30 | xfs_agblock_t agbno; |
---|
.. | .. |
---|
49 | 41 | |
---|
50 | 42 | xchk_xref_is_used_space(sc, agbno, 1); |
---|
51 | 43 | xchk_xref_is_not_inode_chunk(sc, agbno, 1); |
---|
52 | | - xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_FS); |
---|
53 | | - xchk_xref_is_owned_by(sc, agbno, 1, &oinfo); |
---|
| 44 | + xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS); |
---|
54 | 45 | xchk_xref_is_not_shared(sc, agbno, 1); |
---|
55 | 46 | |
---|
56 | 47 | /* scrub teardown will take care of sc->sa for us */ |
---|
.. | .. |
---|
101 | 92 | if (!xchk_process_error(sc, agno, XFS_SB_BLOCK(mp), &error)) |
---|
102 | 93 | return error; |
---|
103 | 94 | |
---|
104 | | - sb = XFS_BUF_TO_SBP(bp); |
---|
| 95 | + sb = bp->b_addr; |
---|
105 | 96 | |
---|
106 | 97 | /* |
---|
107 | 98 | * Verify the geometries match. Fields that are permanently |
---|
.. | .. |
---|
367 | 358 | xchk_agf_xref_freeblks( |
---|
368 | 359 | struct xfs_scrub *sc) |
---|
369 | 360 | { |
---|
370 | | - struct xfs_agf *agf = XFS_BUF_TO_AGF(sc->sa.agf_bp); |
---|
| 361 | + struct xfs_agf *agf = sc->sa.agf_bp->b_addr; |
---|
371 | 362 | xfs_extlen_t blocks = 0; |
---|
372 | 363 | int error; |
---|
373 | 364 | |
---|
.. | .. |
---|
387 | 378 | xchk_agf_xref_cntbt( |
---|
388 | 379 | struct xfs_scrub *sc) |
---|
389 | 380 | { |
---|
390 | | - struct xfs_agf *agf = XFS_BUF_TO_AGF(sc->sa.agf_bp); |
---|
| 381 | + struct xfs_agf *agf = sc->sa.agf_bp->b_addr; |
---|
391 | 382 | xfs_agblock_t agbno; |
---|
392 | 383 | xfs_extlen_t blocks; |
---|
393 | 384 | int have; |
---|
.. | .. |
---|
401 | 392 | if (!xchk_should_check_xref(sc, &error, &sc->sa.cnt_cur)) |
---|
402 | 393 | return; |
---|
403 | 394 | if (!have) { |
---|
404 | | - if (agf->agf_freeblks != be32_to_cpu(0)) |
---|
| 395 | + if (agf->agf_freeblks != cpu_to_be32(0)) |
---|
405 | 396 | xchk_block_xref_set_corrupt(sc, sc->sa.agf_bp); |
---|
406 | 397 | return; |
---|
407 | 398 | } |
---|
.. | .. |
---|
419 | 410 | xchk_agf_xref_btreeblks( |
---|
420 | 411 | struct xfs_scrub *sc) |
---|
421 | 412 | { |
---|
422 | | - struct xfs_agf *agf = XFS_BUF_TO_AGF(sc->sa.agf_bp); |
---|
| 413 | + struct xfs_agf *agf = sc->sa.agf_bp->b_addr; |
---|
423 | 414 | struct xfs_mount *mp = sc->mp; |
---|
424 | 415 | xfs_agblock_t blocks; |
---|
425 | 416 | xfs_agblock_t btreeblks; |
---|
.. | .. |
---|
465 | 456 | xchk_agf_xref_refcblks( |
---|
466 | 457 | struct xfs_scrub *sc) |
---|
467 | 458 | { |
---|
468 | | - struct xfs_agf *agf = XFS_BUF_TO_AGF(sc->sa.agf_bp); |
---|
| 459 | + struct xfs_agf *agf = sc->sa.agf_bp->b_addr; |
---|
469 | 460 | xfs_agblock_t blocks; |
---|
470 | 461 | int error; |
---|
471 | 462 | |
---|
.. | .. |
---|
484 | 475 | xchk_agf_xref( |
---|
485 | 476 | struct xfs_scrub *sc) |
---|
486 | 477 | { |
---|
487 | | - struct xfs_owner_info oinfo; |
---|
488 | 478 | struct xfs_mount *mp = sc->mp; |
---|
489 | 479 | xfs_agblock_t agbno; |
---|
490 | 480 | int error; |
---|
.. | .. |
---|
502 | 492 | xchk_agf_xref_freeblks(sc); |
---|
503 | 493 | xchk_agf_xref_cntbt(sc); |
---|
504 | 494 | xchk_xref_is_not_inode_chunk(sc, agbno, 1); |
---|
505 | | - xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_FS); |
---|
506 | | - xchk_xref_is_owned_by(sc, agbno, 1, &oinfo); |
---|
| 495 | + xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS); |
---|
507 | 496 | xchk_agf_xref_btreeblks(sc); |
---|
508 | 497 | xchk_xref_is_not_shared(sc, agbno, 1); |
---|
509 | 498 | xchk_agf_xref_refcblks(sc); |
---|
.. | .. |
---|
518 | 507 | { |
---|
519 | 508 | struct xfs_mount *mp = sc->mp; |
---|
520 | 509 | struct xfs_agf *agf; |
---|
| 510 | + struct xfs_perag *pag; |
---|
521 | 511 | xfs_agnumber_t agno; |
---|
522 | 512 | xfs_agblock_t agbno; |
---|
523 | 513 | xfs_agblock_t eoag; |
---|
.. | .. |
---|
535 | 525 | goto out; |
---|
536 | 526 | xchk_buffer_recheck(sc, sc->sa.agf_bp); |
---|
537 | 527 | |
---|
538 | | - agf = XFS_BUF_TO_AGF(sc->sa.agf_bp); |
---|
| 528 | + agf = sc->sa.agf_bp->b_addr; |
---|
539 | 529 | |
---|
540 | 530 | /* Check the AG length */ |
---|
541 | 531 | eoag = be32_to_cpu(agf->agf_length); |
---|
.. | .. |
---|
590 | 580 | if (agfl_count != 0 && fl_count != agfl_count) |
---|
591 | 581 | xchk_block_set_corrupt(sc, sc->sa.agf_bp); |
---|
592 | 582 | |
---|
| 583 | + /* Do the incore counters match? */ |
---|
| 584 | + pag = xfs_perag_get(mp, agno); |
---|
| 585 | + if (pag->pagf_freeblks != be32_to_cpu(agf->agf_freeblks)) |
---|
| 586 | + xchk_block_set_corrupt(sc, sc->sa.agf_bp); |
---|
| 587 | + if (pag->pagf_flcount != be32_to_cpu(agf->agf_flcount)) |
---|
| 588 | + xchk_block_set_corrupt(sc, sc->sa.agf_bp); |
---|
| 589 | + if (pag->pagf_btreeblks != be32_to_cpu(agf->agf_btreeblks)) |
---|
| 590 | + xchk_block_set_corrupt(sc, sc->sa.agf_bp); |
---|
| 591 | + xfs_perag_put(pag); |
---|
| 592 | + |
---|
593 | 593 | xchk_agf_xref(sc); |
---|
594 | 594 | out: |
---|
595 | 595 | return error; |
---|
.. | .. |
---|
598 | 598 | /* AGFL */ |
---|
599 | 599 | |
---|
600 | 600 | struct xchk_agfl_info { |
---|
601 | | - struct xfs_owner_info oinfo; |
---|
602 | 601 | unsigned int sz_entries; |
---|
603 | 602 | unsigned int nr_entries; |
---|
604 | 603 | xfs_agblock_t *entries; |
---|
.. | .. |
---|
609 | 608 | STATIC void |
---|
610 | 609 | xchk_agfl_block_xref( |
---|
611 | 610 | struct xfs_scrub *sc, |
---|
612 | | - xfs_agblock_t agbno, |
---|
613 | | - struct xfs_owner_info *oinfo) |
---|
| 611 | + xfs_agblock_t agbno) |
---|
614 | 612 | { |
---|
615 | 613 | if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) |
---|
616 | 614 | return; |
---|
617 | 615 | |
---|
618 | 616 | xchk_xref_is_used_space(sc, agbno, 1); |
---|
619 | 617 | xchk_xref_is_not_inode_chunk(sc, agbno, 1); |
---|
620 | | - xchk_xref_is_owned_by(sc, agbno, 1, oinfo); |
---|
| 618 | + xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_AG); |
---|
621 | 619 | xchk_xref_is_not_shared(sc, agbno, 1); |
---|
622 | 620 | } |
---|
623 | 621 | |
---|
.. | .. |
---|
638 | 636 | else |
---|
639 | 637 | xchk_block_set_corrupt(sc, sc->sa.agfl_bp); |
---|
640 | 638 | |
---|
641 | | - xchk_agfl_block_xref(sc, agbno, priv); |
---|
| 639 | + xchk_agfl_block_xref(sc, agbno); |
---|
642 | 640 | |
---|
643 | 641 | if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) |
---|
644 | | - return XFS_BTREE_QUERY_RANGE_ABORT; |
---|
| 642 | + return -ECANCELED; |
---|
645 | 643 | |
---|
646 | 644 | return 0; |
---|
647 | 645 | } |
---|
.. | .. |
---|
662 | 660 | xchk_agfl_xref( |
---|
663 | 661 | struct xfs_scrub *sc) |
---|
664 | 662 | { |
---|
665 | | - struct xfs_owner_info oinfo; |
---|
666 | 663 | struct xfs_mount *mp = sc->mp; |
---|
667 | 664 | xfs_agblock_t agbno; |
---|
668 | 665 | int error; |
---|
.. | .. |
---|
678 | 675 | |
---|
679 | 676 | xchk_xref_is_used_space(sc, agbno, 1); |
---|
680 | 677 | xchk_xref_is_not_inode_chunk(sc, agbno, 1); |
---|
681 | | - xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_FS); |
---|
682 | | - xchk_xref_is_owned_by(sc, agbno, 1, &oinfo); |
---|
| 678 | + xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS); |
---|
683 | 679 | xchk_xref_is_not_shared(sc, agbno, 1); |
---|
684 | 680 | |
---|
685 | 681 | /* |
---|
.. | .. |
---|
715 | 711 | goto out; |
---|
716 | 712 | |
---|
717 | 713 | /* Allocate buffer to ensure uniqueness of AGFL entries. */ |
---|
718 | | - agf = XFS_BUF_TO_AGF(sc->sa.agf_bp); |
---|
| 714 | + agf = sc->sa.agf_bp->b_addr; |
---|
719 | 715 | agflcount = be32_to_cpu(agf->agf_flcount); |
---|
720 | 716 | if (agflcount > xfs_agfl_size(sc->mp)) { |
---|
721 | 717 | xchk_block_set_corrupt(sc, sc->sa.agf_bp); |
---|
.. | .. |
---|
732 | 728 | } |
---|
733 | 729 | |
---|
734 | 730 | /* Check the blocks in the AGFL. */ |
---|
735 | | - xfs_rmap_ag_owner(&sai.oinfo, XFS_RMAP_OWN_AG); |
---|
736 | | - error = xfs_agfl_walk(sc->mp, XFS_BUF_TO_AGF(sc->sa.agf_bp), |
---|
| 731 | + error = xfs_agfl_walk(sc->mp, sc->sa.agf_bp->b_addr, |
---|
737 | 732 | sc->sa.agfl_bp, xchk_agfl_block, &sai); |
---|
738 | | - if (error == XFS_BTREE_QUERY_RANGE_ABORT) { |
---|
| 733 | + if (error == -ECANCELED) { |
---|
739 | 734 | error = 0; |
---|
740 | 735 | goto out_free; |
---|
741 | 736 | } |
---|
.. | .. |
---|
770 | 765 | xchk_agi_xref_icounts( |
---|
771 | 766 | struct xfs_scrub *sc) |
---|
772 | 767 | { |
---|
773 | | - struct xfs_agi *agi = XFS_BUF_TO_AGI(sc->sa.agi_bp); |
---|
| 768 | + struct xfs_agi *agi = sc->sa.agi_bp->b_addr; |
---|
774 | 769 | xfs_agino_t icount; |
---|
775 | 770 | xfs_agino_t freecount; |
---|
776 | 771 | int error; |
---|
.. | .. |
---|
786 | 781 | xchk_block_xref_set_corrupt(sc, sc->sa.agi_bp); |
---|
787 | 782 | } |
---|
788 | 783 | |
---|
| 784 | +/* Check agi_[fi]blocks against tree size */ |
---|
| 785 | +static inline void |
---|
| 786 | +xchk_agi_xref_fiblocks( |
---|
| 787 | + struct xfs_scrub *sc) |
---|
| 788 | +{ |
---|
| 789 | + struct xfs_agi *agi = sc->sa.agi_bp->b_addr; |
---|
| 790 | + xfs_agblock_t blocks; |
---|
| 791 | + int error = 0; |
---|
| 792 | + |
---|
| 793 | + if (!xfs_sb_version_hasinobtcounts(&sc->mp->m_sb)) |
---|
| 794 | + return; |
---|
| 795 | + |
---|
| 796 | + if (sc->sa.ino_cur) { |
---|
| 797 | + error = xfs_btree_count_blocks(sc->sa.ino_cur, &blocks); |
---|
| 798 | + if (!xchk_should_check_xref(sc, &error, &sc->sa.ino_cur)) |
---|
| 799 | + return; |
---|
| 800 | + if (blocks != be32_to_cpu(agi->agi_iblocks)) |
---|
| 801 | + xchk_block_xref_set_corrupt(sc, sc->sa.agi_bp); |
---|
| 802 | + } |
---|
| 803 | + |
---|
| 804 | + if (sc->sa.fino_cur) { |
---|
| 805 | + error = xfs_btree_count_blocks(sc->sa.fino_cur, &blocks); |
---|
| 806 | + if (!xchk_should_check_xref(sc, &error, &sc->sa.fino_cur)) |
---|
| 807 | + return; |
---|
| 808 | + if (blocks != be32_to_cpu(agi->agi_fblocks)) |
---|
| 809 | + xchk_block_xref_set_corrupt(sc, sc->sa.agi_bp); |
---|
| 810 | + } |
---|
| 811 | +} |
---|
| 812 | + |
---|
789 | 813 | /* Cross-reference with the other btrees. */ |
---|
790 | 814 | STATIC void |
---|
791 | 815 | xchk_agi_xref( |
---|
792 | 816 | struct xfs_scrub *sc) |
---|
793 | 817 | { |
---|
794 | | - struct xfs_owner_info oinfo; |
---|
795 | 818 | struct xfs_mount *mp = sc->mp; |
---|
796 | 819 | xfs_agblock_t agbno; |
---|
797 | 820 | int error; |
---|
.. | .. |
---|
808 | 831 | xchk_xref_is_used_space(sc, agbno, 1); |
---|
809 | 832 | xchk_xref_is_not_inode_chunk(sc, agbno, 1); |
---|
810 | 833 | xchk_agi_xref_icounts(sc); |
---|
811 | | - xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_FS); |
---|
812 | | - xchk_xref_is_owned_by(sc, agbno, 1, &oinfo); |
---|
| 834 | + xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS); |
---|
813 | 835 | xchk_xref_is_not_shared(sc, agbno, 1); |
---|
| 836 | + xchk_agi_xref_fiblocks(sc); |
---|
814 | 837 | |
---|
815 | 838 | /* scrub teardown will take care of sc->sa for us */ |
---|
816 | 839 | } |
---|
.. | .. |
---|
822 | 845 | { |
---|
823 | 846 | struct xfs_mount *mp = sc->mp; |
---|
824 | 847 | struct xfs_agi *agi; |
---|
| 848 | + struct xfs_perag *pag; |
---|
825 | 849 | xfs_agnumber_t agno; |
---|
826 | 850 | xfs_agblock_t agbno; |
---|
827 | 851 | xfs_agblock_t eoag; |
---|
.. | .. |
---|
840 | 864 | goto out; |
---|
841 | 865 | xchk_buffer_recheck(sc, sc->sa.agi_bp); |
---|
842 | 866 | |
---|
843 | | - agi = XFS_BUF_TO_AGI(sc->sa.agi_bp); |
---|
| 867 | + agi = sc->sa.agi_bp->b_addr; |
---|
844 | 868 | |
---|
845 | 869 | /* Check the AG length */ |
---|
846 | 870 | eoag = be32_to_cpu(agi->agi_length); |
---|
.. | .. |
---|
875 | 899 | |
---|
876 | 900 | /* Check inode pointers */ |
---|
877 | 901 | agino = be32_to_cpu(agi->agi_newino); |
---|
878 | | - if (agino != NULLAGINO && !xfs_verify_agino(mp, agno, agino)) |
---|
| 902 | + if (!xfs_verify_agino_or_null(mp, agno, agino)) |
---|
879 | 903 | xchk_block_set_corrupt(sc, sc->sa.agi_bp); |
---|
880 | 904 | |
---|
881 | 905 | agino = be32_to_cpu(agi->agi_dirino); |
---|
882 | | - if (agino != NULLAGINO && !xfs_verify_agino(mp, agno, agino)) |
---|
| 906 | + if (!xfs_verify_agino_or_null(mp, agno, agino)) |
---|
883 | 907 | xchk_block_set_corrupt(sc, sc->sa.agi_bp); |
---|
884 | 908 | |
---|
885 | 909 | /* Check unlinked inode buckets */ |
---|
886 | 910 | for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) { |
---|
887 | 911 | agino = be32_to_cpu(agi->agi_unlinked[i]); |
---|
888 | | - if (agino == NULLAGINO) |
---|
889 | | - continue; |
---|
890 | | - if (!xfs_verify_agino(mp, agno, agino)) |
---|
| 912 | + if (!xfs_verify_agino_or_null(mp, agno, agino)) |
---|
891 | 913 | xchk_block_set_corrupt(sc, sc->sa.agi_bp); |
---|
892 | 914 | } |
---|
893 | 915 | |
---|
894 | 916 | if (agi->agi_pad32 != cpu_to_be32(0)) |
---|
895 | 917 | xchk_block_set_corrupt(sc, sc->sa.agi_bp); |
---|
896 | 918 | |
---|
| 919 | + /* Do the incore counters match? */ |
---|
| 920 | + pag = xfs_perag_get(mp, agno); |
---|
| 921 | + if (pag->pagi_count != be32_to_cpu(agi->agi_count)) |
---|
| 922 | + xchk_block_set_corrupt(sc, sc->sa.agi_bp); |
---|
| 923 | + if (pag->pagi_freecount != be32_to_cpu(agi->agi_freecount)) |
---|
| 924 | + xchk_block_set_corrupt(sc, sc->sa.agi_bp); |
---|
| 925 | + xfs_perag_put(pag); |
---|
| 926 | + |
---|
897 | 927 | xchk_agi_xref(sc); |
---|
898 | 928 | out: |
---|
899 | 929 | return error; |
---|