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