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