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