1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2017-2023 Oracle. All Rights Reserved.
8 #include "xfs_shared.h"
9 #include "xfs_format.h"
10 #include "xfs_trans_resv.h"
11 #include "xfs_mount.h"
12 #include "xfs_btree.h"
14 #include "xfs_log_format.h"
15 #include "xfs_trans.h"
16 #include "xfs_inode.h"
17 #include "xfs_alloc.h"
19 #include "xfs_bmap_btree.h"
21 #include "xfs_rmap_btree.h"
22 #include "scrub/scrub.h"
23 #include "scrub/common.h"
24 #include "scrub/btree.h"
27 /* Set us up with an inode's bmap. */
29 xchk_setup_inode_bmap(
34 if (xchk_need_intent_drain(sc))
35 xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
37 error = xchk_iget_for_scrubbing(sc);
41 sc->ilock_flags = XFS_IOLOCK_EXCL;
42 xfs_ilock(sc->ip, XFS_IOLOCK_EXCL);
45 * We don't want any ephemeral data/cow fork updates sitting around
46 * while we inspect block mappings, so wait for directio to finish
47 * and flush dirty data if we have delalloc reservations.
49 if (S_ISREG(VFS_I(sc->ip)->i_mode) &&
50 sc->sm->sm_type != XFS_SCRUB_TYPE_BMBTA) {
51 struct address_space *mapping = VFS_I(sc->ip)->i_mapping;
53 sc->ilock_flags |= XFS_MMAPLOCK_EXCL;
54 xfs_ilock(sc->ip, XFS_MMAPLOCK_EXCL);
56 inode_dio_wait(VFS_I(sc->ip));
59 * Try to flush all incore state to disk before we examine the
60 * space mappings for the data fork. Leave accumulated errors
61 * in the mapping for the writer threads to consume.
63 * On ENOSPC or EIO writeback errors, we continue into the
64 * extent mapping checks because write failures do not
65 * necessarily imply anything about the correctness of the file
66 * metadata. The metadata and the file data could be on
67 * completely separate devices; a media failure might only
68 * affect a subset of the disk, etc. We can handle delalloc
69 * extents in the scrubber, so leaving them in memory is fine.
71 error = filemap_fdatawrite(mapping);
73 error = filemap_fdatawait_keep_errors(mapping);
74 if (error && (error != -ENOSPC && error != -EIO))
78 /* Got the inode, lock it and we're ready to go. */
79 error = xchk_trans_alloc(sc, 0);
82 sc->ilock_flags |= XFS_ILOCK_EXCL;
83 xfs_ilock(sc->ip, XFS_ILOCK_EXCL);
86 /* scrub teardown will unlock and release the inode */
91 * Inode fork block mapping (BMBT) scrubber.
92 * More complex than the others because we have to scrub
93 * all the extents regardless of whether or not the fork
97 struct xchk_bmap_info {
100 /* Incore extent tree cursor */
101 struct xfs_iext_cursor icur;
103 /* Previous fork mapping that we examined */
104 struct xfs_bmbt_irec prev_rec;
106 /* Is this a realtime fork? */
109 /* May mappings point to shared space? */
112 /* Was the incore extent tree loaded? */
115 /* Which inode fork are we checking? */
119 /* Look for a corresponding rmap for this irec. */
122 struct xchk_bmap_info *info,
123 struct xfs_bmbt_irec *irec,
126 struct xfs_rmap_irec *rmap)
128 xfs_fileoff_t offset;
129 unsigned int rflags = 0;
133 if (info->whichfork == XFS_ATTR_FORK)
134 rflags |= XFS_RMAP_ATTR_FORK;
135 if (irec->br_state == XFS_EXT_UNWRITTEN)
136 rflags |= XFS_RMAP_UNWRITTEN;
139 * CoW staging extents are owned (on disk) by the refcountbt, so
140 * their rmaps do not have offsets.
142 if (info->whichfork == XFS_COW_FORK)
145 offset = irec->br_startoff;
148 * If the caller thinks this could be a shared bmbt extent (IOWs,
149 * any data fork extent of a reflink inode) then we have to use the
150 * range rmap lookup to make sure we get the correct owner/offset.
152 if (info->is_shared) {
153 error = xfs_rmap_lookup_le_range(info->sc->sa.rmap_cur, agbno,
154 owner, offset, rflags, rmap, &has_rmap);
156 error = xfs_rmap_lookup_le(info->sc->sa.rmap_cur, agbno,
157 owner, offset, rflags, rmap, &has_rmap);
159 if (!xchk_should_check_xref(info->sc, &error, &info->sc->sa.rmap_cur))
163 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
168 /* Make sure that we have rmapbt records for this data/attr fork extent. */
171 struct xchk_bmap_info *info,
172 struct xfs_bmbt_irec *irec,
175 struct xfs_rmap_irec rmap;
176 unsigned long long rmap_end;
177 uint64_t owner = info->sc->ip->i_ino;
179 if (!info->sc->sa.rmap_cur || xchk_skip_xref(info->sc->sm))
182 /* Find the rmap record for this irec. */
183 if (!xchk_bmap_get_rmap(info, irec, agbno, owner, &rmap))
187 * The rmap must be an exact match for this incore file mapping record,
188 * which may have arisen from multiple ondisk records.
190 if (rmap.rm_startblock != agbno)
191 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
194 rmap_end = (unsigned long long)rmap.rm_startblock + rmap.rm_blockcount;
195 if (rmap_end != agbno + irec->br_blockcount)
196 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
199 /* Check the logical offsets. */
200 if (rmap.rm_offset != irec->br_startoff)
201 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
204 rmap_end = (unsigned long long)rmap.rm_offset + rmap.rm_blockcount;
205 if (rmap_end != irec->br_startoff + irec->br_blockcount)
206 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
209 /* Check the owner */
210 if (rmap.rm_owner != owner)
211 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
215 * Check for discrepancies between the unwritten flag in the irec and
216 * the rmap. Note that the (in-memory) CoW fork distinguishes between
217 * unwritten and written extents, but we don't track that in the rmap
218 * records because the blocks are owned (on-disk) by the refcountbt,
219 * which doesn't track unwritten state.
221 if (!!(irec->br_state == XFS_EXT_UNWRITTEN) !=
222 !!(rmap.rm_flags & XFS_RMAP_UNWRITTEN))
223 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
226 if (!!(info->whichfork == XFS_ATTR_FORK) !=
227 !!(rmap.rm_flags & XFS_RMAP_ATTR_FORK))
228 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
230 if (rmap.rm_flags & XFS_RMAP_BMBT_BLOCK)
231 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
235 /* Make sure that we have rmapbt records for this COW fork extent. */
237 xchk_bmap_xref_rmap_cow(
238 struct xchk_bmap_info *info,
239 struct xfs_bmbt_irec *irec,
242 struct xfs_rmap_irec rmap;
243 unsigned long long rmap_end;
244 uint64_t owner = XFS_RMAP_OWN_COW;
246 if (!info->sc->sa.rmap_cur || xchk_skip_xref(info->sc->sm))
249 /* Find the rmap record for this irec. */
250 if (!xchk_bmap_get_rmap(info, irec, agbno, owner, &rmap))
254 * CoW staging extents are owned by the refcount btree, so the rmap
255 * can start before and end after the physical space allocated to this
256 * mapping. There are no offsets to check.
258 if (rmap.rm_startblock > agbno)
259 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
262 rmap_end = (unsigned long long)rmap.rm_startblock + rmap.rm_blockcount;
263 if (rmap_end < agbno + irec->br_blockcount)
264 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
267 /* Check the owner */
268 if (rmap.rm_owner != owner)
269 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
273 * No flags allowed. Note that the (in-memory) CoW fork distinguishes
274 * between unwritten and written extents, but we don't track that in
275 * the rmap records because the blocks are owned (on-disk) by the
276 * refcountbt, which doesn't track unwritten state.
278 if (rmap.rm_flags & XFS_RMAP_ATTR_FORK)
279 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
281 if (rmap.rm_flags & XFS_RMAP_BMBT_BLOCK)
282 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
284 if (rmap.rm_flags & XFS_RMAP_UNWRITTEN)
285 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
289 /* Cross-reference a single rtdev extent record. */
291 xchk_bmap_rt_iextent_xref(
292 struct xfs_inode *ip,
293 struct xchk_bmap_info *info,
294 struct xfs_bmbt_irec *irec)
296 xchk_xref_is_used_rt_space(info->sc, irec->br_startblock,
297 irec->br_blockcount);
300 /* Cross-reference a single datadev extent record. */
302 xchk_bmap_iextent_xref(
303 struct xfs_inode *ip,
304 struct xchk_bmap_info *info,
305 struct xfs_bmbt_irec *irec)
307 struct xfs_owner_info oinfo;
308 struct xfs_mount *mp = info->sc->mp;
314 agno = XFS_FSB_TO_AGNO(mp, irec->br_startblock);
315 agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock);
316 len = irec->br_blockcount;
318 error = xchk_ag_init_existing(info->sc, agno, &info->sc->sa);
319 if (!xchk_fblock_process_error(info->sc, info->whichfork,
320 irec->br_startoff, &error))
323 xchk_xref_is_used_space(info->sc, agbno, len);
324 xchk_xref_is_not_inode_chunk(info->sc, agbno, len);
325 switch (info->whichfork) {
327 xchk_bmap_xref_rmap(info, irec, agbno);
328 if (!xfs_is_reflink_inode(info->sc->ip)) {
329 xfs_rmap_ino_owner(&oinfo, info->sc->ip->i_ino,
330 info->whichfork, irec->br_startoff);
331 xchk_xref_is_only_owned_by(info->sc, agbno,
332 irec->br_blockcount, &oinfo);
333 xchk_xref_is_not_shared(info->sc, agbno,
334 irec->br_blockcount);
336 xchk_xref_is_not_cow_staging(info->sc, agbno,
337 irec->br_blockcount);
340 xchk_bmap_xref_rmap(info, irec, agbno);
341 xfs_rmap_ino_owner(&oinfo, info->sc->ip->i_ino,
342 info->whichfork, irec->br_startoff);
343 xchk_xref_is_only_owned_by(info->sc, agbno, irec->br_blockcount,
345 xchk_xref_is_not_shared(info->sc, agbno,
346 irec->br_blockcount);
347 xchk_xref_is_not_cow_staging(info->sc, agbno,
348 irec->br_blockcount);
351 xchk_bmap_xref_rmap_cow(info, irec, agbno);
352 xchk_xref_is_only_owned_by(info->sc, agbno, irec->br_blockcount,
353 &XFS_RMAP_OINFO_COW);
354 xchk_xref_is_cow_staging(info->sc, agbno,
355 irec->br_blockcount);
356 xchk_xref_is_not_shared(info->sc, agbno,
357 irec->br_blockcount);
362 xchk_ag_free(info->sc, &info->sc->sa);
366 * Directories and attr forks should never have blocks that can't be addressed
370 xchk_bmap_dirattr_extent(
371 struct xfs_inode *ip,
372 struct xchk_bmap_info *info,
373 struct xfs_bmbt_irec *irec)
375 struct xfs_mount *mp = ip->i_mount;
378 if (!S_ISDIR(VFS_I(ip)->i_mode) && info->whichfork != XFS_ATTR_FORK)
381 if (!xfs_verify_dablk(mp, irec->br_startoff))
382 xchk_fblock_set_corrupt(info->sc, info->whichfork,
385 off = irec->br_startoff + irec->br_blockcount - 1;
386 if (!xfs_verify_dablk(mp, off))
387 xchk_fblock_set_corrupt(info->sc, info->whichfork, off);
390 /* Scrub a single extent record. */
393 struct xfs_inode *ip,
394 struct xchk_bmap_info *info,
395 struct xfs_bmbt_irec *irec)
397 struct xfs_mount *mp = info->sc->mp;
400 * Check for out-of-order extents. This record could have come
401 * from the incore list, for which there is no ordering check.
403 if (irec->br_startoff < info->prev_rec.br_startoff +
404 info->prev_rec.br_blockcount)
405 xchk_fblock_set_corrupt(info->sc, info->whichfork,
408 if (!xfs_verify_fileext(mp, irec->br_startoff, irec->br_blockcount))
409 xchk_fblock_set_corrupt(info->sc, info->whichfork,
412 xchk_bmap_dirattr_extent(ip, info, irec);
414 /* Make sure the extent points to a valid place. */
416 !xfs_verify_rtext(mp, irec->br_startblock, irec->br_blockcount))
417 xchk_fblock_set_corrupt(info->sc, info->whichfork,
420 !xfs_verify_fsbext(mp, irec->br_startblock, irec->br_blockcount))
421 xchk_fblock_set_corrupt(info->sc, info->whichfork,
424 /* We don't allow unwritten extents on attr forks. */
425 if (irec->br_state == XFS_EXT_UNWRITTEN &&
426 info->whichfork == XFS_ATTR_FORK)
427 xchk_fblock_set_corrupt(info->sc, info->whichfork,
430 if (info->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
434 xchk_bmap_rt_iextent_xref(ip, info, irec);
436 xchk_bmap_iextent_xref(ip, info, irec);
439 /* Scrub a bmbt record. */
442 struct xchk_btree *bs,
443 const union xfs_btree_rec *rec)
445 struct xfs_bmbt_irec irec;
446 struct xfs_bmbt_irec iext_irec;
447 struct xfs_iext_cursor icur;
448 struct xchk_bmap_info *info = bs->private;
449 struct xfs_inode *ip = bs->cur->bc_ino.ip;
450 struct xfs_buf *bp = NULL;
451 struct xfs_btree_block *block;
452 struct xfs_ifork *ifp = xfs_ifork_ptr(ip, info->whichfork);
457 * Check the owners of the btree blocks up to the level below
458 * the root since the verifiers don't do that.
460 if (xfs_has_crc(bs->cur->bc_mp) &&
461 bs->cur->bc_levels[0].ptr == 1) {
462 for (i = 0; i < bs->cur->bc_nlevels - 1; i++) {
463 block = xfs_btree_get_block(bs->cur, i, &bp);
464 owner = be64_to_cpu(block->bb_u.l.bb_owner);
465 if (owner != ip->i_ino)
466 xchk_fblock_set_corrupt(bs->sc,
472 * Check that the incore extent tree contains an extent that matches
473 * this one exactly. We validate those cached bmaps later, so we don't
474 * need to check them here. If the incore extent tree was just loaded
475 * from disk by the scrubber, we assume that its contents match what's
476 * on disk (we still hold the ILOCK) and skip the equivalence check.
478 if (!info->was_loaded)
481 xfs_bmbt_disk_get_all(&rec->bmbt, &irec);
482 if (xfs_bmap_validate_extent(ip, info->whichfork, &irec) != NULL) {
483 xchk_fblock_set_corrupt(bs->sc, info->whichfork,
488 if (!xfs_iext_lookup_extent(ip, ifp, irec.br_startoff, &icur,
490 irec.br_startoff != iext_irec.br_startoff ||
491 irec.br_startblock != iext_irec.br_startblock ||
492 irec.br_blockcount != iext_irec.br_blockcount ||
493 irec.br_state != iext_irec.br_state)
494 xchk_fblock_set_corrupt(bs->sc, info->whichfork,
499 /* Scan the btree records. */
502 struct xfs_scrub *sc,
504 struct xchk_bmap_info *info)
506 struct xfs_owner_info oinfo;
507 struct xfs_ifork *ifp = xfs_ifork_ptr(sc->ip, whichfork);
508 struct xfs_mount *mp = sc->mp;
509 struct xfs_inode *ip = sc->ip;
510 struct xfs_btree_cur *cur;
513 /* Load the incore bmap cache if it's not loaded. */
514 info->was_loaded = !xfs_need_iread_extents(ifp);
516 error = xfs_iread_extents(sc->tp, ip, whichfork);
517 if (!xchk_fblock_process_error(sc, whichfork, 0, &error))
520 /* Check the btree structure. */
521 cur = xfs_bmbt_init_cursor(mp, sc->tp, ip, whichfork);
522 xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, whichfork);
523 error = xchk_btree(sc, cur, xchk_bmapbt_rec, &oinfo, info);
524 xfs_btree_del_cursor(cur, error);
529 struct xchk_bmap_check_rmap_info {
530 struct xfs_scrub *sc;
532 struct xfs_iext_cursor icur;
535 /* Can we find bmaps that fit this rmap? */
537 xchk_bmap_check_rmap(
538 struct xfs_btree_cur *cur,
539 const struct xfs_rmap_irec *rec,
542 struct xfs_bmbt_irec irec;
543 struct xfs_rmap_irec check_rec;
544 struct xchk_bmap_check_rmap_info *sbcri = priv;
545 struct xfs_ifork *ifp;
546 struct xfs_scrub *sc = sbcri->sc;
549 /* Is this even the right fork? */
550 if (rec->rm_owner != sc->ip->i_ino)
552 if ((sbcri->whichfork == XFS_ATTR_FORK) ^
553 !!(rec->rm_flags & XFS_RMAP_ATTR_FORK))
555 if (rec->rm_flags & XFS_RMAP_BMBT_BLOCK)
558 /* Now look up the bmbt record. */
559 ifp = xfs_ifork_ptr(sc->ip, sbcri->whichfork);
561 xchk_fblock_set_corrupt(sc, sbcri->whichfork,
565 have_map = xfs_iext_lookup_extent(sc->ip, ifp, rec->rm_offset,
566 &sbcri->icur, &irec);
568 xchk_fblock_set_corrupt(sc, sbcri->whichfork,
571 * bmap extent record lengths are constrained to 2^21 blocks in length
572 * because of space constraints in the on-disk metadata structure.
573 * However, rmap extent record lengths are constrained only by AG
574 * length, so we have to loop through the bmbt to make sure that the
575 * entire rmap is covered by bmbt records.
579 if (irec.br_startoff != check_rec.rm_offset)
580 xchk_fblock_set_corrupt(sc, sbcri->whichfork,
581 check_rec.rm_offset);
582 if (irec.br_startblock != XFS_AGB_TO_FSB(sc->mp,
583 cur->bc_ag.pag->pag_agno,
584 check_rec.rm_startblock))
585 xchk_fblock_set_corrupt(sc, sbcri->whichfork,
586 check_rec.rm_offset);
587 if (irec.br_blockcount > check_rec.rm_blockcount)
588 xchk_fblock_set_corrupt(sc, sbcri->whichfork,
589 check_rec.rm_offset);
590 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
592 check_rec.rm_startblock += irec.br_blockcount;
593 check_rec.rm_offset += irec.br_blockcount;
594 check_rec.rm_blockcount -= irec.br_blockcount;
595 if (check_rec.rm_blockcount == 0)
597 have_map = xfs_iext_next_extent(ifp, &sbcri->icur, &irec);
599 xchk_fblock_set_corrupt(sc, sbcri->whichfork,
600 check_rec.rm_offset);
604 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
609 /* Make sure each rmap has a corresponding bmbt entry. */
611 xchk_bmap_check_ag_rmaps(
612 struct xfs_scrub *sc,
614 struct xfs_perag *pag)
616 struct xchk_bmap_check_rmap_info sbcri;
617 struct xfs_btree_cur *cur;
621 error = xfs_alloc_read_agf(pag, sc->tp, 0, &agf);
625 cur = xfs_rmapbt_init_cursor(sc->mp, sc->tp, agf, pag);
628 sbcri.whichfork = whichfork;
629 error = xfs_rmap_query_all(cur, xchk_bmap_check_rmap, &sbcri);
630 if (error == -ECANCELED)
633 xfs_btree_del_cursor(cur, error);
634 xfs_trans_brelse(sc->tp, agf);
639 * Decide if we want to walk every rmap btree in the fs to make sure that each
640 * rmap for this file fork has corresponding bmbt entries.
643 xchk_bmap_want_check_rmaps(
644 struct xchk_bmap_info *info)
646 struct xfs_scrub *sc = info->sc;
647 struct xfs_ifork *ifp;
649 if (!xfs_has_rmapbt(sc->mp))
651 if (info->whichfork == XFS_COW_FORK)
653 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
656 /* Don't support realtime rmap checks yet. */
661 * The inode repair code zaps broken inode forks by resetting them back
662 * to EXTENTS format and zero extent records. If we encounter a fork
663 * in this state along with evidence that the fork isn't supposed to be
664 * empty, we need to scan the reverse mappings to decide if we're going
665 * to rebuild the fork. Data forks with nonzero file size are scanned.
666 * xattr forks are never empty of content, so they are always scanned.
668 ifp = xfs_ifork_ptr(sc->ip, info->whichfork);
669 if (ifp->if_format == XFS_DINODE_FMT_EXTENTS && ifp->if_nextents == 0) {
670 if (info->whichfork == XFS_DATA_FORK &&
671 i_size_read(VFS_I(sc->ip)) == 0)
680 /* Make sure each rmap has a corresponding bmbt entry. */
682 xchk_bmap_check_rmaps(
683 struct xfs_scrub *sc,
686 struct xfs_perag *pag;
690 for_each_perag(sc->mp, agno, pag) {
691 error = xchk_bmap_check_ag_rmaps(sc, whichfork, pag);
693 (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) {
702 /* Scrub a delalloc reservation from the incore extent map tree. */
704 xchk_bmap_iextent_delalloc(
705 struct xfs_inode *ip,
706 struct xchk_bmap_info *info,
707 struct xfs_bmbt_irec *irec)
709 struct xfs_mount *mp = info->sc->mp;
712 * Check for out-of-order extents. This record could have come
713 * from the incore list, for which there is no ordering check.
715 if (irec->br_startoff < info->prev_rec.br_startoff +
716 info->prev_rec.br_blockcount)
717 xchk_fblock_set_corrupt(info->sc, info->whichfork,
720 if (!xfs_verify_fileext(mp, irec->br_startoff, irec->br_blockcount))
721 xchk_fblock_set_corrupt(info->sc, info->whichfork,
724 /* Make sure the extent points to a valid place. */
725 if (irec->br_blockcount > XFS_MAX_BMBT_EXTLEN)
726 xchk_fblock_set_corrupt(info->sc, info->whichfork,
730 /* Decide if this individual fork mapping is ok. */
732 xchk_bmap_iext_mapping(
733 struct xchk_bmap_info *info,
734 const struct xfs_bmbt_irec *irec)
736 /* There should never be a "hole" extent in either extent list. */
737 if (irec->br_startblock == HOLESTARTBLOCK)
739 if (irec->br_blockcount > XFS_MAX_BMBT_EXTLEN)
744 /* Are these two mappings contiguous with each other? */
746 xchk_are_bmaps_contiguous(
747 const struct xfs_bmbt_irec *b1,
748 const struct xfs_bmbt_irec *b2)
750 /* Don't try to combine unallocated mappings. */
751 if (!xfs_bmap_is_real_extent(b1))
753 if (!xfs_bmap_is_real_extent(b2))
756 /* Does b2 come right after b1 in the logical and physical range? */
757 if (b1->br_startoff + b1->br_blockcount != b2->br_startoff)
759 if (b1->br_startblock + b1->br_blockcount != b2->br_startblock)
761 if (b1->br_state != b2->br_state)
767 * Walk the incore extent records, accumulating consecutive contiguous records
768 * into a single incore mapping. Returns true if @irec has been set to a
769 * mapping or false if there are no more mappings. Caller must ensure that
770 * @info.icur is zeroed before the first call.
774 struct xchk_bmap_info *info,
775 struct xfs_bmbt_irec *irec)
777 struct xfs_bmbt_irec got;
778 struct xfs_ifork *ifp;
781 ifp = xfs_ifork_ptr(info->sc->ip, info->whichfork);
783 /* Advance to the next iextent record and check the mapping. */
784 xfs_iext_next(ifp, &info->icur);
785 if (!xfs_iext_get_extent(ifp, &info->icur, irec))
788 if (!xchk_bmap_iext_mapping(info, irec)) {
789 xchk_fblock_set_corrupt(info->sc, info->whichfork,
796 * Iterate subsequent iextent records and merge them with the one
797 * that we just read, if possible.
799 while (xfs_iext_peek_next_extent(ifp, &info->icur, &got)) {
800 if (!xchk_are_bmaps_contiguous(irec, &got))
803 if (!xchk_bmap_iext_mapping(info, &got)) {
804 xchk_fblock_set_corrupt(info->sc, info->whichfork,
810 irec->br_blockcount += got.br_blockcount;
811 xfs_iext_next(ifp, &info->icur);
815 * If the merged mapping could be expressed with fewer bmbt records
816 * than we actually found, notify the user that this fork could be
817 * optimized. CoW forks only exist in memory so we ignore them.
819 if (nr > 1 && info->whichfork != XFS_COW_FORK &&
820 howmany_64(irec->br_blockcount, XFS_MAX_BMBT_EXTLEN) < nr)
821 xchk_ino_set_preen(info->sc, info->sc->ip->i_ino);
827 * Scrub an inode fork's block mappings.
829 * First we scan every record in every btree block, if applicable.
830 * Then we unconditionally scan the incore extent cache.
834 struct xfs_scrub *sc,
837 struct xfs_bmbt_irec irec;
838 struct xchk_bmap_info info = { NULL };
839 struct xfs_mount *mp = sc->mp;
840 struct xfs_inode *ip = sc->ip;
841 struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);
842 xfs_fileoff_t endoff;
845 /* Non-existent forks can be ignored. */
849 info.is_rt = whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip);
850 info.whichfork = whichfork;
851 info.is_shared = whichfork == XFS_DATA_FORK && xfs_is_reflink_inode(ip);
856 /* No CoW forks on non-reflink inodes/filesystems. */
857 if (!xfs_is_reflink_inode(ip)) {
858 xchk_ino_set_corrupt(sc, sc->ip->i_ino);
863 if (!xfs_has_attr(mp) && !xfs_has_attr2(mp))
864 xchk_ino_set_corrupt(sc, sc->ip->i_ino);
867 ASSERT(whichfork == XFS_DATA_FORK);
871 /* Check the fork values */
872 switch (ifp->if_format) {
873 case XFS_DINODE_FMT_UUID:
874 case XFS_DINODE_FMT_DEV:
875 case XFS_DINODE_FMT_LOCAL:
876 /* No mappings to check. */
877 if (whichfork == XFS_COW_FORK)
878 xchk_fblock_set_corrupt(sc, whichfork, 0);
880 case XFS_DINODE_FMT_EXTENTS:
882 case XFS_DINODE_FMT_BTREE:
883 if (whichfork == XFS_COW_FORK) {
884 xchk_fblock_set_corrupt(sc, whichfork, 0);
888 error = xchk_bmap_btree(sc, whichfork, &info);
893 xchk_fblock_set_corrupt(sc, whichfork, 0);
897 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
900 /* Find the offset of the last extent in the mapping. */
901 error = xfs_bmap_last_offset(ip, &endoff, whichfork);
902 if (!xchk_fblock_process_error(sc, whichfork, 0, &error))
906 * Scrub extent records. We use a special iterator function here that
907 * combines adjacent mappings if they are logically and physically
908 * contiguous. For large allocations that require multiple bmbt
909 * records, this reduces the number of cross-referencing calls, which
910 * reduces runtime. Cross referencing with the rmap is simpler because
911 * the rmap must match the combined mapping exactly.
913 while (xchk_bmap_iext_iter(&info, &irec)) {
914 if (xchk_should_terminate(sc, &error) ||
915 (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
918 if (irec.br_startoff >= endoff) {
919 xchk_fblock_set_corrupt(sc, whichfork,
924 if (isnullstartblock(irec.br_startblock))
925 xchk_bmap_iextent_delalloc(ip, &info, &irec);
927 xchk_bmap_iextent(ip, &info, &irec);
928 memcpy(&info.prev_rec, &irec, sizeof(struct xfs_bmbt_irec));
931 if (xchk_bmap_want_check_rmaps(&info)) {
932 error = xchk_bmap_check_rmaps(sc, whichfork);
933 if (!xchk_fblock_xref_process_error(sc, whichfork, 0, &error))
940 /* Scrub an inode's data fork. */
943 struct xfs_scrub *sc)
945 return xchk_bmap(sc, XFS_DATA_FORK);
948 /* Scrub an inode's attr fork. */
951 struct xfs_scrub *sc)
953 return xchk_bmap(sc, XFS_ATTR_FORK);
956 /* Scrub an inode's CoW fork. */
959 struct xfs_scrub *sc)
961 if (!xfs_is_reflink_inode(sc->ip))
964 return xchk_bmap(sc, XFS_COW_FORK);