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 309386 : xchk_setup_ag_rmapbt(
34 : struct xfs_scrub *sc)
35 : {
36 309386 : if (xchk_need_intent_drain(sc))
37 3194 : xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
38 :
39 618772 : if (xchk_could_repair(sc)) {
40 32679 : int error;
41 :
42 32679 : error = xrep_setup_ag_rmapbt(sc);
43 32792 : if (error)
44 : return error;
45 : }
46 :
47 309499 : 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 968520766 : xchk_rmapbt_xref_refc(
80 : struct xfs_scrub *sc,
81 : struct xfs_rmap_irec *irec)
82 : {
83 968520766 : xfs_agblock_t fbno;
84 968520766 : xfs_extlen_t flen;
85 968520766 : bool non_inode;
86 968520766 : bool is_bmbt;
87 968520766 : bool is_attr;
88 968520766 : bool is_unwritten;
89 968520766 : int error;
90 :
91 968520766 : if (!sc->sa.refc_cur || xchk_skip_xref(sc->sm))
92 42046 : return;
93 :
94 968478720 : non_inode = XFS_RMAP_NON_INODE_OWNER(irec->rm_owner);
95 968478720 : is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK;
96 968478720 : is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK;
97 968478720 : is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN;
98 :
99 : /* If this is shared, must be a data fork extent. */
100 968478720 : error = xfs_refcount_find_shared(sc->sa.refc_cur, irec->rm_startblock,
101 : irec->rm_blockcount, &fbno, &flen, false);
102 967670982 : if (!xchk_should_check_xref(sc, &error, &sc->sa.refc_cur))
103 : return;
104 967596729 : 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 973054377 : xchk_rmapbt_xref(
111 : struct xfs_scrub *sc,
112 : struct xfs_rmap_irec *irec)
113 : {
114 973054377 : xfs_agblock_t agbno = irec->rm_startblock;
115 973054377 : xfs_extlen_t len = irec->rm_blockcount;
116 :
117 973054377 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
118 : return;
119 :
120 973057456 : xchk_xref_is_used_space(sc, agbno, len);
121 974339079 : if (irec->rm_owner == XFS_RMAP_OWN_INODES)
122 17441237 : xchk_xref_is_inode_chunk(sc, agbno, len);
123 : else
124 956897842 : xchk_xref_is_not_inode_chunk(sc, agbno, len);
125 974667067 : if (irec->rm_owner == XFS_RMAP_OWN_COW)
126 6115371 : xchk_xref_is_cow_staging(sc, irec->rm_startblock,
127 : irec->rm_blockcount);
128 : else
129 968551696 : 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 973215844 : xchk_rmapbt_check_unwritten_in_keyflags(
146 : struct xchk_btree *bs)
147 : {
148 973215844 : struct xfs_scrub *sc = bs->sc;
149 973215844 : struct xfs_btree_cur *cur = bs->cur;
150 973215844 : struct xfs_btree_block *keyblock;
151 973215844 : union xfs_btree_key *lkey, *hkey;
152 973215844 : __be64 badflag = cpu_to_be64(XFS_RMAP_OFF_UNWRITTEN);
153 973215844 : unsigned int level;
154 :
155 973215844 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_PREEN)
156 : return;
157 :
158 2691531217 : for (level = 1; level < cur->bc_nlevels; level++) {
159 1718213442 : struct xfs_buf *bp;
160 1718213442 : unsigned int ptr;
161 :
162 : /* Only check the first time we've seen this node block. */
163 1718213442 : if (cur->bc_levels[level].ptr > 1)
164 1496607289 : continue;
165 :
166 221606153 : keyblock = xfs_btree_get_block(cur, level, &bp);
167 2070420820 : for (ptr = 1; ptr <= be16_to_cpu(keyblock->bb_numrecs); ptr++) {
168 1627106583 : lkey = xfs_btree_key_addr(cur, ptr, keyblock);
169 :
170 1627228869 : if (lkey->rmap.rm_offset & badflag) {
171 0 : xchk_btree_set_preen(sc, cur, level);
172 0 : break;
173 : }
174 :
175 1627228869 : hkey = xfs_btree_high_key_addr(cur, ptr, keyblock);
176 1627246608 : 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 227697155 : xchk_rmapbt_is_shareable(
186 : struct xfs_scrub *sc,
187 : const struct xfs_rmap_irec *irec)
188 : {
189 227697155 : if (!xfs_has_reflink(sc->mp))
190 : return false;
191 227697155 : if (XFS_RMAP_NON_INODE_OWNER(irec->rm_owner))
192 : return false;
193 227697155 : 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 973848442 : xchk_rmapbt_check_overlapping(
202 : struct xchk_btree *bs,
203 : struct xchk_rmap *cr,
204 : const struct xfs_rmap_irec *irec)
205 : {
206 973848442 : xfs_agblock_t pnext, inext;
207 :
208 973848442 : if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
209 : return;
210 :
211 : /* No previous record? */
212 973848442 : if (cr->overlap_rec.rm_blockcount == 0)
213 306022 : goto set_prev;
214 :
215 : /* Do overlap_rec and irec overlap? */
216 973542420 : pnext = cr->overlap_rec.rm_startblock + cr->overlap_rec.rm_blockcount;
217 973542420 : if (pnext <= irec->rm_startblock)
218 859689599 : goto set_prev;
219 :
220 : /* Overlap is only allowed if both records are data fork mappings. */
221 113852821 : if (!xchk_rmapbt_is_shareable(bs->sc, &cr->overlap_rec) ||
222 113852821 : !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 113860024 : inext = irec->rm_startblock + irec->rm_blockcount;
227 113860024 : if (pnext > inext)
228 : return;
229 :
230 87501024 : set_prev:
231 1894993290 : 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 974379716 : xchk_rmap_mergeable(
237 : struct xchk_rmap *cr,
238 : const struct xfs_rmap_irec *r2)
239 : {
240 974379716 : const struct xfs_rmap_irec *r1 = &cr->prev_rec;
241 :
242 : /* Ignore if prev_rec is not yet initialized. */
243 974379716 : if (cr->prev_rec.rm_blockcount == 0)
244 : return false;
245 :
246 974073517 : if (r1->rm_owner != r2->rm_owner)
247 : return false;
248 248855595 : if (r1->rm_startblock + r1->rm_blockcount != r2->rm_startblock)
249 : return false;
250 172758764 : if ((unsigned long long)r1->rm_blockcount + r2->rm_blockcount >
251 : XFS_RMAP_LEN_MAX)
252 : return false;
253 172758764 : if (XFS_RMAP_NON_INODE_OWNER(r2->rm_owner))
254 : return true;
255 : /* must be an inode owner below here */
256 172758764 : if (r1->rm_flags != r2->rm_flags)
257 : return false;
258 113004630 : if (r1->rm_flags & XFS_RMAP_BMBT_BLOCK)
259 : return true;
260 113004630 : 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 973773524 : xchk_rmapbt_check_mergeable(
266 : struct xchk_btree *bs,
267 : struct xchk_rmap *cr,
268 : const struct xfs_rmap_irec *irec)
269 : {
270 973773524 : if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
271 : return;
272 :
273 973773524 : if (xchk_rmap_mergeable(cr, irec))
274 0 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
275 :
276 1947547048 : 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 974764262 : xchk_rmapbt_mark_bitmap(
282 : struct xchk_btree *bs,
283 : struct xchk_rmap *cr,
284 : const struct xfs_rmap_irec *irec)
285 : {
286 974764262 : struct xfs_scrub *sc = bs->sc;
287 974764262 : struct xagb_bitmap *bmp = NULL;
288 974764262 : 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 974764262 : 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 974764262 : if (!cr->bitmaps_complete)
303 : return 0;
304 :
305 974764262 : switch (irec->rm_owner) {
306 306386 : case XFS_RMAP_OWN_FS:
307 306386 : bmp = &cr->fs_owned;
308 306386 : break;
309 34722 : case XFS_RMAP_OWN_LOG:
310 34722 : bmp = &cr->log_owned;
311 34722 : break;
312 6620071 : case XFS_RMAP_OWN_AG:
313 6620071 : bmp = &cr->ag_owned;
314 6620071 : break;
315 438106 : case XFS_RMAP_OWN_INOBT:
316 438106 : bmp = &cr->inobt_owned;
317 438106 : break;
318 379341 : case XFS_RMAP_OWN_REFC:
319 379341 : bmp = &cr->refcbt_owned;
320 379341 : break;
321 : }
322 :
323 7778626 : if (!bmp)
324 : return 0;
325 :
326 7778626 : 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 7777772 : if (fsbcount < irec->rm_blockcount)
334 0 : xchk_btree_xref_set_corrupt(bs->sc,
335 0 : 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 7777772 : return xagb_bitmap_clear(bmp, irec->rm_startblock, irec->rm_blockcount);
348 : }
349 :
350 : /* Scrub an rmapbt record. */
351 : STATIC int
352 974241213 : xchk_rmapbt_rec(
353 : struct xchk_btree *bs,
354 : const union xfs_btree_rec *rec)
355 : {
356 974241213 : struct xchk_rmap *cr = bs->private;
357 974241213 : struct xfs_rmap_irec irec;
358 :
359 1947591535 : if (xfs_rmap_btrec_to_irec(rec, &irec) != NULL ||
360 973518691 : 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 973353413 : xchk_rmapbt_check_unwritten_in_keyflags(bs);
366 973850759 : xchk_rmapbt_check_mergeable(bs, cr, &irec);
367 973590135 : xchk_rmapbt_check_overlapping(bs, cr, &irec);
368 972802596 : xchk_rmapbt_xref(bs->sc, &irec);
369 :
370 974369917 : return xchk_rmapbt_mark_bitmap(bs, cr, &irec);
371 : }
372 :
373 : /* Add an AGFL block to the rmap list. */
374 : STATIC int
375 1880437 : xchk_rmapbt_walk_agfl(
376 : struct xfs_mount *mp,
377 : xfs_agblock_t agbno,
378 : void *priv)
379 : {
380 1880437 : struct xagb_bitmap *bitmap = priv;
381 :
382 1880437 : 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 306802 : xchk_rmapbt_walk_ag_metadata(
396 : struct xfs_scrub *sc,
397 : struct xchk_rmap *cr)
398 : {
399 306802 : struct xfs_mount *mp = sc->mp;
400 306802 : struct xfs_buf *agfl_bp;
401 306802 : struct xfs_agf *agf = sc->sa.agf_bp->b_addr;
402 306802 : struct xfs_btree_cur *cur;
403 306802 : int error;
404 :
405 : /* OWN_FS: AG headers */
406 0 : error = xagb_bitmap_set(&cr->fs_owned, XFS_SB_BLOCK(mp),
407 306802 : XFS_AGFL_BLOCK(mp) - XFS_SB_BLOCK(mp) + 1);
408 305884 : if (error)
409 0 : goto out;
410 :
411 : /* OWN_LOG: Internal log */
412 305884 : if (xfs_ag_contains_log(mp, sc->sa.pag->pag_agno)) {
413 34722 : error = xagb_bitmap_set(&cr->log_owned,
414 34722 : XFS_FSB_TO_AGBNO(mp, mp->m_sb.sb_logstart),
415 : mp->m_sb.sb_logblocks);
416 34722 : if (error)
417 0 : goto out;
418 : }
419 :
420 : /* OWN_AG: bnobt, cntbt, rmapbt, and AGFL */
421 305867 : cur = sc->sa.bno_cur;
422 305867 : 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 305867 : error = xagb_bitmap_set_btblocks(&cr->ag_owned, cur);
426 306798 : if (cur != sc->sa.bno_cur)
427 0 : xfs_btree_del_cursor(cur, error);
428 306696 : if (error)
429 0 : goto out;
430 :
431 306696 : cur = sc->sa.cnt_cur;
432 306696 : 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 306696 : error = xagb_bitmap_set_btblocks(&cr->ag_owned, cur);
436 306334 : if (cur != sc->sa.cnt_cur)
437 0 : xfs_btree_del_cursor(cur, error);
438 306354 : if (error)
439 0 : goto out;
440 :
441 306354 : error = xagb_bitmap_set_btblocks(&cr->ag_owned, sc->sa.rmap_cur);
442 306674 : if (error)
443 0 : goto out;
444 :
445 306674 : error = xfs_alloc_read_agfl(sc->sa.pag, sc->tp, &agfl_bp);
446 307169 : if (error)
447 0 : goto out;
448 :
449 307169 : error = xfs_agfl_walk(sc->mp, agf, agfl_bp, xchk_rmapbt_walk_agfl,
450 : &cr->ag_owned);
451 307098 : xfs_trans_brelse(sc->tp, agfl_bp);
452 307225 : if (error)
453 0 : goto out;
454 :
455 : /* OWN_INOBT: inobt, finobt */
456 307225 : cur = sc->sa.ino_cur;
457 307225 : if (!cur)
458 0 : cur = xfs_inobt_init_cursor(sc->sa.pag, sc->tp, sc->sa.agi_bp,
459 : XFS_BTNUM_INO);
460 307225 : error = xagb_bitmap_set_btblocks(&cr->inobt_owned, cur);
461 307127 : if (cur != sc->sa.ino_cur)
462 0 : xfs_btree_del_cursor(cur, error);
463 306702 : if (error)
464 0 : goto out;
465 :
466 306702 : if (xfs_has_finobt(sc->mp)) {
467 307038 : cur = sc->sa.fino_cur;
468 307038 : if (!cur)
469 0 : cur = xfs_inobt_init_cursor(sc->sa.pag, sc->tp,
470 : sc->sa.agi_bp, XFS_BTNUM_FINO);
471 307038 : error = xagb_bitmap_set_btblocks(&cr->inobt_owned, cur);
472 307004 : if (cur != sc->sa.fino_cur)
473 0 : xfs_btree_del_cursor(cur, error);
474 307004 : if (error)
475 0 : goto out;
476 : }
477 :
478 : /* OWN_REFC: refcountbt */
479 306668 : if (xfs_has_reflink(sc->mp)) {
480 306475 : cur = sc->sa.refc_cur;
481 306475 : if (!cur)
482 0 : cur = xfs_refcountbt_init_cursor(sc->mp, sc->tp,
483 : sc->sa.agf_bp, sc->sa.pag);
484 306475 : error = xagb_bitmap_set_btblocks(&cr->refcbt_owned, cur);
485 306991 : if (cur != sc->sa.refc_cur)
486 0 : xfs_btree_del_cursor(cur, error);
487 306968 : if (error)
488 : goto out;
489 : }
490 :
491 307161 : 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 307161 : 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 307161 : cr->bitmaps_complete = true;
501 307161 : 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 306922 : xchk_rmapbt_check_bitmaps(
510 : struct xfs_scrub *sc,
511 : struct xchk_rmap *cr)
512 : {
513 306922 : struct xfs_btree_cur *cur = sc->sa.rmap_cur;
514 306922 : unsigned int level;
515 :
516 306922 : if (sc->sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT |
517 : XFS_SCRUB_OFLAG_XFAIL))
518 : return;
519 306922 : if (!cur)
520 : return;
521 306922 : 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 306922 : if (xagb_bitmap_hweight(&cr->fs_owned) != 0)
528 0 : xchk_btree_xref_set_corrupt(sc, cur, level);
529 :
530 306255 : if (xagb_bitmap_hweight(&cr->log_owned) != 0)
531 0 : xchk_btree_xref_set_corrupt(sc, cur, level);
532 :
533 306432 : if (xagb_bitmap_hweight(&cr->ag_owned) != 0)
534 0 : xchk_btree_xref_set_corrupt(sc, cur, level);
535 :
536 306497 : if (xagb_bitmap_hweight(&cr->inobt_owned) != 0)
537 0 : xchk_btree_xref_set_corrupt(sc, cur, level);
538 :
539 306622 : 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 306915 : xchk_rmapbt(
546 : struct xfs_scrub *sc)
547 : {
548 306915 : struct xchk_rmap *cr;
549 306915 : int error;
550 :
551 306915 : cr = kzalloc(sizeof(struct xchk_rmap), XCHK_GFP_FLAGS);
552 306966 : if (!cr)
553 : return -ENOMEM;
554 :
555 306966 : xagb_bitmap_init(&cr->fs_owned);
556 306745 : xagb_bitmap_init(&cr->log_owned);
557 306889 : xagb_bitmap_init(&cr->ag_owned);
558 306845 : xagb_bitmap_init(&cr->inobt_owned);
559 306833 : xagb_bitmap_init(&cr->refcbt_owned);
560 :
561 306808 : error = xchk_rmapbt_walk_ag_metadata(sc, cr);
562 306879 : if (error)
563 0 : goto out;
564 :
565 306879 : error = xchk_btree(sc, sc->sa.rmap_cur, xchk_rmapbt_rec,
566 : &XFS_RMAP_OINFO_AG, cr);
567 307026 : if (error)
568 5 : goto out;
569 :
570 307021 : xchk_rmapbt_check_bitmaps(sc, cr);
571 :
572 306806 : out:
573 306806 : xagb_bitmap_destroy(&cr->refcbt_owned);
574 306425 : xagb_bitmap_destroy(&cr->inobt_owned);
575 306552 : xagb_bitmap_destroy(&cr->ag_owned);
576 306589 : xagb_bitmap_destroy(&cr->log_owned);
577 306749 : xagb_bitmap_destroy(&cr->fs_owned);
578 306808 : kfree(cr);
579 306808 : return error;
580 : }
581 :
582 : /* xref check that the extent is owned only by a given owner */
583 : void
584 968809328 : 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 968809328 : struct xfs_rmap_matches res;
591 968809328 : int error;
592 :
593 968809328 : if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
594 12294844 : return;
595 :
596 956514484 : error = xfs_rmap_count_owners(sc->sa.rmap_cur, bno, len, oinfo, &res);
597 956876998 : if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
598 : return;
599 956715332 : if (res.matches != 1)
600 0 : xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
601 956715332 : if (res.bad_non_owner_matches)
602 0 : xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
603 956715332 : 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 26500048 : 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 26500048 : struct xfs_rmap_matches res;
616 26500048 : int error;
617 :
618 26500048 : if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
619 271268 : return;
620 :
621 26228780 : error = xfs_rmap_count_owners(sc->sa.rmap_cur, bno, len, oinfo, &res);
622 26228869 : if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
623 : return;
624 26228817 : if (res.matches != 0)
625 0 : xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
626 26228817 : 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 432718515 : xchk_xref_has_no_owner(
633 : struct xfs_scrub *sc,
634 : xfs_agblock_t bno,
635 : xfs_extlen_t len)
636 : {
637 432718515 : enum xbtree_recpacking outcome;
638 432718515 : int error;
639 :
640 432718515 : if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
641 532459 : return;
642 :
643 432186056 : error = xfs_rmap_has_records(sc->sa.rmap_cur, bno, len, &outcome);
644 432178515 : if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
645 : return;
646 432172965 : if (outcome != XBTREE_RECPACKING_EMPTY)
647 0 : xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
648 : }
|