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 164309 : xchk_setup_ag_rmapbt(
34 : struct xfs_scrub *sc)
35 : {
36 164309 : if (xchk_need_intent_drain(sc))
37 2923 : xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
38 :
39 328618 : if (xchk_could_repair(sc)) {
40 15937 : int error;
41 :
42 15937 : error = xrep_setup_ag_rmapbt(sc);
43 15937 : if (error)
44 : return error;
45 : }
46 :
47 164309 : 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 635627966 : xchk_rmapbt_xref_refc(
80 : struct xfs_scrub *sc,
81 : struct xfs_rmap_irec *irec)
82 : {
83 635627966 : xfs_agblock_t fbno;
84 635627966 : xfs_extlen_t flen;
85 635627966 : bool non_inode;
86 635627966 : bool is_bmbt;
87 635627966 : bool is_attr;
88 635627966 : bool is_unwritten;
89 635627966 : int error;
90 :
91 635627966 : if (!sc->sa.refc_cur || xchk_skip_xref(sc->sm))
92 34347 : return;
93 :
94 635593619 : non_inode = XFS_RMAP_NON_INODE_OWNER(irec->rm_owner);
95 635593619 : is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK;
96 635593619 : is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK;
97 635593619 : is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN;
98 :
99 : /* If this is shared, must be a data fork extent. */
100 635593619 : error = xfs_refcount_find_shared(sc->sa.refc_cur, irec->rm_startblock,
101 : irec->rm_blockcount, &fbno, &flen, false);
102 635451108 : if (!xchk_should_check_xref(sc, &error, &sc->sa.refc_cur))
103 : return;
104 635427133 : 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 640621924 : xchk_rmapbt_xref(
111 : struct xfs_scrub *sc,
112 : struct xfs_rmap_irec *irec)
113 : {
114 640621924 : xfs_agblock_t agbno = irec->rm_startblock;
115 640621924 : xfs_extlen_t len = irec->rm_blockcount;
116 :
117 640621924 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
118 : return;
119 :
120 640639674 : xchk_xref_is_used_space(sc, agbno, len);
121 641250859 : if (irec->rm_owner == XFS_RMAP_OWN_INODES)
122 4053077 : xchk_xref_is_inode_chunk(sc, agbno, len);
123 : else
124 637197782 : xchk_xref_is_not_inode_chunk(sc, agbno, len);
125 641444899 : if (irec->rm_owner == XFS_RMAP_OWN_COW)
126 5861614 : xchk_xref_is_cow_staging(sc, irec->rm_startblock,
127 : irec->rm_blockcount);
128 : else
129 635583285 : 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 640822880 : xchk_rmapbt_check_unwritten_in_keyflags(
146 : struct xchk_btree *bs)
147 : {
148 640822880 : struct xfs_scrub *sc = bs->sc;
149 640822880 : struct xfs_btree_cur *cur = bs->cur;
150 640822880 : struct xfs_btree_block *keyblock;
151 640822880 : union xfs_btree_key *lkey, *hkey;
152 640822880 : __be64 badflag = cpu_to_be64(XFS_RMAP_OFF_UNWRITTEN);
153 640822880 : unsigned int level;
154 :
155 640822880 : if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_PREEN)
156 : return;
157 :
158 1874167717 : for (level = 1; level < cur->bc_nlevels; level++) {
159 1233313672 : struct xfs_buf *bp;
160 1233313672 : unsigned int ptr;
161 :
162 : /* Only check the first time we've seen this node block. */
163 1233313672 : if (cur->bc_levels[level].ptr > 1)
164 1086254202 : continue;
165 :
166 147059470 : keyblock = xfs_btree_get_block(cur, level, &bp);
167 1468744798 : for (ptr = 1; ptr <= be16_to_cpu(keyblock->bb_numrecs); ptr++) {
168 1174594693 : lkey = xfs_btree_key_addr(cur, ptr, keyblock);
169 :
170 1174654027 : if (lkey->rmap.rm_offset & badflag) {
171 0 : xchk_btree_set_preen(sc, cur, level);
172 0 : break;
173 : }
174 :
175 1174654027 : hkey = xfs_btree_high_key_addr(cur, ptr, keyblock);
176 1174636829 : 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 220823293 : xchk_rmapbt_is_shareable(
186 : struct xfs_scrub *sc,
187 : const struct xfs_rmap_irec *irec)
188 : {
189 220823293 : if (!xfs_has_reflink(sc->mp))
190 : return false;
191 220823293 : if (XFS_RMAP_NON_INODE_OWNER(irec->rm_owner))
192 : return false;
193 220823293 : 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 641003782 : xchk_rmapbt_check_overlapping(
202 : struct xchk_btree *bs,
203 : struct xchk_rmap *cr,
204 : const struct xfs_rmap_irec *irec)
205 : {
206 641003782 : xfs_agblock_t pnext, inext;
207 :
208 641003782 : if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
209 : return;
210 :
211 : /* No previous record? */
212 641003782 : if (cr->overlap_rec.rm_blockcount == 0)
213 161304 : goto set_prev;
214 :
215 : /* Do overlap_rec and irec overlap? */
216 640842478 : pnext = cr->overlap_rec.rm_startblock + cr->overlap_rec.rm_blockcount;
217 640842478 : if (pnext <= irec->rm_startblock)
218 530428568 : goto set_prev;
219 :
220 : /* Overlap is only allowed if both records are data fork mappings. */
221 110413910 : if (!xchk_rmapbt_is_shareable(bs->sc, &cr->overlap_rec) ||
222 110413910 : !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 110415392 : inext = irec->rm_startblock + irec->rm_blockcount;
227 110415392 : if (pnext > inext)
228 : return;
229 :
230 85401301 : set_prev:
231 1231982346 : 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 641282120 : xchk_rmap_mergeable(
237 : struct xchk_rmap *cr,
238 : const struct xfs_rmap_irec *r2)
239 : {
240 641282120 : const struct xfs_rmap_irec *r1 = &cr->prev_rec;
241 :
242 : /* Ignore if prev_rec is not yet initialized. */
243 641282120 : if (cr->prev_rec.rm_blockcount == 0)
244 : return false;
245 :
246 641120567 : if (r1->rm_owner != r2->rm_owner)
247 : return false;
248 170638773 : if (r1->rm_startblock + r1->rm_blockcount != r2->rm_startblock)
249 : return false;
250 95331484 : if ((unsigned long long)r1->rm_blockcount + r2->rm_blockcount >
251 : XFS_RMAP_LEN_MAX)
252 : return false;
253 95331484 : if (XFS_RMAP_NON_INODE_OWNER(r2->rm_owner))
254 : return true;
255 : /* must be an inode owner below here */
256 95331484 : if (r1->rm_flags != r2->rm_flags)
257 : return false;
258 35727190 : if (r1->rm_flags & XFS_RMAP_BMBT_BLOCK)
259 : return true;
260 35727190 : 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 640875901 : xchk_rmapbt_check_mergeable(
266 : struct xchk_btree *bs,
267 : struct xchk_rmap *cr,
268 : const struct xfs_rmap_irec *irec)
269 : {
270 640875901 : if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
271 : return;
272 :
273 640875901 : if (xchk_rmap_mergeable(cr, irec))
274 0 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
275 :
276 1281751802 : 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 641475165 : xchk_rmapbt_mark_bitmap(
282 : struct xchk_btree *bs,
283 : struct xchk_rmap *cr,
284 : const struct xfs_rmap_irec *irec)
285 : {
286 641475165 : struct xfs_scrub *sc = bs->sc;
287 641475165 : struct xagb_bitmap *bmp = NULL;
288 641475165 : 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 641475165 : 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 641475165 : if (!cr->bitmaps_complete)
303 : return 0;
304 :
305 641475165 : switch (irec->rm_owner) {
306 161607 : case XFS_RMAP_OWN_FS:
307 161607 : bmp = &cr->fs_owned;
308 161607 : break;
309 21323 : case XFS_RMAP_OWN_LOG:
310 21323 : bmp = &cr->log_owned;
311 21323 : break;
312 4461461 : case XFS_RMAP_OWN_AG:
313 4461461 : bmp = &cr->ag_owned;
314 4461461 : break;
315 220754 : case XFS_RMAP_OWN_INOBT:
316 220754 : bmp = &cr->inobt_owned;
317 220754 : break;
318 236411 : case XFS_RMAP_OWN_REFC:
319 236411 : bmp = &cr->refcbt_owned;
320 236411 : break;
321 : }
322 :
323 5101556 : if (!bmp)
324 : return 0;
325 :
326 5101556 : 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 5100722 : 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 5100722 : return xagb_bitmap_clear(bmp, irec->rm_startblock, irec->rm_blockcount);
348 : }
349 :
350 : /* Scrub an rmapbt record. */
351 : STATIC int
352 641332835 : xchk_rmapbt_rec(
353 : struct xchk_btree *bs,
354 : const union xfs_btree_rec *rec)
355 : {
356 641332835 : struct xchk_rmap *cr = bs->private;
357 641332835 : struct xfs_rmap_irec irec;
358 :
359 1282155375 : if (xfs_rmap_btrec_to_irec(rec, &irec) != NULL ||
360 641230230 : xfs_rmap_check_irec(bs->cur, &irec) != NULL) {
361 1 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
362 1 : return 0;
363 : }
364 :
365 640834339 : xchk_rmapbt_check_unwritten_in_keyflags(bs);
366 641065709 : xchk_rmapbt_check_mergeable(bs, cr, &irec);
367 640881005 : xchk_rmapbt_check_overlapping(bs, cr, &irec);
368 640566485 : xchk_rmapbt_xref(bs->sc, &irec);
369 :
370 641412043 : return xchk_rmapbt_mark_bitmap(bs, cr, &irec);
371 : }
372 :
373 : /* Add an AGFL block to the rmap list. */
374 : STATIC int
375 1004797 : xchk_rmapbt_walk_agfl(
376 : struct xfs_mount *mp,
377 : xfs_agblock_t agbno,
378 : void *priv)
379 : {
380 1004797 : struct xagb_bitmap *bitmap = priv;
381 :
382 1004797 : 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 161942 : xchk_rmapbt_walk_ag_metadata(
396 : struct xfs_scrub *sc,
397 : struct xchk_rmap *cr)
398 : {
399 161942 : struct xfs_mount *mp = sc->mp;
400 161942 : struct xfs_buf *agfl_bp;
401 161942 : struct xfs_agf *agf = sc->sa.agf_bp->b_addr;
402 161942 : struct xfs_btree_cur *cur;
403 161942 : int error;
404 :
405 : /* OWN_FS: AG headers */
406 0 : error = xagb_bitmap_set(&cr->fs_owned, XFS_SB_BLOCK(mp),
407 161942 : XFS_AGFL_BLOCK(mp) - XFS_SB_BLOCK(mp) + 1);
408 161316 : if (error)
409 0 : goto out;
410 :
411 : /* OWN_LOG: Internal log */
412 161316 : if (xfs_ag_contains_log(mp, sc->sa.pag->pag_agno)) {
413 21323 : error = xagb_bitmap_set(&cr->log_owned,
414 21323 : XFS_FSB_TO_AGBNO(mp, mp->m_sb.sb_logstart),
415 : mp->m_sb.sb_logblocks);
416 21323 : if (error)
417 0 : goto out;
418 : }
419 :
420 : /* OWN_AG: bnobt, cntbt, rmapbt, and AGFL */
421 161307 : cur = sc->sa.bno_cur;
422 161307 : 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 161307 : error = xagb_bitmap_set_btblocks(&cr->ag_owned, cur);
426 161981 : if (cur != sc->sa.bno_cur)
427 0 : xfs_btree_del_cursor(cur, error);
428 161893 : if (error)
429 0 : goto out;
430 :
431 161893 : cur = sc->sa.cnt_cur;
432 161893 : 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 161893 : error = xagb_bitmap_set_btblocks(&cr->ag_owned, cur);
436 161887 : if (cur != sc->sa.cnt_cur)
437 0 : xfs_btree_del_cursor(cur, error);
438 161853 : if (error)
439 0 : goto out;
440 :
441 161853 : error = xagb_bitmap_set_btblocks(&cr->ag_owned, sc->sa.rmap_cur);
442 161850 : if (error)
443 0 : goto out;
444 :
445 161850 : error = xfs_alloc_read_agfl(sc->sa.pag, sc->tp, &agfl_bp);
446 162137 : if (error)
447 0 : goto out;
448 :
449 162137 : error = xfs_agfl_walk(sc->mp, agf, agfl_bp, xchk_rmapbt_walk_agfl,
450 : &cr->ag_owned);
451 161987 : xfs_trans_brelse(sc->tp, agfl_bp);
452 162147 : if (error)
453 0 : goto out;
454 :
455 : /* OWN_INOBT: inobt, finobt */
456 162147 : cur = sc->sa.ino_cur;
457 162147 : if (!cur)
458 0 : cur = xfs_inobt_init_cursor(sc->sa.pag, sc->tp, sc->sa.agi_bp,
459 : XFS_BTNUM_INO);
460 162147 : error = xagb_bitmap_set_btblocks(&cr->inobt_owned, cur);
461 162042 : if (cur != sc->sa.ino_cur)
462 0 : xfs_btree_del_cursor(cur, error);
463 161783 : if (error)
464 0 : goto out;
465 :
466 161783 : if (xfs_has_finobt(sc->mp)) {
467 161966 : cur = sc->sa.fino_cur;
468 161966 : if (!cur)
469 0 : cur = xfs_inobt_init_cursor(sc->sa.pag, sc->tp,
470 : sc->sa.agi_bp, XFS_BTNUM_FINO);
471 161966 : error = xagb_bitmap_set_btblocks(&cr->inobt_owned, cur);
472 162002 : if (cur != sc->sa.fino_cur)
473 0 : xfs_btree_del_cursor(cur, error);
474 162002 : if (error)
475 0 : goto out;
476 : }
477 :
478 : /* OWN_REFC: refcountbt */
479 161819 : if (xfs_has_reflink(sc->mp)) {
480 161707 : cur = sc->sa.refc_cur;
481 161707 : if (!cur)
482 0 : cur = xfs_refcountbt_init_cursor(sc->mp, sc->tp,
483 : sc->sa.agf_bp, sc->sa.pag);
484 161707 : error = xagb_bitmap_set_btblocks(&cr->refcbt_owned, cur);
485 162017 : if (cur != sc->sa.refc_cur)
486 0 : xfs_btree_del_cursor(cur, error);
487 162012 : if (error)
488 : goto out;
489 : }
490 :
491 162124 : 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 162124 : 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 162124 : cr->bitmaps_complete = true;
501 162124 : 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 161982 : xchk_rmapbt_check_bitmaps(
510 : struct xfs_scrub *sc,
511 : struct xchk_rmap *cr)
512 : {
513 161982 : struct xfs_btree_cur *cur = sc->sa.rmap_cur;
514 161982 : unsigned int level;
515 :
516 161982 : if (sc->sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT |
517 : XFS_SCRUB_OFLAG_XFAIL))
518 : return;
519 161982 : if (!cur)
520 : return;
521 161982 : 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 161982 : if (xagb_bitmap_hweight(&cr->fs_owned) != 0)
528 0 : xchk_btree_xref_set_corrupt(sc, cur, level);
529 :
530 161524 : if (xagb_bitmap_hweight(&cr->log_owned) != 0)
531 0 : xchk_btree_xref_set_corrupt(sc, cur, level);
532 :
533 161536 : if (xagb_bitmap_hweight(&cr->ag_owned) != 0)
534 0 : xchk_btree_xref_set_corrupt(sc, cur, level);
535 :
536 161595 : if (xagb_bitmap_hweight(&cr->inobt_owned) != 0)
537 0 : xchk_btree_xref_set_corrupt(sc, cur, level);
538 :
539 161659 : 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 161976 : xchk_rmapbt(
546 : struct xfs_scrub *sc)
547 : {
548 161976 : struct xchk_rmap *cr;
549 161976 : int error;
550 :
551 161976 : cr = kzalloc(sizeof(struct xchk_rmap), XCHK_GFP_FLAGS);
552 161915 : if (!cr)
553 : return -ENOMEM;
554 :
555 161915 : xagb_bitmap_init(&cr->fs_owned);
556 161818 : xagb_bitmap_init(&cr->log_owned);
557 161967 : xagb_bitmap_init(&cr->ag_owned);
558 161909 : xagb_bitmap_init(&cr->inobt_owned);
559 161899 : xagb_bitmap_init(&cr->refcbt_owned);
560 :
561 161912 : error = xchk_rmapbt_walk_ag_metadata(sc, cr);
562 161911 : if (error)
563 0 : goto out;
564 :
565 161911 : error = xchk_btree(sc, sc->sa.rmap_cur, xchk_rmapbt_rec,
566 : &XFS_RMAP_OINFO_AG, cr);
567 161998 : if (error)
568 2 : goto out;
569 :
570 161996 : xchk_rmapbt_check_bitmaps(sc, cr);
571 :
572 161858 : out:
573 161858 : xagb_bitmap_destroy(&cr->refcbt_owned);
574 161588 : xagb_bitmap_destroy(&cr->inobt_owned);
575 161682 : xagb_bitmap_destroy(&cr->ag_owned);
576 161633 : xagb_bitmap_destroy(&cr->log_owned);
577 161695 : xagb_bitmap_destroy(&cr->fs_owned);
578 161690 : kfree(cr);
579 161690 : return error;
580 : }
581 :
582 : /* xref check that the extent is owned only by a given owner */
583 : void
584 669931633 : 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 669931633 : struct xfs_rmap_matches res;
591 669931633 : int error;
592 :
593 669931633 : if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
594 267639443 : return;
595 :
596 402292190 : error = xfs_rmap_count_owners(sc->sa.rmap_cur, bno, len, oinfo, &res);
597 402534164 : if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
598 : return;
599 402454449 : if (res.matches != 1)
600 0 : xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
601 402454449 : if (res.bad_non_owner_matches)
602 0 : xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
603 402454449 : 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 25577765 : 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 25577765 : struct xfs_rmap_matches res;
616 25577765 : int error;
617 :
618 25577765 : if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
619 12234362 : return;
620 :
621 13343403 : error = xfs_rmap_count_owners(sc->sa.rmap_cur, bno, len, oinfo, &res);
622 13343440 : if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
623 : return;
624 13343407 : if (res.matches != 0)
625 0 : xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
626 13343407 : 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 444947940 : xchk_xref_has_no_owner(
633 : struct xfs_scrub *sc,
634 : xfs_agblock_t bno,
635 : xfs_extlen_t len)
636 : {
637 444947940 : enum xbtree_recpacking outcome;
638 444947940 : int error;
639 :
640 444947940 : if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
641 3731202 : return;
642 :
643 441216738 : error = xfs_rmap_has_records(sc->sa.rmap_cur, bno, len, &outcome);
644 441209747 : if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
645 : return;
646 441205455 : if (outcome != XBTREE_RECPACKING_EMPTY)
647 0 : xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
648 : }
|