1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2018-2024 Oracle. All Rights Reserved. 4 * Author: Darrick J. Wong <djwong@kernel.org> 5 */ 6 #include "xfs.h" 7 #include "xfs_fs.h" 8 #include "xfs_shared.h" 9 #include "xfs_format.h" 10 #include "xfs_trans_resv.h" 11 #include "xfs_mount.h" 12 #include "xfs_defer.h" 13 #include "xfs_btree.h" 14 #include "xfs_bit.h" 15 #include "xfs_log_format.h" 16 #include "xfs_trans.h" 17 #include "xfs_sb.h" 18 #include "xfs_rmap.h" 19 #include "xfs_rmap_btree.h" 20 #include "xfs_rtrmap_btree.h" 21 #include "xfs_inode.h" 22 #include "xfs_rtalloc.h" 23 #include "xfs_rtgroup.h" 24 #include "xfs_metafile.h" 25 #include "scrub/xfs_scrub.h" 26 #include "scrub/scrub.h" 27 #include "scrub/common.h" 28 #include "scrub/btree.h" 29 #include "scrub/trace.h" 30 31 /* Set us up with the realtime metadata locked. */ 32 int 33 xchk_setup_rtrmapbt( 34 struct xfs_scrub *sc) 35 { 36 int error; 37 38 if (xchk_need_intent_drain(sc)) 39 xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN); 40 41 error = xchk_rtgroup_init(sc, sc->sm->sm_agno, &sc->sr); 42 if (error) 43 return error; 44 45 error = xchk_setup_rt(sc); 46 if (error) 47 return error; 48 49 error = xchk_install_live_inode(sc, rtg_rmap(sc->sr.rtg)); 50 if (error) 51 return error; 52 53 return xchk_rtgroup_lock(sc, &sc->sr, XCHK_RTGLOCK_ALL); 54 } 55 56 /* Realtime reverse mapping. */ 57 58 struct xchk_rtrmap { 59 /* 60 * The furthest-reaching of the rmapbt records that we've already 61 * processed. This enables us to detect overlapping records for space 62 * allocations that cannot be shared. 63 */ 64 struct xfs_rmap_irec overlap_rec; 65 66 /* 67 * The previous rmapbt record, so that we can check for two records 68 * that could be one. 69 */ 70 struct xfs_rmap_irec prev_rec; 71 }; 72 73 /* Flag failures for records that overlap but cannot. */ 74 STATIC void 75 xchk_rtrmapbt_check_overlapping( 76 struct xchk_btree *bs, 77 struct xchk_rtrmap *cr, 78 const struct xfs_rmap_irec *irec) 79 { 80 xfs_rtblock_t pnext, inext; 81 82 if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 83 return; 84 85 /* No previous record? */ 86 if (cr->overlap_rec.rm_blockcount == 0) 87 goto set_prev; 88 89 /* Do overlap_rec and irec overlap? */ 90 pnext = cr->overlap_rec.rm_startblock + cr->overlap_rec.rm_blockcount; 91 if (pnext <= irec->rm_startblock) 92 goto set_prev; 93 94 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 95 96 /* Save whichever rmap record extends furthest. */ 97 inext = irec->rm_startblock + irec->rm_blockcount; 98 if (pnext > inext) 99 return; 100 101 set_prev: 102 memcpy(&cr->overlap_rec, irec, sizeof(struct xfs_rmap_irec)); 103 } 104 105 /* Decide if two reverse-mapping records can be merged. */ 106 static inline bool 107 xchk_rtrmap_mergeable( 108 struct xchk_rtrmap *cr, 109 const struct xfs_rmap_irec *r2) 110 { 111 const struct xfs_rmap_irec *r1 = &cr->prev_rec; 112 113 /* Ignore if prev_rec is not yet initialized. */ 114 if (cr->prev_rec.rm_blockcount == 0) 115 return false; 116 117 if (r1->rm_owner != r2->rm_owner) 118 return false; 119 if (r1->rm_startblock + r1->rm_blockcount != r2->rm_startblock) 120 return false; 121 if ((unsigned long long)r1->rm_blockcount + r2->rm_blockcount > 122 XFS_RMAP_LEN_MAX) 123 return false; 124 if (r1->rm_flags != r2->rm_flags) 125 return false; 126 return r1->rm_offset + r1->rm_blockcount == r2->rm_offset; 127 } 128 129 /* Flag failures for records that could be merged. */ 130 STATIC void 131 xchk_rtrmapbt_check_mergeable( 132 struct xchk_btree *bs, 133 struct xchk_rtrmap *cr, 134 const struct xfs_rmap_irec *irec) 135 { 136 if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 137 return; 138 139 if (xchk_rtrmap_mergeable(cr, irec)) 140 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 141 142 memcpy(&cr->prev_rec, irec, sizeof(struct xfs_rmap_irec)); 143 } 144 145 /* Cross-reference with other metadata. */ 146 STATIC void 147 xchk_rtrmapbt_xref( 148 struct xfs_scrub *sc, 149 struct xfs_rmap_irec *irec) 150 { 151 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 152 return; 153 154 xchk_xref_is_used_rt_space(sc, 155 xfs_rgbno_to_rtb(sc->sr.rtg, irec->rm_startblock), 156 irec->rm_blockcount); 157 } 158 159 /* Scrub a realtime rmapbt record. */ 160 STATIC int 161 xchk_rtrmapbt_rec( 162 struct xchk_btree *bs, 163 const union xfs_btree_rec *rec) 164 { 165 struct xchk_rtrmap *cr = bs->private; 166 struct xfs_rmap_irec irec; 167 168 if (xfs_rmap_btrec_to_irec(rec, &irec) != NULL || 169 xfs_rtrmap_check_irec(to_rtg(bs->cur->bc_group), &irec) != NULL) { 170 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 171 return 0; 172 } 173 174 if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 175 return 0; 176 177 xchk_rtrmapbt_check_mergeable(bs, cr, &irec); 178 xchk_rtrmapbt_check_overlapping(bs, cr, &irec); 179 xchk_rtrmapbt_xref(bs->sc, &irec); 180 return 0; 181 } 182 183 /* Scrub the realtime rmap btree. */ 184 int 185 xchk_rtrmapbt( 186 struct xfs_scrub *sc) 187 { 188 struct xfs_inode *ip = rtg_rmap(sc->sr.rtg); 189 struct xfs_owner_info oinfo; 190 struct xchk_rtrmap cr = { }; 191 int error; 192 193 error = xchk_metadata_inode_forks(sc); 194 if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) 195 return error; 196 197 xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, XFS_DATA_FORK); 198 return xchk_btree(sc, sc->sr.rmap_cur, xchk_rtrmapbt_rec, &oinfo, &cr); 199 } 200 201 /* xref check that the extent has no realtime reverse mapping at all */ 202 void 203 xchk_xref_has_no_rt_owner( 204 struct xfs_scrub *sc, 205 xfs_rgblock_t bno, 206 xfs_extlen_t len) 207 { 208 enum xbtree_recpacking outcome; 209 int error; 210 211 if (!sc->sr.rmap_cur || xchk_skip_xref(sc->sm)) 212 return; 213 214 error = xfs_rmap_has_records(sc->sr.rmap_cur, bno, len, &outcome); 215 if (!xchk_should_check_xref(sc, &error, &sc->sr.rmap_cur)) 216 return; 217 if (outcome != XBTREE_RECPACKING_EMPTY) 218 xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0); 219 } 220 221 /* xref check that the extent is completely mapped */ 222 void 223 xchk_xref_has_rt_owner( 224 struct xfs_scrub *sc, 225 xfs_rgblock_t bno, 226 xfs_extlen_t len) 227 { 228 enum xbtree_recpacking outcome; 229 int error; 230 231 if (!sc->sr.rmap_cur || xchk_skip_xref(sc->sm)) 232 return; 233 234 error = xfs_rmap_has_records(sc->sr.rmap_cur, bno, len, &outcome); 235 if (!xchk_should_check_xref(sc, &error, &sc->sr.rmap_cur)) 236 return; 237 if (outcome != XBTREE_RECPACKING_FULL) 238 xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0); 239 } 240 241 /* xref check that the extent is only owned by a given owner */ 242 void 243 xchk_xref_is_only_rt_owned_by( 244 struct xfs_scrub *sc, 245 xfs_agblock_t bno, 246 xfs_extlen_t len, 247 const struct xfs_owner_info *oinfo) 248 { 249 struct xfs_rmap_matches res; 250 int error; 251 252 if (!sc->sr.rmap_cur || xchk_skip_xref(sc->sm)) 253 return; 254 255 error = xfs_rmap_count_owners(sc->sr.rmap_cur, bno, len, oinfo, &res); 256 if (!xchk_should_check_xref(sc, &error, &sc->sr.rmap_cur)) 257 return; 258 if (res.matches != 1) 259 xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0); 260 if (res.bad_non_owner_matches) 261 xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0); 262 if (res.non_owner_matches) 263 xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0); 264 } 265