1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
13 #include "err_protos.h"
23 static xfs_mount_t
*mp
= NULL
;
26 * Variables to validate AG header values against the manual count
27 * from the btree traversal.
31 xfs_extlen_t agffreeblks
;
32 xfs_extlen_t agflongest
;
33 uint64_t agfbtreeblks
;
35 uint32_t agifreecount
;
39 uint32_t fibtfreecount
;
43 set_mp(xfs_mount_t
*mpp
)
45 libxfs_bcache_purge();
55 void (*func
)(struct xfs_btree_block
*block
,
63 const struct xfs_buf_ops
*ops
),
67 const struct xfs_buf_ops
*ops
)
71 bp
= libxfs_readbuf(mp
->m_dev
, XFS_AGB_TO_DADDR(mp
, agno
, root
),
72 XFS_FSB_TO_BB(mp
, 1), 0, ops
);
74 do_error(_("can't read btree block %d/%d\n"), agno
, root
);
77 if (bp
->b_error
== -EFSBADCRC
|| bp
->b_error
== -EFSCORRUPTED
) {
78 do_warn(_("btree block %d/%d is suspect, error %d\n"),
79 agno
, root
, bp
->b_error
);
83 (*func
)(XFS_BUF_TO_BLOCK(bp
), nlevels
- 1, root
, agno
, suspect
,
84 isroot
, magic
, priv
, ops
);
89 * returns 1 on bad news (inode needs to be cleared), 0 on good
95 int (*func
)(struct xfs_btree_block
*block
,
104 bmap_cursor_t
*bm_cursor
,
115 bmap_cursor_t
*bm_cursor
,
119 const struct xfs_buf_ops
*ops
)
126 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, root
),
127 XFS_FSB_TO_BB(mp
, 1), 0, ops
);
129 do_error(_("can't read btree block %d/%d\n"),
130 XFS_FSB_TO_AGNO(mp
, root
),
131 XFS_FSB_TO_AGBNO(mp
, root
));
136 * only check for bad CRC here - caller will determine if there
137 * is a corruption or not and whether it got corrected and so needs
138 * writing back. CRC errors always imply we need to write the block.
140 if (bp
->b_error
== -EFSBADCRC
) {
141 do_warn(_("btree block %d/%d is suspect, error %d\n"),
142 XFS_FSB_TO_AGNO(mp
, root
),
143 XFS_FSB_TO_AGBNO(mp
, root
), bp
->b_error
);
147 err
= (*func
)(XFS_BUF_TO_BLOCK(bp
), nlevels
- 1,
148 type
, whichfork
, root
, ino
, tot
, nex
, blkmapp
,
149 bm_cursor
, isroot
, check_dups
, &dirty
,
152 ASSERT(dirty
== 0 || (dirty
&& !no_modify
));
154 if ((dirty
|| badcrc
) && !no_modify
)
155 libxfs_writebuf(bp
, 0);
164 struct xfs_btree_block
*block
,
173 bmap_cursor_t
*bm_cursor
,
182 xfs_bmbt_key_t
*pkey
;
184 xfs_fileoff_t first_key
;
185 xfs_fileoff_t last_key
;
186 char *forkname
= get_forkname(whichfork
);
194 * unlike the ag freeblock btrees, if anything looks wrong
195 * in an inode bmap tree, just bail. it's possible that
196 * we'll miss a case where the to-be-toasted inode and
197 * another inode are claiming the same block but that's
200 if (be32_to_cpu(block
->bb_magic
) != magic
) {
202 _("bad magic # %#x in inode %" PRIu64
" (%s fork) bmbt block %" PRIu64
"\n"),
203 be32_to_cpu(block
->bb_magic
), ino
, forkname
, bno
);
206 if (be16_to_cpu(block
->bb_level
) != level
) {
208 _("expected level %d got %d in inode %" PRIu64
", (%s fork) bmbt block %" PRIu64
"\n"),
209 level
, be16_to_cpu(block
->bb_level
),
214 if (magic
== XFS_BMAP_CRC_MAGIC
) {
216 if (be64_to_cpu(block
->bb_u
.l
.bb_owner
) != ino
) {
218 _("expected owner inode %" PRIu64
", got %llu, bmbt block %" PRIu64
"\n"),
220 (unsigned long long)be64_to_cpu(block
->bb_u
.l
.bb_owner
),
224 /* verify block number */
225 if (be64_to_cpu(block
->bb_u
.l
.bb_blkno
) !=
226 XFS_FSB_TO_DADDR(mp
, bno
)) {
228 _("expected block %" PRIu64
", got %llu, bmbt block %" PRIu64
"\n"),
229 XFS_FSB_TO_DADDR(mp
, bno
),
230 (unsigned long long)be64_to_cpu(block
->bb_u
.l
.bb_blkno
),
235 if (platform_uuid_compare(&block
->bb_u
.l
.bb_uuid
,
236 &mp
->m_sb
.sb_meta_uuid
) != 0) {
238 _("wrong FS UUID, bmbt block %" PRIu64
"\n"),
244 if (check_dups
== 0) {
246 * check sibling pointers. if bad we have a conflict
247 * between the sibling pointers and the child pointers
248 * in the parent block. blow out the inode if that happens
250 if (bm_cursor
->level
[level
].fsbno
!= NULLFSBLOCK
) {
252 * this is not the first block on this level
253 * so the cursor for this level has recorded the
254 * values for this's block left-sibling.
256 if (bno
!= bm_cursor
->level
[level
].right_fsbno
) {
258 _("bad fwd (right) sibling pointer (saw %" PRIu64
" parent block says %" PRIu64
")\n"
259 "\tin inode %" PRIu64
" (%s fork) bmap btree block %" PRIu64
"\n"),
260 bm_cursor
->level
[level
].right_fsbno
,
262 bm_cursor
->level
[level
].fsbno
);
265 if (be64_to_cpu(block
->bb_u
.l
.bb_leftsib
) !=
266 bm_cursor
->level
[level
].fsbno
) {
268 _("bad back (left) sibling pointer (saw %llu parent block says %" PRIu64
")\n"
269 "\tin inode %" PRIu64
" (%s fork) bmap btree block %" PRIu64
"\n"),
271 be64_to_cpu(block
->bb_u
.l
.bb_leftsib
),
272 bm_cursor
->level
[level
].fsbno
,
278 * This is the first or only block on this level.
279 * Check that the left sibling pointer is NULL
281 if (be64_to_cpu(block
->bb_u
.l
.bb_leftsib
) != NULLFSBLOCK
) {
283 _("bad back (left) sibling pointer (saw %llu should be NULL (0))\n"
284 "\tin inode %" PRIu64
" (%s fork) bmap btree block %" PRIu64
"\n"),
286 be64_to_cpu(block
->bb_u
.l
.bb_leftsib
),
293 * update cursor block pointers to reflect this block
295 bm_cursor
->level
[level
].fsbno
= bno
;
296 bm_cursor
->level
[level
].left_fsbno
=
297 be64_to_cpu(block
->bb_u
.l
.bb_leftsib
);
298 bm_cursor
->level
[level
].right_fsbno
=
299 be64_to_cpu(block
->bb_u
.l
.bb_rightsib
);
301 agno
= XFS_FSB_TO_AGNO(mp
, bno
);
302 agbno
= XFS_FSB_TO_AGBNO(mp
, bno
);
304 pthread_mutex_lock(&ag_locks
[agno
].lock
);
305 state
= get_bmap(agno
, agbno
);
309 * block was claimed as in use data by the rmap
310 * btree, but has not been found in the data extent
311 * map for the inode. That means this bmbt block hasn't
312 * yet been claimed as in use, which means -it's ours-
317 set_bmap(agno
, agbno
, XR_E_INUSE
);
322 * we'll try and continue searching here since
323 * the block looks like it's been claimed by file
324 * to store user data, a directory to store directory
325 * data, or the space allocation btrees but since
326 * we made it here, the block probably
327 * contains btree data.
329 set_bmap(agno
, agbno
, XR_E_MULT
);
331 _("inode 0x%" PRIx64
"bmap block 0x%" PRIx64
" claimed, state is %d\n"),
336 set_bmap(agno
, agbno
, XR_E_MULT
);
338 _("inode 0x%" PRIx64
" bmap block 0x%" PRIx64
" claimed, state is %d\n"),
341 * if we made it to here, this is probably a bmap block
342 * that is being used by *another* file as a bmap block
343 * so the block will be valid. Both files should be
344 * trashed along with any other file that impinges on
345 * any blocks referenced by either file. So we
346 * continue searching down this btree to mark all
353 _("bad state %d, inode %" PRIu64
" bmap block 0x%" PRIx64
"\n"),
357 pthread_mutex_unlock(&ag_locks
[agno
].lock
);
360 * attribute fork for realtime files is in the regular
363 if (type
!= XR_INO_RTDATA
|| whichfork
!= XFS_DATA_FORK
) {
364 if (search_dup_extent(XFS_FSB_TO_AGNO(mp
, bno
),
365 XFS_FSB_TO_AGBNO(mp
, bno
),
366 XFS_FSB_TO_AGBNO(mp
, bno
) + 1))
369 if (search_rt_dup_extent(mp
, bno
))
374 numrecs
= be16_to_cpu(block
->bb_numrecs
);
376 /* Record BMBT blocks in the reverse-mapping data. */
377 if (check_dups
&& collect_rmaps
) {
378 agno
= XFS_FSB_TO_AGNO(mp
, bno
);
379 pthread_mutex_lock(&ag_locks
[agno
].lock
);
380 error
= rmap_add_bmbt_rec(mp
, ino
, whichfork
, bno
);
381 pthread_mutex_unlock(&ag_locks
[agno
].lock
);
384 _("couldn't add inode %"PRIu64
" bmbt block %"PRIu64
" reverse-mapping data."),
389 if (numrecs
> mp
->m_bmap_dmxr
[0] || (isroot
== 0 && numrecs
<
390 mp
->m_bmap_dmnr
[0])) {
392 _("inode %" PRIu64
" bad # of bmap records (%u, min - %u, max - %u)\n"),
393 ino
, numrecs
, mp
->m_bmap_dmnr
[0],
397 rp
= XFS_BMBT_REC_ADDR(mp
, block
, 1);
400 * XXX - if we were going to fix up the btree record,
401 * we'd do it right here. For now, if there's a problem,
402 * we'll bail out and presumably clear the inode.
404 if (check_dups
== 0) {
405 err
= process_bmbt_reclist(mp
, rp
, &numrecs
, type
, ino
,
406 tot
, blkmapp
, &first_key
,
407 &last_key
, whichfork
);
412 * check that key ordering is monotonically increasing.
413 * if the last_key value in the cursor is set to
414 * NULLFILEOFF, then we know this is the first block
415 * on the leaf level and we shouldn't check the
418 if (first_key
<= bm_cursor
->level
[level
].last_key
&&
419 bm_cursor
->level
[level
].last_key
!=
422 _("out-of-order bmap key (file offset) in inode %" PRIu64
", %s fork, fsbno %" PRIu64
"\n"),
427 * update cursor keys to reflect this block.
428 * don't have to check if last_key is > first_key
429 * since that gets checked by process_bmbt_reclist.
431 bm_cursor
->level
[level
].first_key
= first_key
;
432 bm_cursor
->level
[level
].last_key
= last_key
;
436 return scan_bmbt_reclist(mp
, rp
, &numrecs
, type
, ino
,
440 if (numrecs
> mp
->m_bmap_dmxr
[1] || (isroot
== 0 && numrecs
<
441 mp
->m_bmap_dmnr
[1])) {
443 _("inode %" PRIu64
" bad # of bmap records (%u, min - %u, max - %u)\n"),
444 ino
, numrecs
, mp
->m_bmap_dmnr
[1], mp
->m_bmap_dmxr
[1]);
447 pp
= XFS_BMBT_PTR_ADDR(mp
, block
, 1, mp
->m_bmap_dmxr
[1]);
448 pkey
= XFS_BMBT_KEY_ADDR(mp
, block
, 1);
450 last_key
= NULLFILEOFF
;
452 for (i
= 0, err
= 0; i
< numrecs
; i
++) {
454 * XXX - if we were going to fix up the interior btree nodes,
455 * we'd do it right here. For now, if there's a problem,
456 * we'll bail out and presumably clear the inode.
458 if (!verify_dfsbno(mp
, be64_to_cpu(pp
[i
]))) {
460 _("bad bmap btree ptr 0x%llx in ino %" PRIu64
"\n"),
461 (unsigned long long) be64_to_cpu(pp
[i
]), ino
);
465 err
= scan_lbtree(be64_to_cpu(pp
[i
]), level
, scan_bmapbt
,
466 type
, whichfork
, ino
, tot
, nex
, blkmapp
,
467 bm_cursor
, 0, check_dups
, magic
,
473 * fix key (offset) mismatches between the first key
474 * in the child block (as recorded in the cursor) and the
475 * key in the interior node referencing the child block.
477 * fixes cases where entries have been shifted between
478 * child blocks but the parent hasn't been updated. We
479 * don't have to worry about the key values in the cursor
480 * not being set since we only look at the key values of
481 * our child and those are guaranteed to be set by the
482 * call to scan_lbtree() above.
484 if (check_dups
== 0 && be64_to_cpu(pkey
[i
].br_startoff
) !=
485 bm_cursor
->level
[level
-1].first_key
) {
488 _("correcting bt key (was %llu, now %" PRIu64
") in inode %" PRIu64
"\n"
489 "\t\t%s fork, btree block %" PRIu64
"\n"),
491 be64_to_cpu(pkey
[i
].br_startoff
),
492 bm_cursor
->level
[level
-1].first_key
,
496 pkey
[i
].br_startoff
= cpu_to_be64(
497 bm_cursor
->level
[level
-1].first_key
);
500 _("bad btree key (is %llu, should be %" PRIu64
") in inode %" PRIu64
"\n"
501 "\t\t%s fork, btree block %" PRIu64
"\n"),
503 be64_to_cpu(pkey
[i
].br_startoff
),
504 bm_cursor
->level
[level
-1].first_key
,
511 * If we're the last node at our level, check that the last child
512 * block's forward sibling pointer is NULL.
514 if (check_dups
== 0 &&
515 bm_cursor
->level
[level
].right_fsbno
== NULLFSBLOCK
&&
516 bm_cursor
->level
[level
- 1].right_fsbno
!= NULLFSBLOCK
) {
518 _("bad fwd (right) sibling pointer (saw %" PRIu64
" should be NULLFSBLOCK)\n"
519 "\tin inode %" PRIu64
" (%s fork) bmap btree block %" PRIu64
"\n"),
520 bm_cursor
->level
[level
- 1].right_fsbno
,
521 ino
, forkname
, bm_cursor
->level
[level
- 1].fsbno
);
526 * update cursor keys to reflect this block
528 if (check_dups
== 0) {
529 bm_cursor
->level
[level
].first_key
=
530 be64_to_cpu(pkey
[0].br_startoff
);
531 bm_cursor
->level
[level
].last_key
=
532 be64_to_cpu(pkey
[numrecs
- 1].br_startoff
);
540 struct xfs_btree_block
*block
,
548 const struct xfs_buf_ops
*ops
)
550 struct aghdr_cnts
*agcnts
= priv
;
558 xfs_extlen_t lastcount
= 0;
559 xfs_agblock_t lastblock
= 0;
562 case XFS_ABTB_CRC_MAGIC
:
566 case XFS_ABTC_CRC_MAGIC
:
576 if (be32_to_cpu(block
->bb_magic
) != magic
) {
577 do_warn(_("bad magic # %#x in bt%s block %d/%d\n"),
578 be32_to_cpu(block
->bb_magic
), name
, agno
, bno
);
585 * All freespace btree blocks except the roots are freed for a
586 * fully used filesystem, thus they are counted towards the
587 * free data block counter.
590 agcnts
->agfbtreeblks
++;
594 if (be16_to_cpu(block
->bb_level
) != level
) {
595 do_warn(_("expected level %d got %d in bt%s block %d/%d\n"),
596 level
, be16_to_cpu(block
->bb_level
), name
, agno
, bno
);
603 * check for btree blocks multiply claimed
605 state
= get_bmap(agno
, bno
);
606 if (state
!= XR_E_UNKNOWN
) {
607 set_bmap(agno
, bno
, XR_E_MULT
);
609 _("%s freespace btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
610 name
, state
, agno
, bno
, suspect
);
613 set_bmap(agno
, bno
, XR_E_FS_MAP
);
615 numrecs
= be16_to_cpu(block
->bb_numrecs
);
618 if (numrecs
> mp
->m_alloc_mxr
[0]) {
619 numrecs
= mp
->m_alloc_mxr
[0];
622 if (isroot
== 0 && numrecs
< mp
->m_alloc_mnr
[0]) {
623 numrecs
= mp
->m_alloc_mnr
[0];
629 _("bad btree nrecs (%u, min=%u, max=%u) in bt%s block %u/%u\n"),
630 be16_to_cpu(block
->bb_numrecs
),
631 mp
->m_alloc_mnr
[0], mp
->m_alloc_mxr
[0],
636 rp
= XFS_ALLOC_REC_ADDR(mp
, block
, 1);
637 for (i
= 0; i
< numrecs
; i
++) {
638 xfs_agblock_t b
, end
;
639 xfs_extlen_t len
, blen
;
641 b
= be32_to_cpu(rp
[i
].ar_startblock
);
642 len
= be32_to_cpu(rp
[i
].ar_blockcount
);
645 if (b
== 0 || !verify_agbno(mp
, agno
, b
)) {
647 _("invalid start block %u in record %u of %s btree block %u/%u\n"),
648 b
, i
, name
, agno
, bno
);
651 if (len
== 0 || !verify_agbno(mp
, agno
, end
- 1)) {
653 _("invalid length %u in record %u of %s btree block %u/%u\n"),
654 len
, i
, name
, agno
, bno
);
658 if (magic
== XFS_ABTB_MAGIC
||
659 magic
== XFS_ABTB_CRC_MAGIC
) {
660 if (b
<= lastblock
) {
662 "out-of-order bno btree record %d (%u %u) block %u/%u\n"),
663 i
, b
, len
, agno
, bno
);
668 agcnts
->fdblocks
+= len
;
669 agcnts
->agffreeblks
+= len
;
670 if (len
> agcnts
->agflongest
)
671 agcnts
->agflongest
= len
;
672 if (len
< lastcount
) {
674 "out-of-order cnt btree record %d (%u %u) block %u/%u\n"),
675 i
, b
, len
, agno
, bno
);
681 for ( ; b
< end
; b
+= blen
) {
682 state
= get_bmap_ext(agno
, b
, end
, &blen
);
685 set_bmap(agno
, b
, XR_E_FREE1
);
689 * no warning messages -- we'll catch
692 if (magic
== XFS_ABTC_MAGIC
||
693 magic
== XFS_ABTC_CRC_MAGIC
) {
694 set_bmap_ext(agno
, b
, blen
,
701 _("block (%d,%d-%d) multiply claimed by %s space tree, state - %d\n"),
702 agno
, b
, b
+ blen
- 1,
714 pp
= XFS_ALLOC_PTR_ADDR(mp
, block
, 1, mp
->m_alloc_mxr
[1]);
716 if (numrecs
> mp
->m_alloc_mxr
[1]) {
717 numrecs
= mp
->m_alloc_mxr
[1];
720 if (isroot
== 0 && numrecs
< mp
->m_alloc_mnr
[1]) {
721 numrecs
= mp
->m_alloc_mnr
[1];
726 * don't pass bogus tree flag down further if this block
727 * looked ok. bail out if two levels in a row look bad.
731 _("bad btree nrecs (%u, min=%u, max=%u) in bt%s block %u/%u\n"),
732 be16_to_cpu(block
->bb_numrecs
),
733 mp
->m_alloc_mnr
[1], mp
->m_alloc_mxr
[1],
738 } else if (suspect
) {
742 for (i
= 0; i
< numrecs
; i
++) {
743 xfs_agblock_t agbno
= be32_to_cpu(pp
[i
]);
746 * XXX - put sibling detection right here.
747 * we know our sibling chain is good. So as we go,
748 * we check the entry before and after each entry.
749 * If either of the entries references a different block,
750 * check the sibling pointer. If there's a sibling
751 * pointer mismatch, try and extract as much data
754 if (agbno
!= 0 && verify_agbno(mp
, agno
, agbno
)) {
755 scan_sbtree(agbno
, level
, agno
, suspect
, scan_allocbt
,
756 0, magic
, priv
, ops
);
763 struct xfs_inobt_rec
*rp
,
766 if (!xfs_sb_version_hassparseinodes(&mp
->m_sb
))
769 return xfs_inobt_is_sparse_disk(rp
, offset
);
772 /* See if the rmapbt owners agree with our observations. */
775 struct xfs_mount
*mp
,
787 case XFS_RMAP_OWN_FS
:
788 case XFS_RMAP_OWN_LOG
:
789 set_bmap_ext(agno
, b
, blen
, XR_E_INUSE_FS1
);
791 case XFS_RMAP_OWN_AG
:
792 case XFS_RMAP_OWN_INOBT
:
793 set_bmap_ext(agno
, b
, blen
, XR_E_FS_MAP1
);
795 case XFS_RMAP_OWN_INODES
:
796 set_bmap_ext(agno
, b
, blen
, XR_E_INO1
);
798 case XFS_RMAP_OWN_REFC
:
799 set_bmap_ext(agno
, b
, blen
, XR_E_REFC
);
801 case XFS_RMAP_OWN_COW
:
802 set_bmap_ext(agno
, b
, blen
, XR_E_COW
);
804 case XFS_RMAP_OWN_NULL
:
809 set_bmap_ext(agno
, b
, blen
, XR_E_INUSE1
);
814 if (owner
== XFS_RMAP_OWN_FS
||
815 owner
== XFS_RMAP_OWN_LOG
)
818 _("Static meta block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64
"\n"),
819 agno
, b
, b
+ blen
- 1,
823 if (owner
== XFS_RMAP_OWN_AG
||
824 owner
== XFS_RMAP_OWN_INOBT
)
827 _("AG meta block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64
"\n"),
828 agno
, b
, b
+ blen
- 1,
832 if (owner
== XFS_RMAP_OWN_INODES
)
835 _("inode block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64
"\n"),
836 agno
, b
, b
+ blen
- 1,
840 if (owner
== XFS_RMAP_OWN_REFC
)
843 _("AG refcount block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64
"\n"),
844 agno
, b
, b
+ blen
- 1,
849 owner
< mp
->m_sb
.sb_dblocks
)
852 _("in use block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64
"\n"),
853 agno
, b
, b
+ blen
- 1,
859 * May be on the AGFL. If not, they'll
865 * multiple inode owners are ok with
868 if (xfs_sb_version_hasreflink(&mp
->m_sb
) &&
869 !XFS_RMAP_NON_INODE_OWNER(owner
))
874 _("unknown block (%d,%d-%d) mismatch on %s tree, state - %d,%" PRIx64
"\n"),
875 agno
, b
, b
+ blen
- 1,
882 struct aghdr_cnts
*agcnts
;
883 struct xfs_rmap_irec high_key
;
884 struct xfs_rmap_irec last_rec
;
885 xfs_agblock_t nr_blocks
;
891 xfs_agblock_t lastblock
,
899 else if (b
< lastblock
)
902 if (owner
> lastowner
)
904 else if (owner
< lastowner
)
907 return offset
> lastoffset
;
912 struct xfs_btree_block
*block
,
920 const struct xfs_buf_ops
*ops
)
922 const char *name
= "rmap";
925 struct xfs_rmap_rec
*rp
;
926 struct rmap_priv
*rmap_priv
= priv
;
930 xfs_agblock_t lastblock
= 0;
931 uint64_t lastowner
= 0;
932 uint64_t lastoffset
= 0;
933 struct xfs_rmap_key
*kp
;
934 struct xfs_rmap_irec key
= {0};
936 if (magic
!= XFS_RMAP_CRC_MAGIC
) {
943 if (be32_to_cpu(block
->bb_magic
) != magic
) {
944 do_warn(_("bad magic # %#x in bt%s block %d/%d\n"),
945 be32_to_cpu(block
->bb_magic
), name
, agno
, bno
);
952 * All RMAP btree blocks except the roots are freed for a
953 * fully empty filesystem, thus they are counted towards the
954 * free data block counter.
957 rmap_priv
->agcnts
->agfbtreeblks
++;
958 rmap_priv
->agcnts
->fdblocks
++;
960 rmap_priv
->nr_blocks
++;
962 if (be16_to_cpu(block
->bb_level
) != level
) {
963 do_warn(_("expected level %d got %d in bt%s block %d/%d\n"),
964 level
, be16_to_cpu(block
->bb_level
), name
, agno
, bno
);
970 /* check for btree blocks multiply claimed */
971 state
= get_bmap(agno
, bno
);
972 if (!(state
== XR_E_UNKNOWN
|| state
== XR_E_FS_MAP1
)) {
973 set_bmap(agno
, bno
, XR_E_MULT
);
975 _("%s rmap btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
976 name
, state
, agno
, bno
, suspect
);
979 set_bmap(agno
, bno
, XR_E_FS_MAP
);
981 numrecs
= be16_to_cpu(block
->bb_numrecs
);
983 if (numrecs
> mp
->m_rmap_mxr
[0]) {
984 numrecs
= mp
->m_rmap_mxr
[0];
987 if (isroot
== 0 && numrecs
< mp
->m_rmap_mnr
[0]) {
988 numrecs
= mp
->m_rmap_mnr
[0];
994 _("bad btree nrecs (%u, min=%u, max=%u) in bt%s block %u/%u\n"),
995 be16_to_cpu(block
->bb_numrecs
),
996 mp
->m_rmap_mnr
[0], mp
->m_rmap_mxr
[0],
1001 rp
= XFS_RMAP_REC_ADDR(block
, 1);
1002 for (i
= 0; i
< numrecs
; i
++) {
1003 xfs_agblock_t b
, end
;
1004 xfs_extlen_t len
, blen
;
1005 int64_t owner
, offset
;
1007 b
= be32_to_cpu(rp
[i
].rm_startblock
);
1008 len
= be32_to_cpu(rp
[i
].rm_blockcount
);
1009 owner
= be64_to_cpu(rp
[i
].rm_owner
);
1010 offset
= be64_to_cpu(rp
[i
].rm_offset
);
1013 key
.rm_startblock
= b
;
1014 key
.rm_blockcount
= len
;
1015 key
.rm_owner
= owner
;
1016 if (libxfs_rmap_irec_offset_unpack(offset
, &key
)) {
1017 /* Look for impossible flags. */
1019 _("invalid flags in record %u of %s btree block %u/%u\n"),
1020 i
, name
, agno
, bno
);
1024 end
= key
.rm_startblock
+ key
.rm_blockcount
;
1026 /* Make sure agbno & len make sense. */
1027 if (!verify_agbno(mp
, agno
, b
)) {
1029 _("invalid start block %u in record %u of %s btree block %u/%u\n"),
1030 b
, i
, name
, agno
, bno
);
1033 if (len
== 0 || !verify_agbno(mp
, agno
, end
- 1)) {
1035 _("invalid length %u in record %u of %s btree block %u/%u\n"),
1036 len
, i
, name
, agno
, bno
);
1040 /* Look for impossible owners. */
1041 if (!((owner
> XFS_RMAP_OWN_MIN
&&
1042 owner
<= XFS_RMAP_OWN_FS
) ||
1043 (XFS_INO_TO_AGNO(mp
, owner
) < mp
->m_sb
.sb_agcount
&&
1044 XFS_AGINO_TO_AGBNO(mp
,
1045 XFS_INO_TO_AGINO(mp
, owner
)) <
1046 mp
->m_sb
.sb_agblocks
)))
1048 _("invalid owner in rmap btree record %d (%"PRId64
" %u) block %u/%u\n"),
1049 i
, owner
, len
, agno
, bno
);
1051 /* Look for impossible record field combinations. */
1052 if (XFS_RMAP_NON_INODE_OWNER(key
.rm_owner
)) {
1055 _("record %d of block (%u/%u) in %s btree cannot have non-inode owner with flags\n"),
1056 i
, agno
, bno
, name
);
1059 _("record %d of block (%u/%u) in %s btree cannot have non-inode owner with offset\n"),
1060 i
, agno
, bno
, name
);
1063 /* Check for out of order records. */
1068 lastoffset
= offset
;
1072 if (xfs_sb_version_hasreflink(&mp
->m_sb
))
1073 bad
= !rmap_in_order(b
, lastblock
,
1075 offset
, lastoffset
);
1077 bad
= b
<= lastblock
;
1080 _("out-of-order rmap btree record %d (%u %"PRId64
" %"PRIx64
" %u) block %u/%u\n"),
1081 i
, b
, owner
, offset
, len
, agno
, bno
);
1086 /* Is this mergeable with the previous record? */
1087 if (rmaps_are_mergeable(&rmap_priv
->last_rec
, &key
)) {
1089 _("record %d in block (%u/%u) of %s tree should be merged with previous record\n"),
1090 i
, agno
, bno
, name
);
1091 rmap_priv
->last_rec
.rm_blockcount
+=
1094 rmap_priv
->last_rec
= key
;
1096 /* Check that we don't go past the high key. */
1097 key
.rm_startblock
+= key
.rm_blockcount
- 1;
1098 if (!XFS_RMAP_NON_INODE_OWNER(key
.rm_owner
) &&
1099 !(key
.rm_flags
& XFS_RMAP_BMBT_BLOCK
))
1100 key
.rm_offset
+= key
.rm_blockcount
- 1;
1101 key
.rm_blockcount
= 0;
1102 if (rmap_diffkeys(&key
, &rmap_priv
->high_key
) > 0) {
1104 _("record %d greater than high key of block (%u/%u) in %s tree\n"),
1105 i
, agno
, bno
, name
);
1108 /* Check for block owner collisions. */
1109 for ( ; b
< end
; b
+= blen
) {
1110 state
= get_bmap_ext(agno
, b
, end
, &blen
);
1111 process_rmap_rec(mp
, agno
, b
, end
, blen
, owner
,
1121 pp
= XFS_RMAP_PTR_ADDR(block
, 1, mp
->m_rmap_mxr
[1]);
1123 if (numrecs
> mp
->m_rmap_mxr
[1]) {
1124 numrecs
= mp
->m_rmap_mxr
[1];
1127 if (isroot
== 0 && numrecs
< mp
->m_rmap_mnr
[1]) {
1128 numrecs
= mp
->m_rmap_mnr
[1];
1133 * don't pass bogus tree flag down further if this block
1134 * looked ok. bail out if two levels in a row look bad.
1138 _("bad btree nrecs (%u, min=%u, max=%u) in bt%s block %u/%u\n"),
1139 be16_to_cpu(block
->bb_numrecs
),
1140 mp
->m_rmap_mnr
[1], mp
->m_rmap_mxr
[1],
1145 } else if (suspect
) {
1149 /* check the node's high keys */
1150 for (i
= 0; !isroot
&& i
< numrecs
; i
++) {
1151 kp
= XFS_RMAP_HIGH_KEY_ADDR(block
, i
+ 1);
1154 key
.rm_startblock
= be32_to_cpu(kp
->rm_startblock
);
1155 key
.rm_owner
= be64_to_cpu(kp
->rm_owner
);
1156 if (libxfs_rmap_irec_offset_unpack(be64_to_cpu(kp
->rm_offset
),
1158 /* Look for impossible flags. */
1160 _("invalid flags in key %u of %s btree block %u/%u\n"),
1161 i
, name
, agno
, bno
);
1164 if (rmap_diffkeys(&key
, &rmap_priv
->high_key
) > 0)
1166 _("key %d greater than high key of block (%u/%u) in %s tree\n"),
1167 i
, agno
, bno
, name
);
1170 for (i
= 0; i
< numrecs
; i
++) {
1171 xfs_agblock_t agbno
= be32_to_cpu(pp
[i
]);
1174 * XXX - put sibling detection right here.
1175 * we know our sibling chain is good. So as we go,
1176 * we check the entry before and after each entry.
1177 * If either of the entries references a different block,
1178 * check the sibling pointer. If there's a sibling
1179 * pointer mismatch, try and extract as much data
1182 kp
= XFS_RMAP_HIGH_KEY_ADDR(block
, i
+ 1);
1183 rmap_priv
->high_key
.rm_flags
= 0;
1184 rmap_priv
->high_key
.rm_startblock
=
1185 be32_to_cpu(kp
->rm_startblock
);
1186 rmap_priv
->high_key
.rm_owner
=
1187 be64_to_cpu(kp
->rm_owner
);
1188 if (libxfs_rmap_irec_offset_unpack(be64_to_cpu(kp
->rm_offset
),
1189 &rmap_priv
->high_key
)) {
1190 /* Look for impossible flags. */
1192 _("invalid flags in high key %u of %s btree block %u/%u\n"),
1193 i
, name
, agno
, agbno
);
1197 if (agbno
!= 0 && verify_agbno(mp
, agno
, agbno
)) {
1198 scan_sbtree(agbno
, level
, agno
, suspect
, scan_rmapbt
, 0,
1209 struct xfs_refcount_irec last_rec
;
1210 xfs_agblock_t nr_blocks
;
1216 struct xfs_btree_block
*block
,
1219 xfs_agnumber_t agno
,
1224 const struct xfs_buf_ops
*ops
)
1226 const char *name
= "refcount";
1228 xfs_refcount_ptr_t
*pp
;
1229 struct xfs_refcount_rec
*rp
;
1233 xfs_agblock_t lastblock
= 0;
1234 struct refc_priv
*refc_priv
= priv
;
1236 if (magic
!= XFS_REFC_CRC_MAGIC
) {
1243 if (be32_to_cpu(block
->bb_magic
) != magic
) {
1244 do_warn(_("bad magic # %#x in %s btree block %d/%d\n"),
1245 be32_to_cpu(block
->bb_magic
), name
, agno
, bno
);
1251 if (be16_to_cpu(block
->bb_level
) != level
) {
1252 do_warn(_("expected level %d got %d in %s btree block %d/%d\n"),
1253 level
, be16_to_cpu(block
->bb_level
), name
, agno
, bno
);
1259 refc_priv
->nr_blocks
++;
1261 /* check for btree blocks multiply claimed */
1262 state
= get_bmap(agno
, bno
);
1263 if (!(state
== XR_E_UNKNOWN
|| state
== XR_E_REFC
)) {
1264 set_bmap(agno
, bno
, XR_E_MULT
);
1266 _("%s btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
1267 name
, state
, agno
, bno
, suspect
);
1270 set_bmap(agno
, bno
, XR_E_FS_MAP
);
1272 numrecs
= be16_to_cpu(block
->bb_numrecs
);
1274 if (numrecs
> mp
->m_refc_mxr
[0]) {
1275 numrecs
= mp
->m_refc_mxr
[0];
1278 if (isroot
== 0 && numrecs
< mp
->m_refc_mnr
[0]) {
1279 numrecs
= mp
->m_refc_mnr
[0];
1285 _("bad btree nrecs (%u, min=%u, max=%u) in %s btree block %u/%u\n"),
1286 be16_to_cpu(block
->bb_numrecs
),
1287 mp
->m_refc_mnr
[0], mp
->m_refc_mxr
[0],
1292 rp
= XFS_REFCOUNT_REC_ADDR(block
, 1);
1293 for (i
= 0; i
< numrecs
; i
++) {
1294 xfs_agblock_t b
, agb
, end
;
1298 b
= agb
= be32_to_cpu(rp
[i
].rc_startblock
);
1299 len
= be32_to_cpu(rp
[i
].rc_blockcount
);
1300 nr
= be32_to_cpu(rp
[i
].rc_refcount
);
1301 if (b
>= XFS_REFC_COW_START
&& nr
!= 1)
1303 _("leftover CoW extent has incorrect refcount in record %u of %s btree block %u/%u\n"),
1304 i
, name
, agno
, bno
);
1306 if (agb
< XFS_REFC_COW_START
)
1308 _("leftover CoW extent has invalid startblock in record %u of %s btree block %u/%u\n"),
1309 i
, name
, agno
, bno
);
1310 agb
-= XFS_REFC_COW_START
;
1314 if (!verify_agbno(mp
, agno
, agb
)) {
1316 _("invalid start block %u in record %u of %s btree block %u/%u\n"),
1317 b
, i
, name
, agno
, bno
);
1320 if (len
== 0 || !verify_agbno(mp
, agno
, end
- 1)) {
1322 _("invalid length %u in record %u of %s btree block %u/%u\n"),
1323 len
, i
, name
, agno
, bno
);
1331 for (c
= agb
; c
< end
; c
+= cnr
) {
1332 state
= get_bmap_ext(agno
, c
, end
, &cnr
);
1337 _("leftover CoW extent (%u/%u) len %u\n"),
1339 set_bmap_ext(agno
, c
, cnr
, XR_E_FREE
);
1343 _("extent (%u/%u) len %u claimed, state is %d\n"),
1344 agno
, c
, cnr
, state
);
1348 } else if (nr
< 2 || nr
> MAXREFCOUNT
) {
1350 _("invalid reference count %u in record %u of %s btree block %u/%u\n"),
1351 nr
, i
, name
, agno
, bno
);
1355 if (b
&& b
<= lastblock
) {
1357 "out-of-order %s btree record %d (%u %u) block %u/%u\n"),
1358 name
, i
, b
, len
, agno
, bno
);
1363 /* Is this record mergeable with the last one? */
1364 if (refc_priv
->last_rec
.rc_startblock
+
1365 refc_priv
->last_rec
.rc_blockcount
== b
&&
1366 refc_priv
->last_rec
.rc_refcount
== nr
) {
1368 _("record %d in block (%u/%u) of %s tree should be merged with previous record\n"),
1369 i
, agno
, bno
, name
);
1370 refc_priv
->last_rec
.rc_blockcount
+= len
;
1372 refc_priv
->last_rec
.rc_startblock
= b
;
1373 refc_priv
->last_rec
.rc_blockcount
= len
;
1374 refc_priv
->last_rec
.rc_refcount
= nr
;
1377 /* XXX: probably want to mark the reflinked areas? */
1385 pp
= XFS_REFCOUNT_PTR_ADDR(block
, 1, mp
->m_refc_mxr
[1]);
1387 if (numrecs
> mp
->m_refc_mxr
[1]) {
1388 numrecs
= mp
->m_refc_mxr
[1];
1391 if (isroot
== 0 && numrecs
< mp
->m_refc_mnr
[1]) {
1392 numrecs
= mp
->m_refc_mnr
[1];
1397 * don't pass bogus tree flag down further if this block
1398 * looked ok. bail out if two levels in a row look bad.
1402 _("bad btree nrecs (%u, min=%u, max=%u) in %s btree block %u/%u\n"),
1403 be16_to_cpu(block
->bb_numrecs
),
1404 mp
->m_refc_mnr
[1], mp
->m_refc_mxr
[1],
1409 } else if (suspect
) {
1413 for (i
= 0; i
< numrecs
; i
++) {
1414 xfs_agblock_t agbno
= be32_to_cpu(pp
[i
]);
1416 if (agbno
!= 0 && verify_agbno(mp
, agno
, agbno
)) {
1417 scan_sbtree(agbno
, level
, agno
, suspect
, scan_refcbt
, 0,
1423 refcount_avoid_check();
1428 * The following helpers are to help process and validate individual on-disk
1429 * inode btree records. We have two possible inode btrees with slightly
1430 * different semantics. Many of the validations and actions are equivalent, such
1431 * as record alignment constraints, etc. Other validations differ, such as the
1432 * fact that the inode chunk block allocation state is set by the content of the
1433 * core inobt and verified by the content of the finobt.
1435 * The following structures are used to facilitate common validation routines
1436 * where the only difference between validation of the inobt or finobt might be
1437 * the error messages that results in the event of failure.
1444 static const char *inobt_names
[] = {
1450 verify_single_ino_chunk_align(
1451 xfs_agnumber_t agno
,
1452 enum inobt_type type
,
1453 struct xfs_inobt_rec
*rp
,
1457 const char *inobt_name
= inobt_names
[type
];
1460 xfs_agblock_t agbno
;
1464 ino
= be32_to_cpu(rp
->ir_startino
);
1465 off
= XFS_AGINO_TO_OFFSET(mp
, ino
);
1466 agbno
= XFS_AGINO_TO_AGBNO(mp
, ino
);
1467 lino
= XFS_AGINO_TO_INO(mp
, agno
, ino
);
1470 * on multi-block block chunks, all chunks start at the beginning of the
1471 * block. with multi-chunk blocks, all chunks must start on 64-inode
1472 * boundaries since each block can hold N complete chunks. if fs has
1473 * aligned inodes, all chunks must start at a fs_ino_alignment*N'th
1474 * agbno. skip recs with badly aligned starting inodes.
1477 (inodes_per_block
<= XFS_INODES_PER_CHUNK
&& off
!= 0) ||
1478 (inodes_per_block
> XFS_INODES_PER_CHUNK
&&
1479 off
% XFS_INODES_PER_CHUNK
!= 0) ||
1480 (fs_aligned_inodes
&& fs_ino_alignment
&&
1481 agbno
% fs_ino_alignment
!= 0)) {
1483 _("badly aligned %s rec (starting inode = %" PRIu64
")\n"),
1489 * verify numeric validity of inode chunk first before inserting into a
1490 * tree. don't have to worry about the overflow case because the
1491 * starting ino number of a chunk can only get within 255 inodes of max
1492 * (NULLAGINO). if it gets closer, the agino number will be illegal as
1493 * the agbno will be too large.
1495 if (verify_aginum(mp
, agno
, ino
)) {
1497 _("bad starting inode # (%" PRIu64
" (0x%x 0x%x)) in %s rec, skipping rec\n"),
1498 lino
, agno
, ino
, inobt_name
);
1503 if (verify_aginum(mp
, agno
,
1504 ino
+ XFS_INODES_PER_CHUNK
- 1)) {
1506 _("bad ending inode # (%" PRIu64
" (0x%x 0x%zx)) in %s rec, skipping rec\n"),
1507 lino
+ XFS_INODES_PER_CHUNK
- 1,
1509 ino
+ XFS_INODES_PER_CHUNK
- 1,
1519 * Process the state of individual inodes in an on-disk inobt record and import
1520 * into the appropriate in-core tree based on whether the on-disk tree is
1521 * suspect. Return the total and free inode counts based on the record free and
1525 import_single_ino_chunk(
1526 xfs_agnumber_t agno
,
1527 enum inobt_type type
,
1528 struct xfs_inobt_rec
*rp
,
1533 struct ino_tree_node
*ino_rec
= NULL
;
1534 const char *inobt_name
= inobt_names
[type
];
1540 ino
= be32_to_cpu(rp
->ir_startino
);
1543 if (XFS_INOBT_IS_FREE_DISK(rp
, 0))
1544 ino_rec
= set_inode_free_alloc(mp
, agno
, ino
);
1546 ino_rec
= set_inode_used_alloc(mp
, agno
, ino
);
1547 for (j
= 1; j
< XFS_INODES_PER_CHUNK
; j
++) {
1548 if (XFS_INOBT_IS_FREE_DISK(rp
, j
))
1549 set_inode_free(ino_rec
, j
);
1551 set_inode_used(ino_rec
, j
);
1554 for (j
= 0; j
< XFS_INODES_PER_CHUNK
; j
++) {
1555 if (XFS_INOBT_IS_FREE_DISK(rp
, j
))
1556 add_aginode_uncertain(mp
, agno
, ino
+ j
, 1);
1558 add_aginode_uncertain(mp
, agno
, ino
+ j
, 0);
1563 * Mark sparse inodes as such in the in-core tree. Verify that sparse
1564 * inodes are free and that freecount is consistent with the free mask.
1566 nfree
= ninodes
= 0;
1567 for (j
= 0; j
< XFS_INODES_PER_CHUNK
; j
++) {
1568 if (ino_issparse(rp
, j
)) {
1569 if (!suspect
&& !XFS_INOBT_IS_FREE_DISK(rp
, j
)) {
1571 _("ir_holemask/ir_free mismatch, %s chunk %d/%u, holemask 0x%x free 0x%llx\n"),
1572 inobt_name
, agno
, ino
,
1573 be16_to_cpu(rp
->ir_u
.sp
.ir_holemask
),
1574 (unsigned long long)be64_to_cpu(rp
->ir_free
));
1577 if (!suspect
&& ino_rec
)
1578 set_inode_sparse(ino_rec
, j
);
1580 /* count fields track non-sparse inos */
1581 if (XFS_INOBT_IS_FREE_DISK(rp
, j
))
1588 *p_ninodes
= ninodes
;
1594 scan_single_ino_chunk(
1595 xfs_agnumber_t agno
,
1596 xfs_inobt_rec_t
*rp
,
1601 xfs_agblock_t agbno
;
1607 ino_tree_node_t
*first_rec
, *last_rec
;
1611 ino
= be32_to_cpu(rp
->ir_startino
);
1612 off
= XFS_AGINO_TO_OFFSET(mp
, ino
);
1613 agbno
= XFS_AGINO_TO_AGBNO(mp
, ino
);
1614 lino
= XFS_AGINO_TO_INO(mp
, agno
, ino
);
1615 freecount
= inorec_get_freecount(mp
, rp
);
1618 * Verify record alignment, start/end inode numbers, etc.
1620 suspect
= verify_single_ino_chunk_align(agno
, INOBT
, rp
, suspect
,
1626 * set state of each block containing inodes
1628 if (off
== 0 && !suspect
) {
1630 j
< XFS_INODES_PER_CHUNK
;
1631 j
+= mp
->m_sb
.sb_inopblock
) {
1633 /* inodes in sparse chunks don't use blocks */
1634 if (ino_issparse(rp
, j
))
1637 agbno
= XFS_AGINO_TO_AGBNO(mp
, ino
+ j
);
1638 state
= get_bmap(agno
, agbno
);
1643 case XR_E_INO1
: /* seen by rmap */
1644 set_bmap(agno
, agbno
, XR_E_INO
);
1647 case XR_E_INUSE_FS1
:
1649 ino
+ j
>= first_prealloc_ino
&&
1650 ino
+ j
< last_prealloc_ino
) {
1651 set_bmap(agno
, agbno
, XR_E_INO
);
1656 /* XXX - maybe should mark block a duplicate */
1658 _("inode chunk claims used block, inobt block - agno %d, bno %d, inopb %d\n"),
1659 agno
, agbno
, mp
->m_sb
.sb_inopblock
);
1666 * ensure only one avl entry per chunk
1668 find_inode_rec_range(mp
, agno
, ino
, ino
+ XFS_INODES_PER_CHUNK
,
1669 &first_rec
, &last_rec
);
1670 if (first_rec
!= NULL
) {
1672 * this chunk overlaps with one (or more)
1673 * already in the tree
1676 _("inode rec for ino %" PRIu64
" (%d/%d) overlaps existing rec (start %d/%d)\n"),
1677 lino
, agno
, ino
, agno
, first_rec
->ino_startnum
);
1681 * if the 2 chunks start at the same place,
1682 * then we don't have to put this one
1683 * in the uncertain list. go to the next one.
1685 if (first_rec
->ino_startnum
== ino
)
1690 * Import the state of individual inodes into the appropriate in-core
1691 * trees, mark them free or used, and get the resulting total and free
1694 nfree
= ninodes
= 0;
1695 suspect
= import_single_ino_chunk(agno
, INOBT
, rp
, suspect
, &nfree
,
1698 if (nfree
!= freecount
) {
1700 _("ir_freecount/free mismatch, inode chunk %d/%u, freecount %d nfree %d\n"),
1701 agno
, ino
, freecount
, nfree
);
1704 /* verify sparse record formats have a valid inode count */
1705 if (xfs_sb_version_hassparseinodes(&mp
->m_sb
) &&
1706 ninodes
!= rp
->ir_u
.sp
.ir_count
) {
1708 _("invalid inode count, inode chunk %d/%u, count %d ninodes %d\n"),
1709 agno
, ino
, rp
->ir_u
.sp
.ir_count
, ninodes
);
1716 scan_single_finobt_chunk(
1717 xfs_agnumber_t agno
,
1718 xfs_inobt_rec_t
*rp
,
1723 xfs_agblock_t agbno
;
1729 ino_tree_node_t
*first_rec
, *last_rec
;
1733 ino
= be32_to_cpu(rp
->ir_startino
);
1734 off
= XFS_AGINO_TO_OFFSET(mp
, ino
);
1735 agbno
= XFS_AGINO_TO_AGBNO(mp
, ino
);
1736 lino
= XFS_AGINO_TO_INO(mp
, agno
, ino
);
1737 freecount
= inorec_get_freecount(mp
, rp
);
1740 * Verify record alignment, start/end inode numbers, etc.
1742 suspect
= verify_single_ino_chunk_align(agno
, FINOBT
, rp
, suspect
,
1748 * cross check state of each block containing inodes referenced by the
1749 * finobt against what we have already scanned from the alloc inobt.
1751 if (off
== 0 && !suspect
) {
1753 j
< XFS_INODES_PER_CHUNK
;
1754 j
+= mp
->m_sb
.sb_inopblock
) {
1755 agbno
= XFS_AGINO_TO_AGBNO(mp
, ino
+ j
);
1756 state
= get_bmap(agno
, agbno
);
1758 /* sparse inodes should not refer to inode blocks */
1759 if (ino_issparse(rp
, j
)) {
1760 if (state
== XR_E_INO
) {
1762 _("sparse inode chunk claims inode block, finobt block - agno %d, bno %d, inopb %d\n"),
1763 agno
, agbno
, mp
->m_sb
.sb_inopblock
);
1772 case XR_E_INO1
: /* seen by rmap */
1773 set_bmap(agno
, agbno
, XR_E_INO
);
1777 _("inode chunk claims untracked block, finobt block - agno %d, bno %d, inopb %d\n"),
1778 agno
, agbno
, mp
->m_sb
.sb_inopblock
);
1780 set_bmap(agno
, agbno
, XR_E_INO
);
1784 case XR_E_INUSE_FS1
:
1786 ino
+ j
>= first_prealloc_ino
&&
1787 ino
+ j
< last_prealloc_ino
) {
1789 _("inode chunk claims untracked block, finobt block - agno %d, bno %d, inopb %d\n"),
1790 agno
, agbno
, mp
->m_sb
.sb_inopblock
);
1792 set_bmap(agno
, agbno
, XR_E_INO
);
1799 _("inode chunk claims used block, finobt block - agno %d, bno %d, inopb %d\n"),
1800 agno
, agbno
, mp
->m_sb
.sb_inopblock
);
1807 * ensure we have an incore entry for each chunk
1809 find_inode_rec_range(mp
, agno
, ino
, ino
+ XFS_INODES_PER_CHUNK
,
1810 &first_rec
, &last_rec
);
1817 * verify consistency between finobt record and incore state
1819 if (first_rec
->ino_startnum
!= ino
) {
1821 _("finobt rec for ino %" PRIu64
" (%d/%u) does not match existing rec (%d/%d)\n"),
1822 lino
, agno
, ino
, agno
, first_rec
->ino_startnum
);
1826 nfree
= ninodes
= 0;
1827 for (j
= 0; j
< XFS_INODES_PER_CHUNK
; j
++) {
1828 int isfree
= XFS_INOBT_IS_FREE_DISK(rp
, j
);
1829 int issparse
= ino_issparse(rp
, j
);
1833 if (isfree
&& !issparse
)
1837 * inode allocation state should be consistent between
1838 * the inobt and finobt
1841 isfree
!= is_inode_free(first_rec
, j
))
1845 issparse
!= is_inode_sparse(first_rec
, j
))
1849 goto check_freecount
;
1853 * The finobt contains a record that the previous inobt scan never
1854 * found. Warn about it and import the inodes into the appropriate
1857 * Note that this should do the right thing if the previous inobt scan
1858 * had added these inodes to the uncertain tree. If the finobt is not
1859 * suspect, these inodes should supercede the uncertain ones. Otherwise,
1860 * the uncertain tree helpers handle the case where uncertain inodes
1863 do_warn(_("undiscovered finobt record, ino %" PRIu64
" (%d/%u)\n"),
1866 nfree
= ninodes
= 0;
1867 suspect
= import_single_ino_chunk(agno
, FINOBT
, rp
, suspect
, &nfree
,
1873 * Verify that the record freecount matches the actual number of free
1874 * inodes counted in the record. Don't increment 'suspect' here, since
1875 * we have already verified the allocation state of the individual
1876 * inodes against the in-core state. This will have already incremented
1877 * 'suspect' if something is wrong. If suspect hasn't been set at this
1878 * point, these warnings mean that we have a simple freecount
1879 * inconsistency or a stray finobt record (as opposed to a broader tree
1880 * corruption). Issue a warning and continue the scan. The final btree
1881 * reconstruction will correct this naturally.
1883 if (nfree
!= freecount
) {
1885 _("finobt ir_freecount/free mismatch, inode chunk %d/%u, freecount %d nfree %d\n"),
1886 agno
, ino
, freecount
, nfree
);
1891 _("finobt record with no free inodes, inode chunk %d/%u\n"), agno
, ino
);
1894 /* verify sparse record formats have a valid inode count */
1895 if (xfs_sb_version_hassparseinodes(&mp
->m_sb
) &&
1896 ninodes
!= rp
->ir_u
.sp
.ir_count
) {
1898 _("invalid inode count, inode chunk %d/%u, count %d ninodes %d\n"),
1899 agno
, ino
, rp
->ir_u
.sp
.ir_count
, ninodes
);
1906 * this one walks the inode btrees sucking the info there into
1907 * the incore avl tree. We try and rescue corrupted btree records
1908 * to minimize our chances of losing inodes. Inode info from potentially
1909 * corrupt sources could be bogus so rather than put the info straight
1910 * into the tree, instead we put it on a list and try and verify the
1911 * info in the next phase by examining what's on disk. At that point,
1912 * we'll be able to figure out what's what and stick the corrected info
1913 * into the tree. We do bail out at some point and give up on a subtree
1914 * so as to avoid walking randomly all over the ag.
1916 * Note that it's also ok if the free/inuse info wrong, we can correct
1917 * that when we examine the on-disk inode. The important thing is to
1918 * get the start and alignment of the inode chunks right. Those chunks
1919 * that we aren't sure about go into the uncertain list.
1923 struct xfs_btree_block
*block
,
1926 xfs_agnumber_t agno
,
1931 const struct xfs_buf_ops
*ops
)
1933 struct aghdr_cnts
*agcnts
= priv
;
1937 xfs_inobt_ptr_t
*pp
;
1938 xfs_inobt_rec_t
*rp
;
1944 if (be32_to_cpu(block
->bb_magic
) != magic
) {
1945 do_warn(_("bad magic # %#x in inobt block %d/%d\n"),
1946 be32_to_cpu(block
->bb_magic
), agno
, bno
);
1952 if (be16_to_cpu(block
->bb_level
) != level
) {
1953 do_warn(_("expected level %d got %d in inobt block %d/%d\n"),
1954 level
, be16_to_cpu(block
->bb_level
), agno
, bno
);
1962 * check for btree blocks multiply claimed, any unknown/free state
1963 * is ok in the bitmap block.
1965 state
= get_bmap(agno
, bno
);
1967 case XR_E_FS_MAP1
: /* already been seen by an rmap scan */
1971 set_bmap(agno
, bno
, XR_E_FS_MAP
);
1974 set_bmap(agno
, bno
, XR_E_MULT
);
1976 _("inode btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
1977 state
, agno
, bno
, suspect
);
1980 numrecs
= be16_to_cpu(block
->bb_numrecs
);
1983 * leaf record in btree
1986 /* check for trashed btree block */
1988 if (numrecs
> mp
->m_inobt_mxr
[0]) {
1989 numrecs
= mp
->m_inobt_mxr
[0];
1992 if (isroot
== 0 && numrecs
< mp
->m_inobt_mnr
[0]) {
1993 numrecs
= mp
->m_inobt_mnr
[0];
1999 do_warn(_("dubious inode btree block header %d/%d\n"),
2004 rp
= XFS_INOBT_REC_ADDR(mp
, block
, 1);
2007 * step through the records, each record points to
2008 * a chunk of inodes. The start of inode chunks should
2009 * be block-aligned. Each inode btree rec should point
2010 * to the start of a block of inodes or the start of a group
2011 * of INODES_PER_CHUNK (64) inodes. off is the offset into
2012 * the block. skip processing of bogus records.
2014 for (i
= 0; i
< numrecs
; i
++) {
2015 freecount
= inorec_get_freecount(mp
, &rp
[i
]);
2017 if (magic
== XFS_IBT_MAGIC
||
2018 magic
== XFS_IBT_CRC_MAGIC
) {
2019 int icount
= XFS_INODES_PER_CHUNK
;
2022 * ir_count holds the inode count for all
2023 * records on fs' with sparse inode support
2025 if (xfs_sb_version_hassparseinodes(&mp
->m_sb
))
2026 icount
= rp
[i
].ir_u
.sp
.ir_count
;
2028 agcnts
->agicount
+= icount
;
2029 agcnts
->agifreecount
+= freecount
;
2030 agcnts
->ifreecount
+= freecount
;
2032 suspect
= scan_single_ino_chunk(agno
, &rp
[i
],
2036 * the finobt tracks records with free inodes,
2037 * so only the free inode count is expected to be
2038 * consistent with the agi
2040 agcnts
->fibtfreecount
+= freecount
;
2042 suspect
= scan_single_finobt_chunk(agno
, &rp
[i
],
2054 * interior record, continue on
2056 if (numrecs
> mp
->m_inobt_mxr
[1]) {
2057 numrecs
= mp
->m_inobt_mxr
[1];
2060 if (isroot
== 0 && numrecs
< mp
->m_inobt_mnr
[1]) {
2061 numrecs
= mp
->m_inobt_mnr
[1];
2065 pp
= XFS_INOBT_PTR_ADDR(mp
, block
, 1, mp
->m_inobt_mxr
[1]);
2068 * don't pass bogus tree flag down further if this block
2069 * looked ok. bail out if two levels in a row look bad.
2072 if (suspect
&& !hdr_errors
)
2082 for (i
= 0; i
< numrecs
; i
++) {
2083 if (be32_to_cpu(pp
[i
]) != 0 && verify_agbno(mp
, agno
,
2084 be32_to_cpu(pp
[i
])))
2085 scan_sbtree(be32_to_cpu(pp
[i
]), level
, agno
,
2086 suspect
, scan_inobt
, 0, magic
, priv
,
2093 xfs_agnumber_t agno
;
2098 struct xfs_mount
*mp
,
2102 struct agfl_state
*as
= priv
;
2104 if (verify_agbno(mp
, as
->agno
, bno
))
2105 set_bmap(as
->agno
, bno
, XR_E_FREE
);
2107 do_warn(_("bad agbno %u in agfl, agno %d\n"),
2116 struct aghdr_cnts
*agcnts
)
2119 xfs_agnumber_t agno
;
2120 struct agfl_state state
;
2122 agno
= be32_to_cpu(agf
->agf_seqno
);
2124 if (XFS_SB_BLOCK(mp
) != XFS_AGFL_BLOCK(mp
) &&
2125 XFS_AGF_BLOCK(mp
) != XFS_AGFL_BLOCK(mp
) &&
2126 XFS_AGI_BLOCK(mp
) != XFS_AGFL_BLOCK(mp
))
2127 set_bmap(agno
, XFS_AGFL_BLOCK(mp
), XR_E_INUSE_FS
);
2129 if (be32_to_cpu(agf
->agf_flcount
) == 0)
2132 agflbuf
= libxfs_readbuf(mp
->m_dev
,
2133 XFS_AG_DADDR(mp
, agno
, XFS_AGFL_DADDR(mp
)),
2134 XFS_FSS_TO_BB(mp
, 1), 0, &xfs_agfl_buf_ops
);
2136 do_abort(_("can't read agfl block for ag %d\n"), agno
);
2139 if (agflbuf
->b_error
== -EFSBADCRC
)
2140 do_warn(_("agfl has bad CRC for ag %d\n"), agno
);
2143 /* agf values not fixed in verify_set_agf, so recheck */
2144 if (be32_to_cpu(agf
->agf_flfirst
) >= libxfs_agfl_size(mp
) ||
2145 be32_to_cpu(agf
->agf_fllast
) >= libxfs_agfl_size(mp
)) {
2146 do_warn(_("agf %d freelist blocks bad, skipping "
2147 "freelist scan\n"), agno
);
2154 libxfs_agfl_walk(mp
, agf
, agflbuf
, scan_agfl
, &state
);
2155 if (state
.count
!= be32_to_cpu(agf
->agf_flcount
)) {
2156 do_warn(_("freeblk count %d != flcount %d in ag %d\n"),
2157 state
.count
, be32_to_cpu(agf
->agf_flcount
),
2161 agcnts
->fdblocks
+= state
.count
;
2163 libxfs_putbuf(agflbuf
);
2168 struct xfs_agf
*agf
,
2169 xfs_agnumber_t agno
,
2170 struct aghdr_cnts
*agcnts
)
2175 bno
= be32_to_cpu(agf
->agf_roots
[XFS_BTNUM_BNO
]);
2176 if (bno
!= 0 && verify_agbno(mp
, agno
, bno
)) {
2177 magic
= xfs_sb_version_hascrc(&mp
->m_sb
) ? XFS_ABTB_CRC_MAGIC
2179 scan_sbtree(bno
, be32_to_cpu(agf
->agf_levels
[XFS_BTNUM_BNO
]),
2180 agno
, 0, scan_allocbt
, 1, magic
, agcnts
,
2181 &xfs_allocbt_buf_ops
);
2183 do_warn(_("bad agbno %u for btbno root, agno %d\n"),
2187 bno
= be32_to_cpu(agf
->agf_roots
[XFS_BTNUM_CNT
]);
2188 if (bno
!= 0 && verify_agbno(mp
, agno
, bno
)) {
2189 magic
= xfs_sb_version_hascrc(&mp
->m_sb
) ? XFS_ABTC_CRC_MAGIC
2191 scan_sbtree(bno
, be32_to_cpu(agf
->agf_levels
[XFS_BTNUM_CNT
]),
2192 agno
, 0, scan_allocbt
, 1, magic
, agcnts
,
2193 &xfs_allocbt_buf_ops
);
2195 do_warn(_("bad agbno %u for btbcnt root, agno %d\n"),
2199 if (xfs_sb_version_hasrmapbt(&mp
->m_sb
)) {
2200 struct rmap_priv priv
;
2202 memset(&priv
.high_key
, 0xFF, sizeof(priv
.high_key
));
2203 priv
.high_key
.rm_blockcount
= 0;
2204 priv
.agcnts
= agcnts
;
2205 priv
.last_rec
.rm_owner
= XFS_RMAP_OWN_UNKNOWN
;
2207 bno
= be32_to_cpu(agf
->agf_roots
[XFS_BTNUM_RMAP
]);
2208 if (bno
!= 0 && verify_agbno(mp
, agno
, bno
)) {
2210 be32_to_cpu(agf
->agf_levels
[XFS_BTNUM_RMAP
]),
2211 agno
, 0, scan_rmapbt
, 1, XFS_RMAP_CRC_MAGIC
,
2212 &priv
, &xfs_rmapbt_buf_ops
);
2213 if (be32_to_cpu(agf
->agf_rmap_blocks
) != priv
.nr_blocks
)
2214 do_warn(_("bad rmapbt block count %u, saw %u\n"),
2216 be32_to_cpu(agf
->agf_rmap_blocks
));
2218 do_warn(_("bad agbno %u for rmapbt root, agno %d\n"),
2224 if (xfs_sb_version_hasreflink(&mp
->m_sb
)) {
2225 bno
= be32_to_cpu(agf
->agf_refcount_root
);
2226 if (bno
!= 0 && verify_agbno(mp
, agno
, bno
)) {
2227 struct refc_priv priv
;
2229 memset(&priv
, 0, sizeof(priv
));
2231 be32_to_cpu(agf
->agf_refcount_level
),
2232 agno
, 0, scan_refcbt
, 1, XFS_REFC_CRC_MAGIC
,
2233 &priv
, &xfs_refcountbt_buf_ops
);
2234 if (be32_to_cpu(agf
->agf_refcount_blocks
) != priv
.nr_blocks
)
2235 do_warn(_("bad refcountbt block count %u, saw %u\n"),
2237 be32_to_cpu(agf
->agf_refcount_blocks
));
2239 do_warn(_("bad agbno %u for refcntbt root, agno %d\n"),
2241 refcount_avoid_check();
2245 if (be32_to_cpu(agf
->agf_freeblks
) != agcnts
->agffreeblks
) {
2246 do_warn(_("agf_freeblks %u, counted %u in ag %u\n"),
2247 be32_to_cpu(agf
->agf_freeblks
), agcnts
->agffreeblks
, agno
);
2250 if (be32_to_cpu(agf
->agf_longest
) != agcnts
->agflongest
) {
2251 do_warn(_("agf_longest %u, counted %u in ag %u\n"),
2252 be32_to_cpu(agf
->agf_longest
), agcnts
->agflongest
, agno
);
2255 if (xfs_sb_version_haslazysbcount(&mp
->m_sb
) &&
2256 be32_to_cpu(agf
->agf_btreeblks
) != agcnts
->agfbtreeblks
) {
2257 do_warn(_("agf_btreeblks %u, counted %" PRIu64
" in ag %u\n"),
2258 be32_to_cpu(agf
->agf_btreeblks
), agcnts
->agfbtreeblks
, agno
);
2265 struct xfs_agi
*agi
,
2266 xfs_agnumber_t agno
,
2267 struct aghdr_cnts
*agcnts
)
2273 bno
= be32_to_cpu(agi
->agi_root
);
2274 if (bno
!= 0 && verify_agbno(mp
, agno
, bno
)) {
2275 magic
= xfs_sb_version_hascrc(&mp
->m_sb
) ? XFS_IBT_CRC_MAGIC
2277 scan_sbtree(bno
, be32_to_cpu(agi
->agi_level
),
2278 agno
, 0, scan_inobt
, 1, magic
, agcnts
,
2279 &xfs_inobt_buf_ops
);
2281 do_warn(_("bad agbno %u for inobt root, agno %d\n"),
2282 be32_to_cpu(agi
->agi_root
), agno
);
2285 if (xfs_sb_version_hasfinobt(&mp
->m_sb
)) {
2286 bno
= be32_to_cpu(agi
->agi_free_root
);
2287 if (bno
!= 0 && verify_agbno(mp
, agno
, bno
)) {
2288 magic
= xfs_sb_version_hascrc(&mp
->m_sb
) ?
2289 XFS_FIBT_CRC_MAGIC
: XFS_FIBT_MAGIC
;
2290 scan_sbtree(bno
, be32_to_cpu(agi
->agi_free_level
),
2291 agno
, 0, scan_inobt
, 1, magic
, agcnts
,
2292 &xfs_inobt_buf_ops
);
2294 do_warn(_("bad agbno %u for finobt root, agno %d\n"),
2295 be32_to_cpu(agi
->agi_free_root
), agno
);
2299 if (be32_to_cpu(agi
->agi_count
) != agcnts
->agicount
) {
2300 do_warn(_("agi_count %u, counted %u in ag %u\n"),
2301 be32_to_cpu(agi
->agi_count
), agcnts
->agicount
, agno
);
2304 if (be32_to_cpu(agi
->agi_freecount
) != agcnts
->agifreecount
) {
2305 do_warn(_("agi_freecount %u, counted %u in ag %u\n"),
2306 be32_to_cpu(agi
->agi_freecount
), agcnts
->agifreecount
, agno
);
2309 if (xfs_sb_version_hasfinobt(&mp
->m_sb
) &&
2310 be32_to_cpu(agi
->agi_freecount
) != agcnts
->fibtfreecount
) {
2311 do_warn(_("agi_freecount %u, counted %u in ag %u finobt\n"),
2312 be32_to_cpu(agi
->agi_freecount
), agcnts
->fibtfreecount
,
2316 for (i
= 0; i
< XFS_AGI_UNLINKED_BUCKETS
; i
++) {
2317 xfs_agino_t agino
= be32_to_cpu(agi
->agi_unlinked
[i
]);
2319 if (agino
!= NULLAGINO
) {
2321 _("agi unlinked bucket %d is %u in ag %u (inode=%" PRIu64
")\n"),
2323 XFS_AGINO_TO_INO(mp
, agno
, agino
));
2329 * Scan an AG for obvious corruption.
2333 struct workqueue
*wq
,
2334 xfs_agnumber_t agno
,
2337 struct aghdr_cnts
*agcnts
= arg
;
2338 struct xfs_agf
*agf
;
2339 struct xfs_buf
*agfbuf
= NULL
;
2341 struct xfs_agi
*agi
;
2342 struct xfs_buf
*agibuf
= NULL
;
2344 struct xfs_sb
*sb
= NULL
;
2345 struct xfs_buf
*sbbuf
= NULL
;
2348 char *objname
= NULL
;
2350 sb
= (struct xfs_sb
*)calloc(BBTOB(XFS_FSS_TO_BB(mp
, 1)), 1);
2352 do_error(_("can't allocate memory for superblock\n"));
2356 sbbuf
= libxfs_readbuf(mp
->m_dev
, XFS_AG_DADDR(mp
, agno
, XFS_SB_DADDR
),
2357 XFS_FSS_TO_BB(mp
, 1), 0, &xfs_sb_buf_ops
);
2359 objname
= _("root superblock");
2362 libxfs_sb_from_disk(sb
, XFS_BUF_TO_SBP(sbbuf
));
2364 agfbuf
= libxfs_readbuf(mp
->m_dev
,
2365 XFS_AG_DADDR(mp
, agno
, XFS_AGF_DADDR(mp
)),
2366 XFS_FSS_TO_BB(mp
, 1), 0, &xfs_agf_buf_ops
);
2368 objname
= _("agf block");
2369 goto out_free_sbbuf
;
2371 agf
= XFS_BUF_TO_AGF(agfbuf
);
2373 agibuf
= libxfs_readbuf(mp
->m_dev
,
2374 XFS_AG_DADDR(mp
, agno
, XFS_AGI_DADDR(mp
)),
2375 XFS_FSS_TO_BB(mp
, 1), 0, &xfs_agi_buf_ops
);
2377 objname
= _("agi block");
2378 goto out_free_agfbuf
;
2380 agi
= XFS_BUF_TO_AGI(agibuf
);
2382 /* fix up bad ag headers */
2384 status
= verify_set_agheader(mp
, sbbuf
, sb
, agf
, agi
, agno
);
2386 if (status
& XR_AG_SB_SEC
) {
2390 * clear bad sector bit because we don't want
2391 * to skip further processing. we just want to
2392 * ensure that we write out the modified sb buffer.
2394 status
&= ~XR_AG_SB_SEC
;
2396 if (status
& XR_AG_SB
) {
2398 do_warn(_("reset bad sb for ag %d\n"), agno
);
2401 do_warn(_("would reset bad sb for ag %d\n"), agno
);
2404 if (status
& XR_AG_AGF
) {
2406 do_warn(_("reset bad agf for ag %d\n"), agno
);
2409 do_warn(_("would reset bad agf for ag %d\n"), agno
);
2412 if (status
& XR_AG_AGI
) {
2414 do_warn(_("reset bad agi for ag %d\n"), agno
);
2417 do_warn(_("would reset bad agi for ag %d\n"), agno
);
2421 if (status
&& no_modify
) {
2422 do_warn(_("bad uncorrected agheader %d, skipping ag...\n"),
2424 goto out_free_agibuf
;
2427 scan_freelist(agf
, agcnts
);
2429 validate_agf(agf
, agno
, agcnts
);
2430 validate_agi(agi
, agno
, agcnts
);
2432 ASSERT(agi_dirty
== 0 || (agi_dirty
&& !no_modify
));
2433 ASSERT(agf_dirty
== 0 || (agf_dirty
&& !no_modify
));
2434 ASSERT(sb_dirty
== 0 || (sb_dirty
&& !no_modify
));
2437 * Only pay attention to CRC/verifier errors if we can correct them.
2438 * Note that we can get uncorrected EFSCORRUPTED errors here because
2439 * the verifier will flag on out of range values that we can't correct
2440 * until phase 5 when we have all the information necessary to rebuild
2441 * the freespace/inode btrees. We can correct bad CRC errors
2442 * immediately, though.
2445 agi_dirty
+= (agibuf
->b_error
== -EFSBADCRC
);
2446 agf_dirty
+= (agfbuf
->b_error
== -EFSBADCRC
);
2447 sb_dirty
+= (sbbuf
->b_error
== -EFSBADCRC
);
2450 if (agi_dirty
&& !no_modify
)
2451 libxfs_writebuf(agibuf
, 0);
2453 libxfs_putbuf(agibuf
);
2455 if (agf_dirty
&& !no_modify
)
2456 libxfs_writebuf(agfbuf
, 0);
2458 libxfs_putbuf(agfbuf
);
2460 if (sb_dirty
&& !no_modify
) {
2462 memcpy(&mp
->m_sb
, sb
, sizeof(xfs_sb_t
));
2463 libxfs_sb_to_disk(XFS_BUF_TO_SBP(sbbuf
), sb
);
2464 libxfs_writebuf(sbbuf
, 0);
2466 libxfs_putbuf(sbbuf
);
2468 PROG_RPT_INC(prog_rpt_done
[agno
], 1);
2470 #ifdef XR_INODE_TRACE
2471 print_inode_list(i
);
2476 libxfs_putbuf(agibuf
);
2478 libxfs_putbuf(agfbuf
);
2480 libxfs_putbuf(sbbuf
);
2485 do_error(_("can't get %s for ag %d\n"), objname
, agno
);
2490 struct xfs_mount
*mp
,
2493 struct aghdr_cnts
*agcnts
;
2494 uint64_t fdblocks
= 0;
2495 uint64_t icount
= 0;
2496 uint64_t ifreecount
= 0;
2497 uint64_t usedblocks
= 0;
2499 struct workqueue wq
;
2501 agcnts
= malloc(mp
->m_sb
.sb_agcount
* sizeof(*agcnts
));
2503 do_abort(_("no memory for ag header counts\n"));
2506 memset(agcnts
, 0, mp
->m_sb
.sb_agcount
* sizeof(*agcnts
));
2508 create_work_queue(&wq
, mp
, scan_threads
);
2510 for (i
= 0; i
< mp
->m_sb
.sb_agcount
; i
++)
2511 queue_work(&wq
, scan_ag
, i
, &agcnts
[i
]);
2513 destroy_work_queue(&wq
);
2515 /* tally up the counts */
2516 for (i
= 0; i
< mp
->m_sb
.sb_agcount
; i
++) {
2517 fdblocks
+= agcnts
[i
].fdblocks
;
2518 icount
+= agcnts
[i
].agicount
;
2519 ifreecount
+= agcnts
[i
].ifreecount
;
2520 usedblocks
+= agcnts
[i
].usedblocks
;
2526 * Validate that our manual counts match the superblock.
2528 if (mp
->m_sb
.sb_icount
!= icount
) {
2529 do_warn(_("sb_icount %" PRIu64
", counted %" PRIu64
"\n"),
2530 mp
->m_sb
.sb_icount
, icount
);
2533 if (mp
->m_sb
.sb_ifree
!= ifreecount
) {
2534 do_warn(_("sb_ifree %" PRIu64
", counted %" PRIu64
"\n"),
2535 mp
->m_sb
.sb_ifree
, ifreecount
);
2538 if (mp
->m_sb
.sb_fdblocks
!= fdblocks
) {
2539 do_warn(_("sb_fdblocks %" PRIu64
", counted %" PRIu64
"\n"),
2540 mp
->m_sb
.sb_fdblocks
, fdblocks
);
2544 usedblocks
!= mp
->m_sb
.sb_dblocks
- fdblocks
) {
2545 do_warn(_("used blocks %" PRIu64
", counted %" PRIu64
"\n"),
2546 mp
->m_sb
.sb_dblocks
- fdblocks
, usedblocks
);