^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2017 Oracle. All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Author: Darrick J. Wong <darrick.wong@oracle.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include "xfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include "xfs_fs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "xfs_shared.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "xfs_format.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "xfs_trans_resv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "xfs_mount.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "xfs_btree.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "xfs_alloc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "xfs_rmap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "scrub/scrub.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "scrub/common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "scrub/btree.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Set us up to scrub free space btrees.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) xchk_setup_ag_allocbt(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct xfs_scrub *sc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct xfs_inode *ip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) return xchk_setup_ag_btree(sc, ip, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /* Free space btree scrubber. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * Ensure there's a corresponding cntbt/bnobt record matching this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * bnobt/cntbt record, respectively.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) STATIC void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) xchk_allocbt_xref_other(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct xfs_scrub *sc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) xfs_agblock_t agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) xfs_extlen_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct xfs_btree_cur **pcur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) xfs_agblock_t fbno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) xfs_extlen_t flen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) int has_otherrec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (sc->sm->sm_type == XFS_SCRUB_TYPE_BNOBT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) pcur = &sc->sa.cnt_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) pcur = &sc->sa.bno_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (!*pcur || xchk_skip_xref(sc->sm))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) error = xfs_alloc_lookup_le(*pcur, agbno, len, &has_otherrec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (!xchk_should_check_xref(sc, &error, pcur))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (!has_otherrec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) xchk_btree_xref_set_corrupt(sc, *pcur, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) error = xfs_alloc_get_rec(*pcur, &fbno, &flen, &has_otherrec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (!xchk_should_check_xref(sc, &error, pcur))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (!has_otherrec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) xchk_btree_xref_set_corrupt(sc, *pcur, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (fbno != agbno || flen != len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) xchk_btree_xref_set_corrupt(sc, *pcur, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /* Cross-reference with the other btrees. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) STATIC void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) xchk_allocbt_xref(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct xfs_scrub *sc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) xfs_agblock_t agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) xfs_extlen_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) xchk_allocbt_xref_other(sc, agbno, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) xchk_xref_is_not_inode_chunk(sc, agbno, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) xchk_xref_has_no_owner(sc, agbno, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) xchk_xref_is_not_shared(sc, agbno, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* Scrub a bnobt/cntbt record. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) xchk_allocbt_rec(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct xchk_btree *bs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) union xfs_btree_rec *rec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct xfs_mount *mp = bs->cur->bc_mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) xfs_agnumber_t agno = bs->cur->bc_ag.agno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) xfs_agblock_t bno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) xfs_extlen_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) bno = be32_to_cpu(rec->alloc.ar_startblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) len = be32_to_cpu(rec->alloc.ar_blockcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (bno + len <= bno ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) !xfs_verify_agbno(mp, agno, bno) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) !xfs_verify_agbno(mp, agno, bno + len - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) xchk_allocbt_xref(bs->sc, bno, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* Scrub the freespace btrees for some AG. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) xchk_allocbt(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct xfs_scrub *sc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) xfs_btnum_t which)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct xfs_btree_cur *cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) cur = which == XFS_BTNUM_BNO ? sc->sa.bno_cur : sc->sa.cnt_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return xchk_btree(sc, cur, xchk_allocbt_rec, &XFS_RMAP_OINFO_AG, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) xchk_bnobt(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct xfs_scrub *sc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return xchk_allocbt(sc, XFS_BTNUM_BNO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) xchk_cntbt(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct xfs_scrub *sc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return xchk_allocbt(sc, XFS_BTNUM_CNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* xref check that the extent is not free */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) xchk_xref_is_used_space(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct xfs_scrub *sc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) xfs_agblock_t agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) xfs_extlen_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) bool is_freesp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (!sc->sa.bno_cur || xchk_skip_xref(sc->sm))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) error = xfs_alloc_has_record(sc->sa.bno_cur, agbno, len, &is_freesp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (!xchk_should_check_xref(sc, &error, &sc->sa.bno_cur))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (is_freesp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) xchk_btree_xref_set_corrupt(sc, sc->sa.bno_cur, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }