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_platform.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 static inline bool 82 xchk_rtrmapbt_is_shareable( 83 struct xfs_scrub *sc, 84 const struct xfs_rmap_irec *irec) 85 { 86 if (!xfs_has_rtreflink(sc->mp)) 87 return false; 88 if (irec->rm_flags & XFS_RMAP_UNWRITTEN) 89 return false; 90 if (irec->rm_owner == XFS_RMAP_OWN_COW || 91 irec->rm_owner == XFS_RMAP_OWN_FS) 92 return false; 93 return true; 94 } 95 96 /* Flag failures for records that overlap but cannot. */ 97 STATIC void 98 xchk_rtrmapbt_check_overlapping( 99 struct xchk_btree *bs, 100 struct xchk_rtrmap *cr, 101 const struct xfs_rmap_irec *irec) 102 { 103 xfs_rtblock_t pnext, inext; 104 105 if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 106 return; 107 108 /* No previous record? */ 109 if (cr->overlap_rec.rm_blockcount == 0) 110 goto set_prev; 111 112 /* Do overlap_rec and irec overlap? */ 113 pnext = cr->overlap_rec.rm_startblock + cr->overlap_rec.rm_blockcount; 114 if (pnext <= irec->rm_startblock) 115 goto set_prev; 116 117 /* Overlap is only allowed if both records are data fork mappings. */ 118 if (!xchk_rtrmapbt_is_shareable(bs->sc, &cr->overlap_rec) || 119 !xchk_rtrmapbt_is_shareable(bs->sc, irec)) 120 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 121 122 /* Save whichever rmap record extends furthest. */ 123 inext = irec->rm_startblock + irec->rm_blockcount; 124 if (pnext > inext) 125 return; 126 127 set_prev: 128 memcpy(&cr->overlap_rec, irec, sizeof(struct xfs_rmap_irec)); 129 } 130 131 /* Decide if two reverse-mapping records can be merged. */ 132 static inline bool 133 xchk_rtrmap_mergeable( 134 struct xchk_rtrmap *cr, 135 const struct xfs_rmap_irec *r2) 136 { 137 const struct xfs_rmap_irec *r1 = &cr->prev_rec; 138 139 /* Ignore if prev_rec is not yet initialized. */ 140 if (cr->prev_rec.rm_blockcount == 0) 141 return false; 142 143 if (r1->rm_owner != r2->rm_owner) 144 return false; 145 if (r1->rm_startblock + r1->rm_blockcount != r2->rm_startblock) 146 return false; 147 if ((unsigned long long)r1->rm_blockcount + r2->rm_blockcount > 148 XFS_RMAP_LEN_MAX) 149 return false; 150 if (r1->rm_flags != r2->rm_flags) 151 return false; 152 if (r1->rm_owner == XFS_RMAP_OWN_COW || 153 r1->rm_owner == XFS_RMAP_OWN_FS) 154 return true; 155 return r1->rm_offset + r1->rm_blockcount == r2->rm_offset; 156 } 157 158 /* Flag failures for records that could be merged. */ 159 STATIC void 160 xchk_rtrmapbt_check_mergeable( 161 struct xchk_btree *bs, 162 struct xchk_rtrmap *cr, 163 const struct xfs_rmap_irec *irec) 164 { 165 if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 166 return; 167 168 if (xchk_rtrmap_mergeable(cr, irec)) 169 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 170 171 memcpy(&cr->prev_rec, irec, sizeof(struct xfs_rmap_irec)); 172 } 173 174 /* Cross-reference a rmap against the refcount btree. */ 175 STATIC void 176 xchk_rtrmapbt_xref_rtrefc( 177 struct xfs_scrub *sc, 178 struct xfs_rmap_irec *irec) 179 { 180 xfs_rgblock_t fbno; 181 xfs_extlen_t flen; 182 bool is_inode; 183 bool is_bmbt; 184 bool is_attr; 185 bool is_unwritten; 186 int error; 187 188 if (!sc->sr.refc_cur || xchk_skip_xref(sc->sm)) 189 return; 190 191 is_inode = !XFS_RMAP_NON_INODE_OWNER(irec->rm_owner); 192 is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK; 193 is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK; 194 is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN; 195 196 /* If this is shared, must be a data fork extent. */ 197 error = xfs_refcount_find_shared(sc->sr.refc_cur, irec->rm_startblock, 198 irec->rm_blockcount, &fbno, &flen, false); 199 if (!xchk_should_check_xref(sc, &error, &sc->sr.refc_cur)) 200 return; 201 if (flen != 0 && (!is_inode || is_attr || is_bmbt || is_unwritten)) 202 xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0); 203 } 204 205 /* Cross-reference with other metadata. */ 206 STATIC void 207 xchk_rtrmapbt_xref( 208 struct xfs_scrub *sc, 209 struct xfs_rmap_irec *irec) 210 { 211 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 212 return; 213 214 xchk_xref_is_used_rt_space(sc, 215 xfs_rgbno_to_rtb(sc->sr.rtg, irec->rm_startblock), 216 irec->rm_blockcount); 217 if (irec->rm_owner == XFS_RMAP_OWN_COW) 218 xchk_xref_is_rt_cow_staging(sc, irec->rm_startblock, 219 irec->rm_blockcount); 220 else 221 xchk_rtrmapbt_xref_rtrefc(sc, irec); 222 } 223 224 /* Scrub a realtime rmapbt record. */ 225 STATIC int 226 xchk_rtrmapbt_rec( 227 struct xchk_btree *bs, 228 const union xfs_btree_rec *rec) 229 { 230 struct xchk_rtrmap *cr = bs->private; 231 struct xfs_rmap_irec irec; 232 233 if (xfs_rmap_btrec_to_irec(rec, &irec) != NULL || 234 xfs_rtrmap_check_irec(to_rtg(bs->cur->bc_group), &irec) != NULL) { 235 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 236 return 0; 237 } 238 239 if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 240 return 0; 241 242 xchk_rtrmapbt_check_mergeable(bs, cr, &irec); 243 xchk_rtrmapbt_check_overlapping(bs, cr, &irec); 244 xchk_rtrmapbt_xref(bs->sc, &irec); 245 return 0; 246 } 247 248 /* Scrub the realtime rmap btree. */ 249 int 250 xchk_rtrmapbt( 251 struct xfs_scrub *sc) 252 { 253 struct xfs_owner_info oinfo; 254 struct xchk_rtrmap cr = { }; 255 int error; 256 257 error = xchk_metadata_inode_forks(sc); 258 if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) 259 return error; 260 261 xfs_rmap_inode_bmbt_owner(&oinfo, rtg_rmap(sc->sr.rtg), XFS_DATA_FORK); 262 return xchk_btree(sc, sc->sr.rmap_cur, xchk_rtrmapbt_rec, &oinfo, &cr); 263 } 264 265 /* xref check that the extent has no realtime reverse mapping at all */ 266 void 267 xchk_xref_has_no_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_EMPTY) 282 xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0); 283 } 284 285 /* xref check that the extent is completely mapped */ 286 void 287 xchk_xref_has_rt_owner( 288 struct xfs_scrub *sc, 289 xfs_rgblock_t bno, 290 xfs_extlen_t len) 291 { 292 enum xbtree_recpacking outcome; 293 int error; 294 295 if (!sc->sr.rmap_cur || xchk_skip_xref(sc->sm)) 296 return; 297 298 error = xfs_rmap_has_records(sc->sr.rmap_cur, bno, len, &outcome); 299 if (!xchk_should_check_xref(sc, &error, &sc->sr.rmap_cur)) 300 return; 301 if (outcome != XBTREE_RECPACKING_FULL) 302 xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0); 303 } 304 305 /* xref check that the extent is only owned by a given owner */ 306 void 307 xchk_xref_is_only_rt_owned_by( 308 struct xfs_scrub *sc, 309 xfs_agblock_t bno, 310 xfs_extlen_t len, 311 const struct xfs_owner_info *oinfo) 312 { 313 struct xfs_rmap_matches res; 314 int error; 315 316 if (!sc->sr.rmap_cur || xchk_skip_xref(sc->sm)) 317 return; 318 319 error = xfs_rmap_count_owners(sc->sr.rmap_cur, bno, len, oinfo, &res); 320 if (!xchk_should_check_xref(sc, &error, &sc->sr.rmap_cur)) 321 return; 322 if (res.matches != 1) 323 xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0); 324 if (res.bad_non_owner_matches) 325 xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0); 326 if (res.non_owner_matches) 327 xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0); 328 } 329