^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) #ifndef __XFS_SCRUB_SCRUB_H__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #define __XFS_SCRUB_SCRUB_H__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) struct xfs_scrub;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) /* Type info and names for the scrub types. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) enum xchk_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) ST_NONE = 1, /* disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) ST_PERAG, /* per-AG metadata */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) ST_FS, /* per-FS metadata */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) ST_INODE, /* per-inode metadata */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct xchk_meta_ops {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* Acquire whatever resources are needed for the operation. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) int (*setup)(struct xfs_scrub *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct xfs_inode *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /* Examine metadata for errors. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) int (*scrub)(struct xfs_scrub *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /* Repair or optimize the metadata. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) int (*repair)(struct xfs_scrub *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /* Decide if we even have this piece of metadata. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) bool (*has)(struct xfs_sb *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /* type describing required/allowed inputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) enum xchk_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* Buffer pointers and btree cursors for an entire AG. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct xchk_ag {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) xfs_agnumber_t agno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct xfs_perag *pag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* AG btree roots */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct xfs_buf *agf_bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct xfs_buf *agfl_bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct xfs_buf *agi_bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* AG btrees */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct xfs_btree_cur *bno_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct xfs_btree_cur *cnt_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct xfs_btree_cur *ino_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct xfs_btree_cur *fino_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct xfs_btree_cur *rmap_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct xfs_btree_cur *refc_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct xfs_scrub {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* General scrub state. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct xfs_mount *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct xfs_scrub_metadata *sm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) const struct xchk_meta_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct xfs_trans *tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct xfs_inode *ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) void *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) uint ilock_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* See the XCHK/XREP state flags below. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) unsigned int flags;
^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) * The XFS_SICK_* flags that correspond to the metadata being scrubbed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * or repaired. We will use this mask to update the in-core fs health
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * status with whatever we find.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) unsigned int sick_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* State tracking for single-AG operations. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct xchk_ag sa;
^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) /* XCHK state flags grow up from zero, XREP state flags grown down from 2^31 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define XCHK_TRY_HARDER (1 << 0) /* can't get resources, try again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define XCHK_HAS_QUOTAOFFLOCK (1 << 1) /* we hold the quotaoff lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define XCHK_REAPING_DISABLED (1 << 2) /* background block reaping paused */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define XREP_ALREADY_FIXED (1 << 31) /* checking our repair work */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* Metadata scrubbers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) int xchk_tester(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) int xchk_superblock(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) int xchk_agf(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) int xchk_agfl(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) int xchk_agi(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) int xchk_bnobt(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int xchk_cntbt(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) int xchk_inobt(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int xchk_finobt(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int xchk_rmapbt(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) int xchk_refcountbt(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) int xchk_inode(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int xchk_bmap_data(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) int xchk_bmap_attr(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) int xchk_bmap_cow(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) int xchk_directory(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) int xchk_xattr(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) int xchk_symlink(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) int xchk_parent(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #ifdef CONFIG_XFS_RT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) int xchk_rtbitmap(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) int xchk_rtsummary(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) xchk_rtbitmap(struct xfs_scrub *sc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) xchk_rtsummary(struct xfs_scrub *sc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #ifdef CONFIG_XFS_QUOTA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) int xchk_quota(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) xchk_quota(struct xfs_scrub *sc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) int xchk_fscounters(struct xfs_scrub *sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* cross-referencing helpers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) void xchk_xref_is_used_space(struct xfs_scrub *sc, xfs_agblock_t agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) xfs_extlen_t len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) void xchk_xref_is_not_inode_chunk(struct xfs_scrub *sc, xfs_agblock_t agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) xfs_extlen_t len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) void xchk_xref_is_inode_chunk(struct xfs_scrub *sc, xfs_agblock_t agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) xfs_extlen_t len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) void xchk_xref_is_owned_by(struct xfs_scrub *sc, xfs_agblock_t agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) xfs_extlen_t len, const struct xfs_owner_info *oinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) void xchk_xref_is_not_owned_by(struct xfs_scrub *sc, xfs_agblock_t agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) xfs_extlen_t len, const struct xfs_owner_info *oinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) void xchk_xref_has_no_owner(struct xfs_scrub *sc, xfs_agblock_t agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) xfs_extlen_t len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) void xchk_xref_is_cow_staging(struct xfs_scrub *sc, xfs_agblock_t bno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) xfs_extlen_t len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) void xchk_xref_is_not_shared(struct xfs_scrub *sc, xfs_agblock_t bno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) xfs_extlen_t len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #ifdef CONFIG_XFS_RT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) void xchk_xref_is_used_rt_space(struct xfs_scrub *sc, xfs_rtblock_t rtbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) xfs_extlen_t len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) # define xchk_xref_is_used_rt_space(sc, rtbno, len) do { } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct xchk_fscounters {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) uint64_t icount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) uint64_t ifree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) uint64_t fdblocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) unsigned long long icount_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) unsigned long long icount_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #endif /* __XFS_SCRUB_SCRUB_H__ */