Lines Matching +full:level +full:- +full:detect
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2017-2023 Oracle. All Rights Reserved.
51 /* Reverse-mapping scrubber. */
55 * The furthest-reaching of the rmapbt records that we've already
56 * processed. This enables us to detect overlapping records for space
78 /* Cross-reference a rmap against the refcount btree. */
92 if (!sc->sa.refc_cur || xchk_skip_xref(sc->sm)) in xchk_rmapbt_xref_refc()
95 non_inode = XFS_RMAP_NON_INODE_OWNER(irec->rm_owner); in xchk_rmapbt_xref_refc()
96 is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK; in xchk_rmapbt_xref_refc()
97 is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK; in xchk_rmapbt_xref_refc()
98 is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN; in xchk_rmapbt_xref_refc()
101 error = xfs_refcount_find_shared(sc->sa.refc_cur, irec->rm_startblock, in xchk_rmapbt_xref_refc()
102 irec->rm_blockcount, &fbno, &flen, false); in xchk_rmapbt_xref_refc()
103 if (!xchk_should_check_xref(sc, &error, &sc->sa.refc_cur)) in xchk_rmapbt_xref_refc()
106 xchk_btree_xref_set_corrupt(sc, sc->sa.refc_cur, 0); in xchk_rmapbt_xref_refc()
109 /* Cross-reference with the other btrees. */
115 xfs_agblock_t agbno = irec->rm_startblock; in xchk_rmapbt_xref()
116 xfs_extlen_t len = irec->rm_blockcount; in xchk_rmapbt_xref()
118 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_rmapbt_xref()
122 if (irec->rm_owner == XFS_RMAP_OWN_INODES) in xchk_rmapbt_xref()
126 if (irec->rm_owner == XFS_RMAP_OWN_COW) in xchk_rmapbt_xref()
127 xchk_xref_is_cow_staging(sc, irec->rm_startblock, in xchk_rmapbt_xref()
128 irec->rm_blockcount); in xchk_rmapbt_xref()
149 struct xfs_scrub *sc = bs->sc; in xchk_rmapbt_check_unwritten_in_keyflags()
150 struct xfs_btree_cur *cur = bs->cur; in xchk_rmapbt_check_unwritten_in_keyflags()
154 unsigned int level; in xchk_rmapbt_check_unwritten_in_keyflags() local
156 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_PREEN) in xchk_rmapbt_check_unwritten_in_keyflags()
159 for (level = 1; level < cur->bc_nlevels; level++) { in xchk_rmapbt_check_unwritten_in_keyflags()
164 if (cur->bc_levels[level].ptr > 1) in xchk_rmapbt_check_unwritten_in_keyflags()
167 keyblock = xfs_btree_get_block(cur, level, &bp); in xchk_rmapbt_check_unwritten_in_keyflags()
168 for (ptr = 1; ptr <= be16_to_cpu(keyblock->bb_numrecs); ptr++) { in xchk_rmapbt_check_unwritten_in_keyflags()
171 if (lkey->rmap.rm_offset & badflag) { in xchk_rmapbt_check_unwritten_in_keyflags()
172 xchk_btree_set_preen(sc, cur, level); in xchk_rmapbt_check_unwritten_in_keyflags()
177 if (hkey->rmap.rm_offset & badflag) { in xchk_rmapbt_check_unwritten_in_keyflags()
178 xchk_btree_set_preen(sc, cur, level); in xchk_rmapbt_check_unwritten_in_keyflags()
190 if (!xfs_has_reflink(sc->mp)) in xchk_rmapbt_is_shareable()
192 if (XFS_RMAP_NON_INODE_OWNER(irec->rm_owner)) in xchk_rmapbt_is_shareable()
194 if (irec->rm_flags & (XFS_RMAP_BMBT_BLOCK | XFS_RMAP_ATTR_FORK | in xchk_rmapbt_is_shareable()
209 if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_rmapbt_check_overlapping()
213 if (cr->overlap_rec.rm_blockcount == 0) in xchk_rmapbt_check_overlapping()
217 pnext = cr->overlap_rec.rm_startblock + cr->overlap_rec.rm_blockcount; in xchk_rmapbt_check_overlapping()
218 if (pnext <= irec->rm_startblock) in xchk_rmapbt_check_overlapping()
222 if (!xchk_rmapbt_is_shareable(bs->sc, &cr->overlap_rec) || in xchk_rmapbt_check_overlapping()
223 !xchk_rmapbt_is_shareable(bs->sc, irec)) in xchk_rmapbt_check_overlapping()
224 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); in xchk_rmapbt_check_overlapping()
227 inext = irec->rm_startblock + irec->rm_blockcount; in xchk_rmapbt_check_overlapping()
232 memcpy(&cr->overlap_rec, irec, sizeof(struct xfs_rmap_irec)); in xchk_rmapbt_check_overlapping()
235 /* Decide if two reverse-mapping records can be merged. */
241 const struct xfs_rmap_irec *r1 = &cr->prev_rec; in xchk_rmap_mergeable()
244 if (cr->prev_rec.rm_blockcount == 0) in xchk_rmap_mergeable()
247 if (r1->rm_owner != r2->rm_owner) in xchk_rmap_mergeable()
249 if (r1->rm_startblock + r1->rm_blockcount != r2->rm_startblock) in xchk_rmap_mergeable()
251 if ((unsigned long long)r1->rm_blockcount + r2->rm_blockcount > in xchk_rmap_mergeable()
254 if (XFS_RMAP_NON_INODE_OWNER(r2->rm_owner)) in xchk_rmap_mergeable()
257 if (r1->rm_flags != r2->rm_flags) in xchk_rmap_mergeable()
259 if (r1->rm_flags & XFS_RMAP_BMBT_BLOCK) in xchk_rmap_mergeable()
261 return r1->rm_offset + r1->rm_blockcount == r2->rm_offset; in xchk_rmap_mergeable()
271 if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_rmapbt_check_mergeable()
275 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); in xchk_rmapbt_check_mergeable()
277 memcpy(&cr->prev_rec, irec, sizeof(struct xfs_rmap_irec)); in xchk_rmapbt_check_mergeable()
287 struct xfs_scrub *sc = bs->sc; in xchk_rmapbt_mark_bitmap()
289 xfs_extlen_t fsbcount = irec->rm_blockcount; in xchk_rmapbt_mark_bitmap()
292 * Skip corrupt records. It is essential that we detect records in the in xchk_rmapbt_mark_bitmap()
296 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) in xchk_rmapbt_mark_bitmap()
303 if (!cr->bitmaps_complete) in xchk_rmapbt_mark_bitmap()
306 switch (irec->rm_owner) { in xchk_rmapbt_mark_bitmap()
308 bmp = &cr->fs_owned; in xchk_rmapbt_mark_bitmap()
311 bmp = &cr->log_owned; in xchk_rmapbt_mark_bitmap()
314 bmp = &cr->ag_owned; in xchk_rmapbt_mark_bitmap()
317 bmp = &cr->inobt_owned; in xchk_rmapbt_mark_bitmap()
320 bmp = &cr->refcbt_owned; in xchk_rmapbt_mark_bitmap()
327 if (xagb_bitmap_test(bmp, irec->rm_startblock, &fsbcount)) { in xchk_rmapbt_mark_bitmap()
334 if (fsbcount < irec->rm_blockcount) in xchk_rmapbt_mark_bitmap()
335 xchk_btree_xref_set_corrupt(bs->sc, in xchk_rmapbt_mark_bitmap()
336 bs->sc->sa.rmap_cur, 0); in xchk_rmapbt_mark_bitmap()
342 * cross-referencing corruption. in xchk_rmapbt_mark_bitmap()
344 xchk_btree_xref_set_corrupt(bs->sc, bs->sc->sa.rmap_cur, 0); in xchk_rmapbt_mark_bitmap()
347 /* Unset the region so that we can detect missing rmap records. */ in xchk_rmapbt_mark_bitmap()
348 return xagb_bitmap_clear(bmp, irec->rm_startblock, irec->rm_blockcount); in xchk_rmapbt_mark_bitmap()
357 struct xchk_rmap *cr = bs->private; in xchk_rmapbt_rec()
361 xfs_rmap_check_irec(bs->cur->bc_ag.pag, &irec) != NULL) { in xchk_rmapbt_rec()
362 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); in xchk_rmapbt_rec()
369 xchk_rmapbt_xref(bs->sc, &irec); in xchk_rmapbt_rec()
400 struct xfs_mount *mp = sc->mp; in xchk_rmapbt_walk_ag_metadata()
402 struct xfs_agf *agf = sc->sa.agf_bp->b_addr; in xchk_rmapbt_walk_ag_metadata()
407 error = xagb_bitmap_set(&cr->fs_owned, XFS_SB_BLOCK(mp), in xchk_rmapbt_walk_ag_metadata()
408 XFS_AGFL_BLOCK(mp) - XFS_SB_BLOCK(mp) + 1); in xchk_rmapbt_walk_ag_metadata()
413 if (xfs_ag_contains_log(mp, sc->sa.pag->pag_agno)) { in xchk_rmapbt_walk_ag_metadata()
414 error = xagb_bitmap_set(&cr->log_owned, in xchk_rmapbt_walk_ag_metadata()
415 XFS_FSB_TO_AGBNO(mp, mp->m_sb.sb_logstart), in xchk_rmapbt_walk_ag_metadata()
416 mp->m_sb.sb_logblocks); in xchk_rmapbt_walk_ag_metadata()
422 cur = sc->sa.bno_cur; in xchk_rmapbt_walk_ag_metadata()
424 cur = xfs_bnobt_init_cursor(sc->mp, sc->tp, sc->sa.agf_bp, in xchk_rmapbt_walk_ag_metadata()
425 sc->sa.pag); in xchk_rmapbt_walk_ag_metadata()
426 error = xagb_bitmap_set_btblocks(&cr->ag_owned, cur); in xchk_rmapbt_walk_ag_metadata()
427 if (cur != sc->sa.bno_cur) in xchk_rmapbt_walk_ag_metadata()
432 cur = sc->sa.cnt_cur; in xchk_rmapbt_walk_ag_metadata()
434 cur = xfs_cntbt_init_cursor(sc->mp, sc->tp, sc->sa.agf_bp, in xchk_rmapbt_walk_ag_metadata()
435 sc->sa.pag); in xchk_rmapbt_walk_ag_metadata()
436 error = xagb_bitmap_set_btblocks(&cr->ag_owned, cur); in xchk_rmapbt_walk_ag_metadata()
437 if (cur != sc->sa.cnt_cur) in xchk_rmapbt_walk_ag_metadata()
442 error = xagb_bitmap_set_btblocks(&cr->ag_owned, sc->sa.rmap_cur); in xchk_rmapbt_walk_ag_metadata()
446 error = xfs_alloc_read_agfl(sc->sa.pag, sc->tp, &agfl_bp); in xchk_rmapbt_walk_ag_metadata()
450 error = xfs_agfl_walk(sc->mp, agf, agfl_bp, xchk_rmapbt_walk_agfl, in xchk_rmapbt_walk_ag_metadata()
451 &cr->ag_owned); in xchk_rmapbt_walk_ag_metadata()
452 xfs_trans_brelse(sc->tp, agfl_bp); in xchk_rmapbt_walk_ag_metadata()
457 cur = sc->sa.ino_cur; in xchk_rmapbt_walk_ag_metadata()
459 cur = xfs_inobt_init_cursor(sc->sa.pag, sc->tp, sc->sa.agi_bp); in xchk_rmapbt_walk_ag_metadata()
460 error = xagb_bitmap_set_btblocks(&cr->inobt_owned, cur); in xchk_rmapbt_walk_ag_metadata()
461 if (cur != sc->sa.ino_cur) in xchk_rmapbt_walk_ag_metadata()
466 if (xfs_has_finobt(sc->mp)) { in xchk_rmapbt_walk_ag_metadata()
467 cur = sc->sa.fino_cur; in xchk_rmapbt_walk_ag_metadata()
469 cur = xfs_finobt_init_cursor(sc->sa.pag, sc->tp, in xchk_rmapbt_walk_ag_metadata()
470 sc->sa.agi_bp); in xchk_rmapbt_walk_ag_metadata()
471 error = xagb_bitmap_set_btblocks(&cr->inobt_owned, cur); in xchk_rmapbt_walk_ag_metadata()
472 if (cur != sc->sa.fino_cur) in xchk_rmapbt_walk_ag_metadata()
479 if (xfs_has_reflink(sc->mp)) { in xchk_rmapbt_walk_ag_metadata()
480 cur = sc->sa.refc_cur; in xchk_rmapbt_walk_ag_metadata()
482 cur = xfs_refcountbt_init_cursor(sc->mp, sc->tp, in xchk_rmapbt_walk_ag_metadata()
483 sc->sa.agf_bp, sc->sa.pag); in xchk_rmapbt_walk_ag_metadata()
484 error = xagb_bitmap_set_btblocks(&cr->refcbt_owned, cur); in xchk_rmapbt_walk_ag_metadata()
485 if (cur != sc->sa.refc_cur) in xchk_rmapbt_walk_ag_metadata()
494 * cross-referencing checks, but proceed with the scrub anyway. in xchk_rmapbt_walk_ag_metadata()
497 xchk_btree_xref_process_error(sc, sc->sa.rmap_cur, in xchk_rmapbt_walk_ag_metadata()
498 sc->sa.rmap_cur->bc_nlevels - 1, &error); in xchk_rmapbt_walk_ag_metadata()
500 cr->bitmaps_complete = true; in xchk_rmapbt_walk_ag_metadata()
513 struct xfs_btree_cur *cur = sc->sa.rmap_cur; in xchk_rmapbt_check_bitmaps()
514 unsigned int level; in xchk_rmapbt_check_bitmaps() local
516 if (sc->sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT | in xchk_rmapbt_check_bitmaps()
521 level = cur->bc_nlevels - 1; in xchk_rmapbt_check_bitmaps()
527 if (xagb_bitmap_hweight(&cr->fs_owned) != 0) in xchk_rmapbt_check_bitmaps()
528 xchk_btree_xref_set_corrupt(sc, cur, level); in xchk_rmapbt_check_bitmaps()
530 if (xagb_bitmap_hweight(&cr->log_owned) != 0) in xchk_rmapbt_check_bitmaps()
531 xchk_btree_xref_set_corrupt(sc, cur, level); in xchk_rmapbt_check_bitmaps()
533 if (xagb_bitmap_hweight(&cr->ag_owned) != 0) in xchk_rmapbt_check_bitmaps()
534 xchk_btree_xref_set_corrupt(sc, cur, level); in xchk_rmapbt_check_bitmaps()
536 if (xagb_bitmap_hweight(&cr->inobt_owned) != 0) in xchk_rmapbt_check_bitmaps()
537 xchk_btree_xref_set_corrupt(sc, cur, level); in xchk_rmapbt_check_bitmaps()
539 if (xagb_bitmap_hweight(&cr->refcbt_owned) != 0) in xchk_rmapbt_check_bitmaps()
540 xchk_btree_xref_set_corrupt(sc, cur, level); in xchk_rmapbt_check_bitmaps()
553 return -ENOMEM; in xchk_rmapbt()
555 xagb_bitmap_init(&cr->fs_owned); in xchk_rmapbt()
556 xagb_bitmap_init(&cr->log_owned); in xchk_rmapbt()
557 xagb_bitmap_init(&cr->ag_owned); in xchk_rmapbt()
558 xagb_bitmap_init(&cr->inobt_owned); in xchk_rmapbt()
559 xagb_bitmap_init(&cr->refcbt_owned); in xchk_rmapbt()
565 error = xchk_btree(sc, sc->sa.rmap_cur, xchk_rmapbt_rec, in xchk_rmapbt()
573 xagb_bitmap_destroy(&cr->refcbt_owned); in xchk_rmapbt()
574 xagb_bitmap_destroy(&cr->inobt_owned); in xchk_rmapbt()
575 xagb_bitmap_destroy(&cr->ag_owned); in xchk_rmapbt()
576 xagb_bitmap_destroy(&cr->log_owned); in xchk_rmapbt()
577 xagb_bitmap_destroy(&cr->fs_owned); in xchk_rmapbt()
593 if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm)) in xchk_xref_is_only_owned_by()
596 error = xfs_rmap_count_owners(sc->sa.rmap_cur, bno, len, oinfo, &res); in xchk_xref_is_only_owned_by()
597 if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur)) in xchk_xref_is_only_owned_by()
600 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0); in xchk_xref_is_only_owned_by()
602 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0); in xchk_xref_is_only_owned_by()
604 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0); in xchk_xref_is_only_owned_by()
618 if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm)) in xchk_xref_is_not_owned_by()
621 error = xfs_rmap_count_owners(sc->sa.rmap_cur, bno, len, oinfo, &res); in xchk_xref_is_not_owned_by()
622 if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur)) in xchk_xref_is_not_owned_by()
625 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0); in xchk_xref_is_not_owned_by()
627 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0); in xchk_xref_is_not_owned_by()
640 if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm)) in xchk_xref_has_no_owner()
643 error = xfs_rmap_has_records(sc->sa.rmap_cur, bno, len, &outcome); in xchk_xref_has_no_owner()
644 if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur)) in xchk_xref_has_no_owner()
647 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0); in xchk_xref_has_no_owner()