1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2021-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_log_format.h" 11 #include "xfs_trans_resv.h" 12 #include "xfs_mount.h" 13 #include "xfs_trans.h" 14 #include "xfs_btree.h" 15 #include "xfs_rmap.h" 16 #include "xfs_refcount.h" 17 #include "xfs_inode.h" 18 #include "xfs_rtbitmap.h" 19 #include "xfs_rtgroup.h" 20 #include "xfs_metafile.h" 21 #include "xfs_rtrefcount_btree.h" 22 #include "xfs_rtalloc.h" 23 #include "xfs_ag.h" 24 #include "scrub/scrub.h" 25 #include "scrub/common.h" 26 #include "scrub/btree.h" 27 #include "scrub/repair.h" 28 #include "scrub/refcount.h" 29 30 /* Set us up with the realtime refcount metadata locked. */ 31 int 32 xchk_setup_rtrefcountbt( 33 struct xfs_scrub *sc) 34 { 35 int error; 36 37 if (xchk_need_intent_drain(sc)) 38 xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN); 39 40 if (xchk_could_repair(sc)) { 41 error = xrep_setup_rtrefcountbt(sc); 42 if (error) 43 return error; 44 } 45 46 error = xchk_rtgroup_init(sc, sc->sm->sm_agno); 47 if (error) 48 return error; 49 50 error = xchk_setup_rt(sc); 51 if (error) 52 return error; 53 54 error = xchk_install_live_inode(sc, rtg_refcount(sc->sr.rtg)); 55 if (error) 56 return error; 57 58 return xchk_rtgroup_lock(sc, XCHK_RTGLOCK_ALL); 59 } 60 61 /* Realtime Reference count btree scrubber. */ 62 63 /* Use the rmap entries covering this extent to verify the refcount. */ 64 STATIC void 65 xchk_rtrefcountbt_xref_rmap( 66 struct xfs_scrub *sc, 67 const struct xfs_refcount_irec *irec) 68 { 69 struct xchk_refcnt_check refchk = { 70 .sc = sc, 71 .bno = irec->rc_startblock, 72 .len = irec->rc_blockcount, 73 .refcount = irec->rc_refcount, 74 .seen = 0, 75 }; 76 struct xfs_rmap_irec low; 77 struct xfs_rmap_irec high; 78 struct xchk_refcnt_frag *frag; 79 struct xchk_refcnt_frag *n; 80 int error; 81 82 if (!sc->sr.rmap_cur || xchk_skip_xref(sc->sm)) 83 return; 84 85 /* Cross-reference with the rmapbt to confirm the refcount. */ 86 memset(&low, 0, sizeof(low)); 87 low.rm_startblock = irec->rc_startblock; 88 memset(&high, 0xFF, sizeof(high)); 89 high.rm_startblock = irec->rc_startblock + irec->rc_blockcount - 1; 90 91 INIT_LIST_HEAD(&refchk.fragments); 92 error = xfs_rmap_query_range(sc->sr.rmap_cur, &low, &high, 93 xchk_refcountbt_rmap_check, &refchk); 94 if (!xchk_should_check_xref(sc, &error, &sc->sr.rmap_cur)) 95 goto out_free; 96 97 xchk_refcountbt_process_rmap_fragments(&refchk); 98 if (irec->rc_refcount != refchk.seen) 99 xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0); 100 101 out_free: 102 list_for_each_entry_safe(frag, n, &refchk.fragments, list) { 103 list_del(&frag->list); 104 kfree(frag); 105 } 106 } 107 108 /* Cross-reference with the other btrees. */ 109 STATIC void 110 xchk_rtrefcountbt_xref( 111 struct xfs_scrub *sc, 112 const struct xfs_refcount_irec *irec) 113 { 114 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 115 return; 116 117 xchk_xref_is_used_rt_space(sc, 118 xfs_rgbno_to_rtb(sc->sr.rtg, irec->rc_startblock), 119 irec->rc_blockcount); 120 xchk_rtrefcountbt_xref_rmap(sc, irec); 121 } 122 123 struct xchk_rtrefcbt_records { 124 /* Previous refcount record. */ 125 struct xfs_refcount_irec prev_rec; 126 127 /* The next rtgroup block where we aren't expecting shared extents. */ 128 xfs_rgblock_t next_unshared_rgbno; 129 130 /* Number of CoW blocks we expect. */ 131 xfs_extlen_t cow_blocks; 132 133 /* Was the last record a shared or CoW staging extent? */ 134 enum xfs_refc_domain prev_domain; 135 }; 136 137 static inline bool 138 xchk_rtrefcount_mergeable( 139 struct xchk_rtrefcbt_records *rrc, 140 const struct xfs_refcount_irec *r2) 141 { 142 const struct xfs_refcount_irec *r1 = &rrc->prev_rec; 143 144 /* Ignore if prev_rec is not yet initialized. */ 145 if (r1->rc_blockcount == 0) 146 return false; 147 148 if (r1->rc_domain != r2->rc_domain) 149 return false; 150 if (r1->rc_startblock + r1->rc_blockcount != r2->rc_startblock) 151 return false; 152 if (r1->rc_refcount != r2->rc_refcount) 153 return false; 154 if ((unsigned long long)r1->rc_blockcount + r2->rc_blockcount > 155 XFS_REFC_LEN_MAX) 156 return false; 157 158 return true; 159 } 160 161 /* Flag failures for records that could be merged. */ 162 STATIC void 163 xchk_rtrefcountbt_check_mergeable( 164 struct xchk_btree *bs, 165 struct xchk_rtrefcbt_records *rrc, 166 const struct xfs_refcount_irec *irec) 167 { 168 if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 169 return; 170 171 if (xchk_rtrefcount_mergeable(rrc, irec)) 172 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 173 174 memcpy(&rrc->prev_rec, irec, sizeof(struct xfs_refcount_irec)); 175 } 176 177 /* 178 * Make sure that a gap in the reference count records does not correspond to 179 * overlapping records (i.e. shared extents) in the reverse mappings. 180 */ 181 static inline void 182 xchk_rtrefcountbt_xref_gaps( 183 struct xfs_scrub *sc, 184 struct xchk_rtrefcbt_records *rrc, 185 xfs_rgblock_t bno) 186 { 187 struct xfs_rmap_irec low; 188 struct xfs_rmap_irec high; 189 xfs_rgblock_t next_bno = NULLRGBLOCK; 190 int error; 191 192 if (bno <= rrc->next_unshared_rgbno || !sc->sr.rmap_cur || 193 xchk_skip_xref(sc->sm)) 194 return; 195 196 memset(&low, 0, sizeof(low)); 197 low.rm_startblock = rrc->next_unshared_rgbno; 198 memset(&high, 0xFF, sizeof(high)); 199 high.rm_startblock = bno - 1; 200 201 error = xfs_rmap_query_range(sc->sr.rmap_cur, &low, &high, 202 xchk_refcountbt_rmap_check_gap, &next_bno); 203 if (error == -ECANCELED) 204 xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0); 205 else 206 xchk_should_check_xref(sc, &error, &sc->sr.rmap_cur); 207 } 208 209 /* Scrub a rtrefcountbt record. */ 210 STATIC int 211 xchk_rtrefcountbt_rec( 212 struct xchk_btree *bs, 213 const union xfs_btree_rec *rec) 214 { 215 struct xfs_mount *mp = bs->cur->bc_mp; 216 struct xchk_rtrefcbt_records *rrc = bs->private; 217 struct xfs_refcount_irec irec; 218 u32 mod; 219 220 xfs_refcount_btrec_to_irec(rec, &irec); 221 if (xfs_rtrefcount_check_irec(to_rtg(bs->cur->bc_group), &irec) != 222 NULL) { 223 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 224 return 0; 225 } 226 227 /* We can only share full rt extents. */ 228 mod = xfs_rgbno_to_rtxoff(mp, irec.rc_startblock); 229 if (mod) 230 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 231 mod = xfs_extlen_to_rtxmod(mp, irec.rc_blockcount); 232 if (mod) 233 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 234 235 if (irec.rc_domain == XFS_REFC_DOMAIN_COW) 236 rrc->cow_blocks += irec.rc_blockcount; 237 238 /* Shared records always come before CoW records. */ 239 if (irec.rc_domain == XFS_REFC_DOMAIN_SHARED && 240 rrc->prev_domain == XFS_REFC_DOMAIN_COW) 241 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 242 rrc->prev_domain = irec.rc_domain; 243 244 xchk_rtrefcountbt_check_mergeable(bs, rrc, &irec); 245 xchk_rtrefcountbt_xref(bs->sc, &irec); 246 247 /* 248 * If this is a record for a shared extent, check that all blocks 249 * between the previous record and this one have at most one reverse 250 * mapping. 251 */ 252 if (irec.rc_domain == XFS_REFC_DOMAIN_SHARED) { 253 xchk_rtrefcountbt_xref_gaps(bs->sc, rrc, irec.rc_startblock); 254 rrc->next_unshared_rgbno = irec.rc_startblock + 255 irec.rc_blockcount; 256 } 257 258 return 0; 259 } 260 261 /* Count the number of blocks used by the rtrefcount btree file in this AG. */ 262 static int 263 xchk_rtrefcount_count_agblocks( 264 struct xfs_scrub *sc, 265 xfs_agnumber_t agno, 266 const struct xfs_owner_info *btree_oinfo, 267 xfs_filblks_t *blocks) 268 { 269 xfs_filblks_t agblocks = 0; 270 int error; 271 272 error = xchk_ag_init_existing(sc, agno); 273 if (error) 274 goto out_free; 275 276 /* 277 * If we don't have an rmap cursor, we can't complete the cross 278 * referencing, so return EFSCORRUPTED to end the loop and trigger the 279 * XFAIL flag. 280 */ 281 if (!sc->sa.rmap_cur) { 282 error = -EFSCORRUPTED; 283 goto out_free; 284 } 285 286 error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur, btree_oinfo, 287 &agblocks); 288 if (error) 289 goto out_free; 290 291 *blocks += agblocks; 292 out_free: 293 xchk_ag_free(sc); 294 return error; 295 } 296 297 /* Make sure we have as many refc blocks as the rmap says. */ 298 STATIC void 299 xchk_rtrefcount_xref_rmap( 300 struct xfs_scrub *sc, 301 const struct xfs_owner_info *btree_oinfo, 302 xfs_extlen_t cow_blocks) 303 { 304 xfs_filblks_t refcbt_blocks = 0; 305 xfs_filblks_t blocks = 1; /* one for the iroot */ 306 xfs_agnumber_t agno; 307 int error = 0; 308 309 if (!xfs_has_rmapbt(sc->mp) || xchk_skip_xref(sc->sm)) 310 return; 311 312 /* Check that we saw as many refcbt blocks as the rmap knows about. */ 313 error = xfs_btree_count_blocks(sc->sr.refc_cur, &refcbt_blocks); 314 if (!xchk_btree_process_error(sc, sc->sr.refc_cur, 0, &error)) 315 return; 316 317 for (agno = 0; agno < sc->mp->m_sb.sb_agcount; agno++) { 318 error = xchk_rtrefcount_count_agblocks(sc, agno, btree_oinfo, 319 &blocks); 320 if (error) 321 break; 322 } 323 if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0, &error)) 324 return; 325 if (blocks != refcbt_blocks) 326 xchk_fblock_xref_set_corrupt(sc, XFS_DATA_FORK, 0); 327 328 if (!sc->sr.rmap_cur || xchk_skip_xref(sc->sm)) 329 return; 330 331 /* Check that we saw as many cow blocks as the rmap knows about. */ 332 error = xchk_count_rmap_ownedby_ag(sc, sc->sr.rmap_cur, 333 &XFS_RMAP_OINFO_COW, &blocks); 334 if (!xchk_should_check_xref(sc, &error, &sc->sr.rmap_cur)) 335 return; 336 if (blocks != cow_blocks) 337 xchk_btree_xref_set_corrupt(sc, sc->sr.rmap_cur, 0); 338 } 339 340 /* Scrub the refcount btree for some rtgroup. */ 341 int 342 xchk_rtrefcountbt( 343 struct xfs_scrub *sc) 344 { 345 struct xfs_owner_info btree_oinfo; 346 struct xchk_rtrefcbt_records rrc = { 347 .cow_blocks = 0, 348 .next_unshared_rgbno = 0, 349 .prev_domain = XFS_REFC_DOMAIN_SHARED, 350 }; 351 int error; 352 353 error = xchk_metadata_inode_forks(sc); 354 if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) 355 return error; 356 357 xfs_rmap_inode_bmbt_owner(&btree_oinfo, rtg_refcount(sc->sr.rtg), 358 XFS_DATA_FORK); 359 error = xchk_btree(sc, sc->sr.refc_cur, xchk_rtrefcountbt_rec, 360 &btree_oinfo, &rrc); 361 if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) 362 return error; 363 364 /* 365 * Check that all blocks between the last refcount > 1 record and the 366 * end of the rtgroup have at most one reverse mapping. 367 */ 368 xchk_rtrefcountbt_xref_gaps(sc, &rrc, 369 xfs_rtx_to_rgbno(sc->sr.rtg, sc->mp->m_sb.sb_rgextents)); 370 xchk_rtrefcount_xref_rmap(sc, &btree_oinfo, rrc.cow_blocks); 371 372 return 0; 373 } 374 375 /* xref check that a cow staging extent is marked in the rtrefcountbt. */ 376 void 377 xchk_xref_is_rt_cow_staging( 378 struct xfs_scrub *sc, 379 xfs_rgblock_t bno, 380 xfs_extlen_t len) 381 { 382 struct xfs_refcount_irec rc; 383 int has_refcount; 384 int error; 385 386 if (!sc->sr.refc_cur || xchk_skip_xref(sc->sm)) 387 return; 388 389 /* Find the CoW staging extent. */ 390 error = xfs_refcount_lookup_le(sc->sr.refc_cur, XFS_REFC_DOMAIN_COW, 391 bno, &has_refcount); 392 if (!xchk_should_check_xref(sc, &error, &sc->sr.refc_cur)) 393 return; 394 if (!has_refcount) { 395 xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0); 396 return; 397 } 398 399 error = xfs_refcount_get_rec(sc->sr.refc_cur, &rc, &has_refcount); 400 if (!xchk_should_check_xref(sc, &error, &sc->sr.refc_cur)) 401 return; 402 if (!has_refcount) { 403 xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0); 404 return; 405 } 406 407 /* CoW lookup returned a shared extent record? */ 408 if (rc.rc_domain != XFS_REFC_DOMAIN_COW) 409 xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0); 410 411 /* Can't start after bno */ 412 if (rc.rc_startblock > bno) 413 xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0); 414 415 /* Must be at least as long as what was passed in */ 416 if (rc.rc_startblock + rc.rc_blockcount < bno + len) 417 xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0); 418 } 419 420 /* 421 * xref check that the extent is not shared. Only file data blocks 422 * can have multiple owners. 423 */ 424 void 425 xchk_xref_is_not_rt_shared( 426 struct xfs_scrub *sc, 427 xfs_rgblock_t bno, 428 xfs_extlen_t len) 429 { 430 enum xbtree_recpacking outcome; 431 int error; 432 433 if (!sc->sr.refc_cur || xchk_skip_xref(sc->sm)) 434 return; 435 436 error = xfs_refcount_has_records(sc->sr.refc_cur, 437 XFS_REFC_DOMAIN_SHARED, bno, len, &outcome); 438 if (!xchk_should_check_xref(sc, &error, &sc->sr.refc_cur)) 439 return; 440 if (outcome != XBTREE_RECPACKING_EMPTY) 441 xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0); 442 } 443 444 /* xref check that the extent is not being used for CoW staging. */ 445 void 446 xchk_xref_is_not_rt_cow_staging( 447 struct xfs_scrub *sc, 448 xfs_rgblock_t bno, 449 xfs_extlen_t len) 450 { 451 enum xbtree_recpacking outcome; 452 int error; 453 454 if (!sc->sr.refc_cur || xchk_skip_xref(sc->sm)) 455 return; 456 457 error = xfs_refcount_has_records(sc->sr.refc_cur, XFS_REFC_DOMAIN_COW, 458 bno, len, &outcome); 459 if (!xchk_should_check_xref(sc, &error, &sc->sr.refc_cur)) 460 return; 461 if (outcome != XBTREE_RECPACKING_EMPTY) 462 xchk_btree_xref_set_corrupt(sc, sc->sr.refc_cur, 0); 463 } 464