^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_log_format.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "xfs_trans.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "xfs_inode.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "xfs_dir2.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "xfs_dir2_priv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "xfs_attr_leaf.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "scrub/scrub.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "scrub/common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "scrub/trace.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "scrub/dabtree.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* Directory/Attribute Btree */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * Check for da btree operation errors. See the section about handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * operational errors in common.c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) xchk_da_process_error(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct xchk_da_btree *ds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) int *error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct xfs_scrub *sc = ds->sc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (*error == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) switch (*error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) case -EDEADLOCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* Used to restart an op with deadlock avoidance. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) trace_xchk_deadlock_retry(sc->ip, sc->sm, *error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) case -EFSBADCRC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) case -EFSCORRUPTED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* Note the badness but don't abort. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) *error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) trace_xchk_file_op_error(sc, ds->dargs.whichfork,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) xfs_dir2_da_to_db(ds->dargs.geo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) ds->state->path.blk[level].blkno),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) *error, __return_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^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) * Check for da btree corruption. See the section about handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * operational errors in common.c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) xchk_da_set_corrupt(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct xchk_da_btree *ds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct xfs_scrub *sc = ds->sc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) trace_xchk_fblock_error(sc, ds->dargs.whichfork,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) xfs_dir2_da_to_db(ds->dargs.geo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) ds->state->path.blk[level].blkno),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) __return_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static struct xfs_da_node_entry *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) xchk_da_btree_node_entry(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct xchk_da_btree *ds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) int level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct xfs_da_state_blk *blk = &ds->state->path.blk[level];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct xfs_da3_icnode_hdr hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) ASSERT(blk->magic == XFS_DA_NODE_MAGIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) xfs_da3_node_hdr_from_disk(ds->sc->mp, &hdr, blk->bp->b_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return hdr.btree + blk->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* Scrub a da btree hash (key). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) xchk_da_btree_hash(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct xchk_da_btree *ds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) int level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) __be32 *hashp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct xfs_da_node_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) xfs_dahash_t hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) xfs_dahash_t parent_hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* Is this hash in order? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) hash = be32_to_cpu(*hashp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (hash < ds->hashes[level])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) xchk_da_set_corrupt(ds, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) ds->hashes[level] = hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (level == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* Is this hash no larger than the parent hash? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) entry = xchk_da_btree_node_entry(ds, level - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) parent_hash = be32_to_cpu(entry->hashval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (parent_hash < hash)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) xchk_da_set_corrupt(ds, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * Check a da btree pointer. Returns true if it's ok to use this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) STATIC bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) xchk_da_btree_ptr_ok(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct xchk_da_btree *ds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) int level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) xfs_dablk_t blkno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (blkno < ds->lowest || (ds->highest != 0 && blkno >= ds->highest)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) xchk_da_set_corrupt(ds, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * The da btree scrubber can handle leaf1 blocks as a degenerate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * form of leafn blocks. Since the regular da code doesn't handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * leaf1, we must multiplex the verifiers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) xchk_da_btree_read_verify(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct xfs_buf *bp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct xfs_da_blkinfo *info = bp->b_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) switch (be16_to_cpu(info->magic)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) case XFS_DIR2_LEAF1_MAGIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) case XFS_DIR3_LEAF1_MAGIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) bp->b_ops = &xfs_dir3_leaf1_buf_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) bp->b_ops->verify_read(bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * xfs_da3_node_buf_ops already know how to handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * DA*_NODE, ATTR*_LEAF, and DIR*_LEAFN blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) bp->b_ops = &xfs_da3_node_buf_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) bp->b_ops->verify_read(bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) xchk_da_btree_write_verify(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct xfs_buf *bp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct xfs_da_blkinfo *info = bp->b_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) switch (be16_to_cpu(info->magic)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) case XFS_DIR2_LEAF1_MAGIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) case XFS_DIR3_LEAF1_MAGIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) bp->b_ops = &xfs_dir3_leaf1_buf_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) bp->b_ops->verify_write(bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * xfs_da3_node_buf_ops already know how to handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * DA*_NODE, ATTR*_LEAF, and DIR*_LEAFN blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) bp->b_ops = &xfs_da3_node_buf_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) bp->b_ops->verify_write(bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static void *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) xchk_da_btree_verify(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct xfs_buf *bp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct xfs_da_blkinfo *info = bp->b_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) switch (be16_to_cpu(info->magic)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) case XFS_DIR2_LEAF1_MAGIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) case XFS_DIR3_LEAF1_MAGIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) bp->b_ops = &xfs_dir3_leaf1_buf_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return bp->b_ops->verify_struct(bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) bp->b_ops = &xfs_da3_node_buf_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return bp->b_ops->verify_struct(bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static const struct xfs_buf_ops xchk_da_btree_buf_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) .name = "xchk_da_btree",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) .verify_read = xchk_da_btree_read_verify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) .verify_write = xchk_da_btree_write_verify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) .verify_struct = xchk_da_btree_verify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /* Check a block's sibling. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) xchk_da_btree_block_check_sibling(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct xchk_da_btree *ds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) int level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) int direction,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) xfs_dablk_t sibling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct xfs_da_state_path *path = &ds->state->path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct xfs_da_state_path *altpath = &ds->state->altpath;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) int plevel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) memcpy(altpath, path, sizeof(ds->state->altpath));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * If the pointer is null, we shouldn't be able to move the upper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * level pointer anywhere.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (sibling == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) error = xfs_da3_path_shift(ds->state, altpath, direction,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) false, &retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (error == 0 && retval == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) xchk_da_set_corrupt(ds, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /* Move the alternate cursor one block in the direction given. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) error = xfs_da3_path_shift(ds->state, altpath, direction, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) &retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (!xchk_da_process_error(ds, level, &error))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) xchk_da_set_corrupt(ds, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (altpath->blk[level].bp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) xchk_buffer_recheck(ds->sc, altpath->blk[level].bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* Compare upper level pointer to sibling pointer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (altpath->blk[level].blkno != sibling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) xchk_da_set_corrupt(ds, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /* Free all buffers in the altpath that aren't referenced from path. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) for (plevel = 0; plevel < altpath->active; plevel++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (altpath->blk[plevel].bp == NULL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) (plevel < path->active &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) altpath->blk[plevel].bp == path->blk[plevel].bp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) xfs_trans_brelse(ds->dargs.trans, altpath->blk[plevel].bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) altpath->blk[plevel].bp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) /* Check a block's sibling pointers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) xchk_da_btree_block_check_siblings(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct xchk_da_btree *ds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) int level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) struct xfs_da_blkinfo *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) xfs_dablk_t forw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) xfs_dablk_t back;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) forw = be32_to_cpu(hdr->forw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) back = be32_to_cpu(hdr->back);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) /* Top level blocks should not have sibling pointers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (level == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (forw != 0 || back != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) xchk_da_set_corrupt(ds, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * Check back (left) and forw (right) pointers. These functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * absorb error codes for us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) error = xchk_da_btree_block_check_sibling(ds, level, 0, back);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) error = xchk_da_btree_block_check_sibling(ds, level, 1, forw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) memset(&ds->state->altpath, 0, sizeof(ds->state->altpath));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) /* Load a dir/attribute block from a btree. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) xchk_da_btree_block(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) struct xchk_da_btree *ds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) int level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) xfs_dablk_t blkno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) struct xfs_da_state_blk *blk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct xfs_da_intnode *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct xfs_da_node_entry *btree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct xfs_da3_blkinfo *hdr3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct xfs_da_args *dargs = &ds->dargs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) struct xfs_inode *ip = ds->dargs.dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) xfs_ino_t owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) int *pmaxrecs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct xfs_da3_icnode_hdr nodehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) blk = &ds->state->path.blk[level];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) ds->state->path.active = level + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /* Release old block. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (blk->bp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) xfs_trans_brelse(dargs->trans, blk->bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) blk->bp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) /* Check the pointer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) blk->blkno = blkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (!xchk_da_btree_ptr_ok(ds, level, blkno))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) goto out_nobuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) /* Read the buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) error = xfs_da_read_buf(dargs->trans, dargs->dp, blk->blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) XFS_DABUF_MAP_HOLE_OK, &blk->bp, dargs->whichfork,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) &xchk_da_btree_buf_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (!xchk_da_process_error(ds, level, &error))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) goto out_nobuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (blk->bp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) xchk_buffer_recheck(ds->sc, blk->bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * We didn't find a dir btree root block, which means that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * there's no LEAF1/LEAFN tree (at least not where it's supposed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * to be), so jump out now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (ds->dargs.whichfork == XFS_DATA_FORK && level == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) blk->bp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) goto out_nobuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) /* It's /not/ ok for attr trees not to have a da btree. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (blk->bp == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) xchk_da_set_corrupt(ds, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) goto out_nobuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) hdr3 = blk->bp->b_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) blk->magic = be16_to_cpu(hdr3->hdr.magic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) pmaxrecs = &ds->maxrecs[level];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) /* We only started zeroing the header on v5 filesystems. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (xfs_sb_version_hascrc(&ds->sc->mp->m_sb) && hdr3->hdr.pad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) xchk_da_set_corrupt(ds, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) /* Check the owner. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (xfs_sb_version_hascrc(&ip->i_mount->m_sb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) owner = be64_to_cpu(hdr3->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (owner != ip->i_ino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) xchk_da_set_corrupt(ds, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /* Check the siblings. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) error = xchk_da_btree_block_check_siblings(ds, level, &hdr3->hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) /* Interpret the buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) switch (blk->magic) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) case XFS_ATTR_LEAF_MAGIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) case XFS_ATTR3_LEAF_MAGIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) xfs_trans_buf_set_type(dargs->trans, blk->bp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) XFS_BLFT_ATTR_LEAF_BUF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) blk->magic = XFS_ATTR_LEAF_MAGIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) blk->hashval = xfs_attr_leaf_lasthash(blk->bp, pmaxrecs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (ds->tree_level != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) xchk_da_set_corrupt(ds, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) case XFS_DIR2_LEAFN_MAGIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) case XFS_DIR3_LEAFN_MAGIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) xfs_trans_buf_set_type(dargs->trans, blk->bp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) XFS_BLFT_DIR_LEAFN_BUF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) blk->magic = XFS_DIR2_LEAFN_MAGIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) blk->hashval = xfs_dir2_leaf_lasthash(ip, blk->bp, pmaxrecs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (ds->tree_level != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) xchk_da_set_corrupt(ds, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) case XFS_DIR2_LEAF1_MAGIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) case XFS_DIR3_LEAF1_MAGIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) xfs_trans_buf_set_type(dargs->trans, blk->bp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) XFS_BLFT_DIR_LEAF1_BUF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) blk->magic = XFS_DIR2_LEAF1_MAGIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) blk->hashval = xfs_dir2_leaf_lasthash(ip, blk->bp, pmaxrecs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (ds->tree_level != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) xchk_da_set_corrupt(ds, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) case XFS_DA_NODE_MAGIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) case XFS_DA3_NODE_MAGIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) xfs_trans_buf_set_type(dargs->trans, blk->bp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) XFS_BLFT_DA_NODE_BUF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) blk->magic = XFS_DA_NODE_MAGIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) node = blk->bp->b_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) xfs_da3_node_hdr_from_disk(ip->i_mount, &nodehdr, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) btree = nodehdr.btree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) *pmaxrecs = nodehdr.count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) blk->hashval = be32_to_cpu(btree[*pmaxrecs - 1].hashval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (level == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (nodehdr.level >= XFS_DA_NODE_MAXDEPTH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) xchk_da_set_corrupt(ds, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) goto out_freebp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) ds->tree_level = nodehdr.level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (ds->tree_level != nodehdr.level) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) xchk_da_set_corrupt(ds, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) goto out_freebp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) /* XXX: Check hdr3.pad32 once we know how to fix it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) xchk_da_set_corrupt(ds, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) goto out_freebp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * If we've been handed a block that is below the dabtree root, does
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * its hashval match what the parent block expected to see?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (level > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) struct xfs_da_node_entry *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) key = xchk_da_btree_node_entry(ds, level - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (be32_to_cpu(key->hashval) != blk->hashval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) xchk_da_set_corrupt(ds, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) goto out_freebp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) out_freebp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) xfs_trans_brelse(dargs->trans, blk->bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) blk->bp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) out_nobuf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) blk->blkno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) /* Visit all nodes and leaves of a da btree. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) xchk_da_btree(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) struct xfs_scrub *sc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) int whichfork,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) xchk_da_btree_rec_fn scrub_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) void *private)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) struct xchk_da_btree ds = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct xfs_mount *mp = sc->mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) struct xfs_da_state_blk *blks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) struct xfs_da_node_entry *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) xfs_dablk_t blkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) int level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) /* Skip short format data structures; no btree to scan. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (!xfs_ifork_has_extents(XFS_IFORK_PTR(sc->ip, whichfork)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) /* Set up initial da state. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) ds.dargs.dp = sc->ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) ds.dargs.whichfork = whichfork;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) ds.dargs.trans = sc->tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) ds.dargs.op_flags = XFS_DA_OP_OKNOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) ds.state = xfs_da_state_alloc(&ds.dargs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) ds.sc = sc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) ds.private = private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (whichfork == XFS_ATTR_FORK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) ds.dargs.geo = mp->m_attr_geo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) ds.lowest = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) ds.highest = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) ds.dargs.geo = mp->m_dir_geo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) ds.lowest = ds.dargs.geo->leafblk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) ds.highest = ds.dargs.geo->freeblk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) blkno = ds.lowest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) level = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) /* Find the root of the da tree, if present. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) blks = ds.state->path.blk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) error = xchk_da_btree_block(&ds, level, blkno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) goto out_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) * We didn't find a block at ds.lowest, which means that there's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) * no LEAF1/LEAFN tree (at least not where it's supposed to be),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) * so jump out now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (blks[level].bp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) goto out_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) blks[level].index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) while (level >= 0 && level < XFS_DA_NODE_MAXDEPTH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) /* Handle leaf block. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (blks[level].magic != XFS_DA_NODE_MAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) /* End of leaf, pop back towards the root. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (blks[level].index >= ds.maxrecs[level]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (level > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) blks[level - 1].index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) ds.tree_level++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) level--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) /* Dispatch record scrubbing. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) error = scrub_fn(&ds, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (xchk_should_terminate(sc, &error) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) blks[level].index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) /* End of node, pop back towards the root. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (blks[level].index >= ds.maxrecs[level]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (level > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) blks[level - 1].index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) ds.tree_level++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) level--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) /* Hashes in order for scrub? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) key = xchk_da_btree_node_entry(&ds, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) error = xchk_da_btree_hash(&ds, level, &key->hashval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) /* Drill another level deeper. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) blkno = be32_to_cpu(key->before);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) level++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (level >= XFS_DA_NODE_MAXDEPTH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) /* Too deep! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) xchk_da_set_corrupt(&ds, level - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) ds.tree_level--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) error = xchk_da_btree_block(&ds, level, blkno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (blks[level].bp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) blks[level].index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) /* Release all the buffers we're tracking. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) for (level = 0; level < XFS_DA_NODE_MAXDEPTH; level++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if (blks[level].bp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) xfs_trans_brelse(sc->tp, blks[level].bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) blks[level].bp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) out_state:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) xfs_da_state_free(ds.state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) }