rmap.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2017-2023 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_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_ag.h"
  18. #include "xfs_bit.h"
  19. #include "xfs_alloc.h"
  20. #include "xfs_alloc_btree.h"
  21. #include "xfs_ialloc_btree.h"
  22. #include "xfs_refcount_btree.h"
  23. #include "scrub/scrub.h"
  24. #include "scrub/common.h"
  25. #include "scrub/btree.h"
  26. #include "scrub/bitmap.h"
  27. #include "scrub/agb_bitmap.h"
  28. #include "scrub/repair.h"
  29. /*
  30. * Set us up to scrub reverse mapping btrees.
  31. */
  32. int
  33. xchk_setup_ag_rmapbt(
  34. struct xfs_scrub *sc)
  35. {
  36. if (xchk_need_intent_drain(sc))
  37. xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
  38. if (xchk_could_repair(sc)) {
  39. int error;
  40. error = xrep_setup_ag_rmapbt(sc);
  41. if (error)
  42. return error;
  43. }
  44. return xchk_setup_ag_btree(sc, false);
  45. }
  46. /* Reverse-mapping scrubber. */
  47. struct xchk_rmap {
  48. /*
  49. * The furthest-reaching of the rmapbt records that we've already
  50. * processed. This enables us to detect overlapping records for space
  51. * allocations that cannot be shared.
  52. */
  53. struct xfs_rmap_irec overlap_rec;
  54. /*
  55. * The previous rmapbt record, so that we can check for two records
  56. * that could be one.
  57. */
  58. struct xfs_rmap_irec prev_rec;
  59. /* Bitmaps containing all blocks for each type of AG metadata. */
  60. struct xagb_bitmap fs_owned;
  61. struct xagb_bitmap log_owned;
  62. struct xagb_bitmap ag_owned;
  63. struct xagb_bitmap inobt_owned;
  64. struct xagb_bitmap refcbt_owned;
  65. /* Did we complete the AG space metadata bitmaps? */
  66. bool bitmaps_complete;
  67. };
  68. /* Cross-reference a rmap against the refcount btree. */
  69. STATIC void
  70. xchk_rmapbt_xref_refc(
  71. struct xfs_scrub *sc,
  72. struct xfs_rmap_irec *irec)
  73. {
  74. xfs_agblock_t fbno;
  75. xfs_extlen_t flen;
  76. bool non_inode;
  77. bool is_bmbt;
  78. bool is_attr;
  79. bool is_unwritten;
  80. int error;
  81. if (!sc->sa.refc_cur || xchk_skip_xref(sc->sm))
  82. return;
  83. non_inode = XFS_RMAP_NON_INODE_OWNER(irec->rm_owner);
  84. is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK;
  85. is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK;
  86. is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN;
  87. /* If this is shared, must be a data fork extent. */
  88. error = xfs_refcount_find_shared(sc->sa.refc_cur, irec->rm_startblock,
  89. irec->rm_blockcount, &fbno, &flen, false);
  90. if (!xchk_should_check_xref(sc, &error, &sc->sa.refc_cur))
  91. return;
  92. if (flen != 0 && (non_inode || is_attr || is_bmbt || is_unwritten))
  93. xchk_btree_xref_set_corrupt(sc, sc->sa.refc_cur, 0);
  94. }
  95. /* Cross-reference with the other btrees. */
  96. STATIC void
  97. xchk_rmapbt_xref(
  98. struct xfs_scrub *sc,
  99. struct xfs_rmap_irec *irec)
  100. {
  101. xfs_agblock_t agbno = irec->rm_startblock;
  102. xfs_extlen_t len = irec->rm_blockcount;
  103. if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
  104. return;
  105. xchk_xref_is_used_space(sc, agbno, len);
  106. if (irec->rm_owner == XFS_RMAP_OWN_INODES)
  107. xchk_xref_is_inode_chunk(sc, agbno, len);
  108. else
  109. xchk_xref_is_not_inode_chunk(sc, agbno, len);
  110. if (irec->rm_owner == XFS_RMAP_OWN_COW)
  111. xchk_xref_is_cow_staging(sc, irec->rm_startblock,
  112. irec->rm_blockcount);
  113. else
  114. xchk_rmapbt_xref_refc(sc, irec);
  115. }
  116. /*
  117. * Check for bogus UNWRITTEN flags in the rmapbt node block keys.
  118. *
  119. * In reverse mapping records, the file mapping extent state
  120. * (XFS_RMAP_OFF_UNWRITTEN) is a record attribute, not a key field. It is not
  121. * involved in lookups in any way. In older kernels, the functions that
  122. * convert rmapbt records to keys forgot to filter out the extent state bit,
  123. * even though the key comparison functions have filtered the flag correctly.
  124. * If we spot an rmap key with the unwritten bit set in rm_offset, we should
  125. * mark the btree as needing optimization to rebuild the btree without those
  126. * flags.
  127. */
  128. STATIC void
  129. xchk_rmapbt_check_unwritten_in_keyflags(
  130. struct xchk_btree *bs)
  131. {
  132. struct xfs_scrub *sc = bs->sc;
  133. struct xfs_btree_cur *cur = bs->cur;
  134. struct xfs_btree_block *keyblock;
  135. union xfs_btree_key *lkey, *hkey;
  136. __be64 badflag = cpu_to_be64(XFS_RMAP_OFF_UNWRITTEN);
  137. unsigned int level;
  138. if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_PREEN)
  139. return;
  140. for (level = 1; level < cur->bc_nlevels; level++) {
  141. struct xfs_buf *bp;
  142. unsigned int ptr;
  143. /* Only check the first time we've seen this node block. */
  144. if (cur->bc_levels[level].ptr > 1)
  145. continue;
  146. keyblock = xfs_btree_get_block(cur, level, &bp);
  147. for (ptr = 1; ptr <= be16_to_cpu(keyblock->bb_numrecs); ptr++) {
  148. lkey = xfs_btree_key_addr(cur, ptr, keyblock);
  149. if (lkey->rmap.rm_offset & badflag) {
  150. xchk_btree_set_preen(sc, cur, level);
  151. break;
  152. }
  153. hkey = xfs_btree_high_key_addr(cur, ptr, keyblock);
  154. if (hkey->rmap.rm_offset & badflag) {
  155. xchk_btree_set_preen(sc, cur, level);
  156. break;
  157. }
  158. }
  159. }
  160. }
  161. static inline bool
  162. xchk_rmapbt_is_shareable(
  163. struct xfs_scrub *sc,
  164. const struct xfs_rmap_irec *irec)
  165. {
  166. if (!xfs_has_reflink(sc->mp))
  167. return false;
  168. if (XFS_RMAP_NON_INODE_OWNER(irec->rm_owner))
  169. return false;
  170. if (irec->rm_flags & (XFS_RMAP_BMBT_BLOCK | XFS_RMAP_ATTR_FORK |
  171. XFS_RMAP_UNWRITTEN))
  172. return false;
  173. return true;
  174. }
  175. /* Flag failures for records that overlap but cannot. */
  176. STATIC void
  177. xchk_rmapbt_check_overlapping(
  178. struct xchk_btree *bs,
  179. struct xchk_rmap *cr,
  180. const struct xfs_rmap_irec *irec)
  181. {
  182. xfs_agblock_t pnext, inext;
  183. if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
  184. return;
  185. /* No previous record? */
  186. if (cr->overlap_rec.rm_blockcount == 0)
  187. goto set_prev;
  188. /* Do overlap_rec and irec overlap? */
  189. pnext = cr->overlap_rec.rm_startblock + cr->overlap_rec.rm_blockcount;
  190. if (pnext <= irec->rm_startblock)
  191. goto set_prev;
  192. /* Overlap is only allowed if both records are data fork mappings. */
  193. if (!xchk_rmapbt_is_shareable(bs->sc, &cr->overlap_rec) ||
  194. !xchk_rmapbt_is_shareable(bs->sc, irec))
  195. xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
  196. /* Save whichever rmap record extends furthest. */
  197. inext = irec->rm_startblock + irec->rm_blockcount;
  198. if (pnext > inext)
  199. return;
  200. set_prev:
  201. memcpy(&cr->overlap_rec, irec, sizeof(struct xfs_rmap_irec));
  202. }
  203. /* Decide if two reverse-mapping records can be merged. */
  204. static inline bool
  205. xchk_rmap_mergeable(
  206. struct xchk_rmap *cr,
  207. const struct xfs_rmap_irec *r2)
  208. {
  209. const struct xfs_rmap_irec *r1 = &cr->prev_rec;
  210. /* Ignore if prev_rec is not yet initialized. */
  211. if (cr->prev_rec.rm_blockcount == 0)
  212. return false;
  213. if (r1->rm_owner != r2->rm_owner)
  214. return false;
  215. if (r1->rm_startblock + r1->rm_blockcount != r2->rm_startblock)
  216. return false;
  217. if ((unsigned long long)r1->rm_blockcount + r2->rm_blockcount >
  218. XFS_RMAP_LEN_MAX)
  219. return false;
  220. if (XFS_RMAP_NON_INODE_OWNER(r2->rm_owner))
  221. return true;
  222. /* must be an inode owner below here */
  223. if (r1->rm_flags != r2->rm_flags)
  224. return false;
  225. if (r1->rm_flags & XFS_RMAP_BMBT_BLOCK)
  226. return true;
  227. return r1->rm_offset + r1->rm_blockcount == r2->rm_offset;
  228. }
  229. /* Flag failures for records that could be merged. */
  230. STATIC void
  231. xchk_rmapbt_check_mergeable(
  232. struct xchk_btree *bs,
  233. struct xchk_rmap *cr,
  234. const struct xfs_rmap_irec *irec)
  235. {
  236. if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
  237. return;
  238. if (xchk_rmap_mergeable(cr, irec))
  239. xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
  240. memcpy(&cr->prev_rec, irec, sizeof(struct xfs_rmap_irec));
  241. }
  242. /* Compare an rmap for AG metadata against the metadata walk. */
  243. STATIC int
  244. xchk_rmapbt_mark_bitmap(
  245. struct xchk_btree *bs,
  246. struct xchk_rmap *cr,
  247. const struct xfs_rmap_irec *irec)
  248. {
  249. struct xfs_scrub *sc = bs->sc;
  250. struct xagb_bitmap *bmp = NULL;
  251. xfs_extlen_t fsbcount = irec->rm_blockcount;
  252. /*
  253. * Skip corrupt records. It is essential that we detect records in the
  254. * btree that cannot overlap but do, flag those as CORRUPT, and skip
  255. * the bitmap comparison to avoid generating false XCORRUPT reports.
  256. */
  257. if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
  258. return 0;
  259. /*
  260. * If the AG metadata walk didn't complete, there's no point in
  261. * comparing against partial results.
  262. */
  263. if (!cr->bitmaps_complete)
  264. return 0;
  265. switch (irec->rm_owner) {
  266. case XFS_RMAP_OWN_FS:
  267. bmp = &cr->fs_owned;
  268. break;
  269. case XFS_RMAP_OWN_LOG:
  270. bmp = &cr->log_owned;
  271. break;
  272. case XFS_RMAP_OWN_AG:
  273. bmp = &cr->ag_owned;
  274. break;
  275. case XFS_RMAP_OWN_INOBT:
  276. bmp = &cr->inobt_owned;
  277. break;
  278. case XFS_RMAP_OWN_REFC:
  279. bmp = &cr->refcbt_owned;
  280. break;
  281. }
  282. if (!bmp)
  283. return 0;
  284. if (xagb_bitmap_test(bmp, irec->rm_startblock, &fsbcount)) {
  285. /*
  286. * The start of this reverse mapping corresponds to a set
  287. * region in the bitmap. If the mapping covers more area than
  288. * the set region, then it covers space that wasn't found by
  289. * the AG metadata walk.
  290. */
  291. if (fsbcount < irec->rm_blockcount)
  292. xchk_btree_xref_set_corrupt(bs->sc,
  293. bs->sc->sa.rmap_cur, 0);
  294. } else {
  295. /*
  296. * The start of this reverse mapping does not correspond to a
  297. * completely set region in the bitmap. The region wasn't
  298. * fully set by walking the AG metadata, so this is a
  299. * cross-referencing corruption.
  300. */
  301. xchk_btree_xref_set_corrupt(bs->sc, bs->sc->sa.rmap_cur, 0);
  302. }
  303. /* Unset the region so that we can detect missing rmap records. */
  304. return xagb_bitmap_clear(bmp, irec->rm_startblock, irec->rm_blockcount);
  305. }
  306. /* Scrub an rmapbt record. */
  307. STATIC int
  308. xchk_rmapbt_rec(
  309. struct xchk_btree *bs,
  310. const union xfs_btree_rec *rec)
  311. {
  312. struct xchk_rmap *cr = bs->private;
  313. struct xfs_rmap_irec irec;
  314. if (xfs_rmap_btrec_to_irec(rec, &irec) != NULL ||
  315. xfs_rmap_check_irec(bs->cur->bc_ag.pag, &irec) != NULL) {
  316. xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
  317. return 0;
  318. }
  319. xchk_rmapbt_check_unwritten_in_keyflags(bs);
  320. xchk_rmapbt_check_mergeable(bs, cr, &irec);
  321. xchk_rmapbt_check_overlapping(bs, cr, &irec);
  322. xchk_rmapbt_xref(bs->sc, &irec);
  323. return xchk_rmapbt_mark_bitmap(bs, cr, &irec);
  324. }
  325. /* Add an AGFL block to the rmap list. */
  326. STATIC int
  327. xchk_rmapbt_walk_agfl(
  328. struct xfs_mount *mp,
  329. xfs_agblock_t agbno,
  330. void *priv)
  331. {
  332. struct xagb_bitmap *bitmap = priv;
  333. return xagb_bitmap_set(bitmap, agbno, 1);
  334. }
  335. /*
  336. * Set up bitmaps mapping all the AG metadata to compare with the rmapbt
  337. * records.
  338. *
  339. * Grab our own btree cursors here if the scrub setup function didn't give us a
  340. * btree cursor due to reports of poor health. We need to find out if the
  341. * rmapbt disagrees with primary metadata btrees to tag the rmapbt as being
  342. * XCORRUPT.
  343. */
  344. STATIC int
  345. xchk_rmapbt_walk_ag_metadata(
  346. struct xfs_scrub *sc,
  347. struct xchk_rmap *cr)
  348. {
  349. struct xfs_mount *mp = sc->mp;
  350. struct xfs_buf *agfl_bp;
  351. struct xfs_agf *agf = sc->sa.agf_bp->b_addr;
  352. struct xfs_btree_cur *cur;
  353. int error;
  354. /* OWN_FS: AG headers */
  355. error = xagb_bitmap_set(&cr->fs_owned, XFS_SB_BLOCK(mp),
  356. XFS_AGFL_BLOCK(mp) - XFS_SB_BLOCK(mp) + 1);
  357. if (error)
  358. goto out;
  359. /* OWN_LOG: Internal log */
  360. if (xfs_ag_contains_log(mp, sc->sa.pag->pag_agno)) {
  361. error = xagb_bitmap_set(&cr->log_owned,
  362. XFS_FSB_TO_AGBNO(mp, mp->m_sb.sb_logstart),
  363. mp->m_sb.sb_logblocks);
  364. if (error)
  365. goto out;
  366. }
  367. /* OWN_AG: bnobt, cntbt, rmapbt, and AGFL */
  368. cur = sc->sa.bno_cur;
  369. if (!cur)
  370. cur = xfs_bnobt_init_cursor(sc->mp, sc->tp, sc->sa.agf_bp,
  371. sc->sa.pag);
  372. error = xagb_bitmap_set_btblocks(&cr->ag_owned, cur);
  373. if (cur != sc->sa.bno_cur)
  374. xfs_btree_del_cursor(cur, error);
  375. if (error)
  376. goto out;
  377. cur = sc->sa.cnt_cur;
  378. if (!cur)
  379. cur = xfs_cntbt_init_cursor(sc->mp, sc->tp, sc->sa.agf_bp,
  380. sc->sa.pag);
  381. error = xagb_bitmap_set_btblocks(&cr->ag_owned, cur);
  382. if (cur != sc->sa.cnt_cur)
  383. xfs_btree_del_cursor(cur, error);
  384. if (error)
  385. goto out;
  386. error = xagb_bitmap_set_btblocks(&cr->ag_owned, sc->sa.rmap_cur);
  387. if (error)
  388. goto out;
  389. error = xfs_alloc_read_agfl(sc->sa.pag, sc->tp, &agfl_bp);
  390. if (error)
  391. goto out;
  392. error = xfs_agfl_walk(sc->mp, agf, agfl_bp, xchk_rmapbt_walk_agfl,
  393. &cr->ag_owned);
  394. xfs_trans_brelse(sc->tp, agfl_bp);
  395. if (error)
  396. goto out;
  397. /* OWN_INOBT: inobt, finobt */
  398. cur = sc->sa.ino_cur;
  399. if (!cur)
  400. cur = xfs_inobt_init_cursor(sc->sa.pag, sc->tp, sc->sa.agi_bp);
  401. error = xagb_bitmap_set_btblocks(&cr->inobt_owned, cur);
  402. if (cur != sc->sa.ino_cur)
  403. xfs_btree_del_cursor(cur, error);
  404. if (error)
  405. goto out;
  406. if (xfs_has_finobt(sc->mp)) {
  407. cur = sc->sa.fino_cur;
  408. if (!cur)
  409. cur = xfs_finobt_init_cursor(sc->sa.pag, sc->tp,
  410. sc->sa.agi_bp);
  411. error = xagb_bitmap_set_btblocks(&cr->inobt_owned, cur);
  412. if (cur != sc->sa.fino_cur)
  413. xfs_btree_del_cursor(cur, error);
  414. if (error)
  415. goto out;
  416. }
  417. /* OWN_REFC: refcountbt */
  418. if (xfs_has_reflink(sc->mp)) {
  419. cur = sc->sa.refc_cur;
  420. if (!cur)
  421. cur = xfs_refcountbt_init_cursor(sc->mp, sc->tp,
  422. sc->sa.agf_bp, sc->sa.pag);
  423. error = xagb_bitmap_set_btblocks(&cr->refcbt_owned, cur);
  424. if (cur != sc->sa.refc_cur)
  425. xfs_btree_del_cursor(cur, error);
  426. if (error)
  427. goto out;
  428. }
  429. out:
  430. /*
  431. * If there's an error, set XFAIL and disable the bitmap
  432. * cross-referencing checks, but proceed with the scrub anyway.
  433. */
  434. if (error)
  435. xchk_btree_xref_process_error(sc, sc->sa.rmap_cur,
  436. sc->sa.rmap_cur->bc_nlevels - 1, &error);
  437. else
  438. cr->bitmaps_complete = true;
  439. return 0;
  440. }
  441. /*
  442. * Check for set regions in the bitmaps; if there are any, the rmap records do
  443. * not describe all the AG metadata.
  444. */
  445. STATIC void
  446. xchk_rmapbt_check_bitmaps(
  447. struct xfs_scrub *sc,
  448. struct xchk_rmap *cr)
  449. {
  450. struct xfs_btree_cur *cur = sc->sa.rmap_cur;
  451. unsigned int level;
  452. if (sc->sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT |
  453. XFS_SCRUB_OFLAG_XFAIL))
  454. return;
  455. if (!cur)
  456. return;
  457. level = cur->bc_nlevels - 1;
  458. /*
  459. * Any bitmap with bits still set indicates that the reverse mapping
  460. * doesn't cover the entire primary structure.
  461. */
  462. if (xagb_bitmap_hweight(&cr->fs_owned) != 0)
  463. xchk_btree_xref_set_corrupt(sc, cur, level);
  464. if (xagb_bitmap_hweight(&cr->log_owned) != 0)
  465. xchk_btree_xref_set_corrupt(sc, cur, level);
  466. if (xagb_bitmap_hweight(&cr->ag_owned) != 0)
  467. xchk_btree_xref_set_corrupt(sc, cur, level);
  468. if (xagb_bitmap_hweight(&cr->inobt_owned) != 0)
  469. xchk_btree_xref_set_corrupt(sc, cur, level);
  470. if (xagb_bitmap_hweight(&cr->refcbt_owned) != 0)
  471. xchk_btree_xref_set_corrupt(sc, cur, level);
  472. }
  473. /* Scrub the rmap btree for some AG. */
  474. int
  475. xchk_rmapbt(
  476. struct xfs_scrub *sc)
  477. {
  478. struct xchk_rmap *cr;
  479. int error;
  480. cr = kzalloc(sizeof(struct xchk_rmap), XCHK_GFP_FLAGS);
  481. if (!cr)
  482. return -ENOMEM;
  483. xagb_bitmap_init(&cr->fs_owned);
  484. xagb_bitmap_init(&cr->log_owned);
  485. xagb_bitmap_init(&cr->ag_owned);
  486. xagb_bitmap_init(&cr->inobt_owned);
  487. xagb_bitmap_init(&cr->refcbt_owned);
  488. error = xchk_rmapbt_walk_ag_metadata(sc, cr);
  489. if (error)
  490. goto out;
  491. error = xchk_btree(sc, sc->sa.rmap_cur, xchk_rmapbt_rec,
  492. &XFS_RMAP_OINFO_AG, cr);
  493. if (error)
  494. goto out;
  495. xchk_rmapbt_check_bitmaps(sc, cr);
  496. out:
  497. xagb_bitmap_destroy(&cr->refcbt_owned);
  498. xagb_bitmap_destroy(&cr->inobt_owned);
  499. xagb_bitmap_destroy(&cr->ag_owned);
  500. xagb_bitmap_destroy(&cr->log_owned);
  501. xagb_bitmap_destroy(&cr->fs_owned);
  502. kfree(cr);
  503. return error;
  504. }
  505. /* xref check that the extent is owned only by a given owner */
  506. void
  507. xchk_xref_is_only_owned_by(
  508. struct xfs_scrub *sc,
  509. xfs_agblock_t bno,
  510. xfs_extlen_t len,
  511. const struct xfs_owner_info *oinfo)
  512. {
  513. struct xfs_rmap_matches res;
  514. int error;
  515. if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
  516. return;
  517. error = xfs_rmap_count_owners(sc->sa.rmap_cur, bno, len, oinfo, &res);
  518. if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
  519. return;
  520. if (res.matches != 1)
  521. xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
  522. if (res.bad_non_owner_matches)
  523. xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
  524. if (res.non_owner_matches)
  525. xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
  526. }
  527. /* xref check that the extent is not owned by a given owner */
  528. void
  529. xchk_xref_is_not_owned_by(
  530. struct xfs_scrub *sc,
  531. xfs_agblock_t bno,
  532. xfs_extlen_t len,
  533. const struct xfs_owner_info *oinfo)
  534. {
  535. struct xfs_rmap_matches res;
  536. int error;
  537. if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
  538. return;
  539. error = xfs_rmap_count_owners(sc->sa.rmap_cur, bno, len, oinfo, &res);
  540. if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
  541. return;
  542. if (res.matches != 0)
  543. xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
  544. if (res.bad_non_owner_matches)
  545. xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
  546. }
  547. /* xref check that the extent has no reverse mapping at all */
  548. void
  549. xchk_xref_has_no_owner(
  550. struct xfs_scrub *sc,
  551. xfs_agblock_t bno,
  552. xfs_extlen_t len)
  553. {
  554. enum xbtree_recpacking outcome;
  555. int error;
  556. if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
  557. return;
  558. error = xfs_rmap_has_records(sc->sa.rmap_cur, bno, len, &outcome);
  559. if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
  560. return;
  561. if (outcome != XBTREE_RECPACKING_EMPTY)
  562. xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
  563. }