2 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "err_protos.h"
35 static xfs_mount_t
*mp
= NULL
;
38 * Variables to validate AG header values against the manual count
39 * from the btree traversal.
43 xfs_extlen_t agffreeblks
;
44 xfs_extlen_t agflongest
;
45 uint64_t agfbtreeblks
;
47 uint32_t agifreecount
;
51 uint32_t fibtfreecount
;
55 set_mp(xfs_mount_t
*mpp
)
57 libxfs_bcache_purge();
67 void (*func
)(struct xfs_btree_block
*block
,
78 const struct xfs_buf_ops
*ops
)
82 bp
= libxfs_readbuf(mp
->m_dev
, XFS_AGB_TO_DADDR(mp
, agno
, root
),
83 XFS_FSB_TO_BB(mp
, 1), 0, ops
);
85 do_error(_("can't read btree block %d/%d\n"), agno
, root
);
88 if (bp
->b_error
== -EFSBADCRC
|| bp
->b_error
== -EFSCORRUPTED
) {
89 do_warn(_("btree block %d/%d is suspect, error %d\n"),
90 agno
, root
, bp
->b_error
);
94 (*func
)(XFS_BUF_TO_BLOCK(bp
), nlevels
- 1, root
, agno
, suspect
,
100 * returns 1 on bad news (inode needs to be cleared), 0 on good
106 int (*func
)(struct xfs_btree_block
*block
,
115 bmap_cursor_t
*bm_cursor
,
126 bmap_cursor_t
*bm_cursor
,
130 const struct xfs_buf_ops
*ops
)
137 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, root
),
138 XFS_FSB_TO_BB(mp
, 1), 0, ops
);
140 do_error(_("can't read btree block %d/%d\n"),
141 XFS_FSB_TO_AGNO(mp
, root
),
142 XFS_FSB_TO_AGBNO(mp
, root
));
147 * only check for bad CRC here - caller will determine if there
148 * is a corruption or not and whether it got corrected and so needs
149 * writing back. CRC errors always imply we need to write the block.
151 if (bp
->b_error
== -EFSBADCRC
) {
152 do_warn(_("btree block %d/%d is suspect, error %d\n"),
153 XFS_FSB_TO_AGNO(mp
, root
),
154 XFS_FSB_TO_AGBNO(mp
, root
), bp
->b_error
);
158 err
= (*func
)(XFS_BUF_TO_BLOCK(bp
), nlevels
- 1,
159 type
, whichfork
, root
, ino
, tot
, nex
, blkmapp
,
160 bm_cursor
, isroot
, check_dups
, &dirty
,
163 ASSERT(dirty
== 0 || (dirty
&& !no_modify
));
165 if ((dirty
|| badcrc
) && !no_modify
)
166 libxfs_writebuf(bp
, 0);
175 struct xfs_btree_block
*block
,
184 bmap_cursor_t
*bm_cursor
,
193 xfs_bmbt_key_t
*pkey
;
195 xfs_fileoff_t first_key
;
196 xfs_fileoff_t last_key
;
197 char *forkname
= get_forkname(whichfork
);
205 * unlike the ag freeblock btrees, if anything looks wrong
206 * in an inode bmap tree, just bail. it's possible that
207 * we'll miss a case where the to-be-toasted inode and
208 * another inode are claiming the same block but that's
211 if (be32_to_cpu(block
->bb_magic
) != magic
) {
213 _("bad magic # %#x in inode %" PRIu64
" (%s fork) bmbt block %" PRIu64
"\n"),
214 be32_to_cpu(block
->bb_magic
), ino
, forkname
, bno
);
217 if (be16_to_cpu(block
->bb_level
) != level
) {
219 _("expected level %d got %d in inode %" PRIu64
", (%s fork) bmbt block %" PRIu64
"\n"),
220 level
, be16_to_cpu(block
->bb_level
),
225 if (magic
== XFS_BMAP_CRC_MAGIC
) {
227 if (be64_to_cpu(block
->bb_u
.l
.bb_owner
) != ino
) {
229 _("expected owner inode %" PRIu64
", got %llu, bmbt block %" PRIu64
"\n"),
231 (unsigned long long)be64_to_cpu(block
->bb_u
.l
.bb_owner
),
235 /* verify block number */
236 if (be64_to_cpu(block
->bb_u
.l
.bb_blkno
) !=
237 XFS_FSB_TO_DADDR(mp
, bno
)) {
239 _("expected block %" PRIu64
", got %llu, bmbt block %" PRIu64
"\n"),
240 XFS_FSB_TO_DADDR(mp
, bno
),
241 (unsigned long long)be64_to_cpu(block
->bb_u
.l
.bb_blkno
),
246 if (platform_uuid_compare(&block
->bb_u
.l
.bb_uuid
,
247 &mp
->m_sb
.sb_meta_uuid
) != 0) {
249 _("wrong FS UUID, bmbt block %" PRIu64
"\n"),
255 if (check_dups
== 0) {
257 * check sibling pointers. if bad we have a conflict
258 * between the sibling pointers and the child pointers
259 * in the parent block. blow out the inode if that happens
261 if (bm_cursor
->level
[level
].fsbno
!= NULLFSBLOCK
) {
263 * this is not the first block on this level
264 * so the cursor for this level has recorded the
265 * values for this's block left-sibling.
267 if (bno
!= bm_cursor
->level
[level
].right_fsbno
) {
269 _("bad fwd (right) sibling pointer (saw %" PRIu64
" parent block says %" PRIu64
")\n"
270 "\tin inode %" PRIu64
" (%s fork) bmap btree block %" PRIu64
"\n"),
271 bm_cursor
->level
[level
].right_fsbno
,
273 bm_cursor
->level
[level
].fsbno
);
276 if (be64_to_cpu(block
->bb_u
.l
.bb_leftsib
) !=
277 bm_cursor
->level
[level
].fsbno
) {
279 _("bad back (left) sibling pointer (saw %llu parent block says %" PRIu64
")\n"
280 "\tin inode %" PRIu64
" (%s fork) bmap btree block %" PRIu64
"\n"),
282 be64_to_cpu(block
->bb_u
.l
.bb_leftsib
),
283 bm_cursor
->level
[level
].fsbno
,
289 * This is the first or only block on this level.
290 * Check that the left sibling pointer is NULL
292 if (be64_to_cpu(block
->bb_u
.l
.bb_leftsib
) != NULLFSBLOCK
) {
294 _("bad back (left) sibling pointer (saw %llu should be NULL (0))\n"
295 "\tin inode %" PRIu64
" (%s fork) bmap btree block %" PRIu64
"\n"),
297 be64_to_cpu(block
->bb_u
.l
.bb_leftsib
),
304 * update cursor block pointers to reflect this block
306 bm_cursor
->level
[level
].fsbno
= bno
;
307 bm_cursor
->level
[level
].left_fsbno
=
308 be64_to_cpu(block
->bb_u
.l
.bb_leftsib
);
309 bm_cursor
->level
[level
].right_fsbno
=
310 be64_to_cpu(block
->bb_u
.l
.bb_rightsib
);
312 agno
= XFS_FSB_TO_AGNO(mp
, bno
);
313 agbno
= XFS_FSB_TO_AGBNO(mp
, bno
);
315 pthread_mutex_lock(&ag_locks
[agno
].lock
);
316 state
= get_bmap(agno
, agbno
);
320 * block was claimed as in use data by the rmap
321 * btree, but has not been found in the data extent
322 * map for the inode. That means this bmbt block hasn't
323 * yet been claimed as in use, which means -it's ours-
328 set_bmap(agno
, agbno
, XR_E_INUSE
);
333 * we'll try and continue searching here since
334 * the block looks like it's been claimed by file
335 * to store user data, a directory to store directory
336 * data, or the space allocation btrees but since
337 * we made it here, the block probably
338 * contains btree data.
340 set_bmap(agno
, agbno
, XR_E_MULT
);
342 _("inode 0x%" PRIx64
"bmap block 0x%" PRIx64
" claimed, state is %d\n"),
347 set_bmap(agno
, agbno
, XR_E_MULT
);
349 _("inode 0x%" PRIx64
" bmap block 0x%" PRIx64
" claimed, state is %d\n"),
352 * if we made it to here, this is probably a bmap block
353 * that is being used by *another* file as a bmap block
354 * so the block will be valid. Both files should be
355 * trashed along with any other file that impinges on
356 * any blocks referenced by either file. So we
357 * continue searching down this btree to mark all
364 _("bad state %d, inode %" PRIu64
" bmap block 0x%" PRIx64
"\n"),
368 pthread_mutex_unlock(&ag_locks
[agno
].lock
);
371 * attribute fork for realtime files is in the regular
374 if (type
!= XR_INO_RTDATA
|| whichfork
!= XFS_DATA_FORK
) {
375 if (search_dup_extent(XFS_FSB_TO_AGNO(mp
, bno
),
376 XFS_FSB_TO_AGBNO(mp
, bno
),
377 XFS_FSB_TO_AGBNO(mp
, bno
) + 1))
380 if (search_rt_dup_extent(mp
, bno
))
385 numrecs
= be16_to_cpu(block
->bb_numrecs
);
387 /* Record BMBT blocks in the reverse-mapping data. */
388 if (check_dups
&& collect_rmaps
) {
389 agno
= XFS_FSB_TO_AGNO(mp
, bno
);
390 pthread_mutex_lock(&ag_locks
[agno
].lock
);
391 error
= rmap_add_bmbt_rec(mp
, ino
, whichfork
, bno
);
392 pthread_mutex_unlock(&ag_locks
[agno
].lock
);
395 _("couldn't add inode %"PRIu64
" bmbt block %"PRIu64
" reverse-mapping data."),
400 if (numrecs
> mp
->m_bmap_dmxr
[0] || (isroot
== 0 && numrecs
<
401 mp
->m_bmap_dmnr
[0])) {
403 _("inode %" PRIu64
" bad # of bmap records (%u, min - %u, max - %u)\n"),
404 ino
, numrecs
, mp
->m_bmap_dmnr
[0],
408 rp
= XFS_BMBT_REC_ADDR(mp
, block
, 1);
411 * XXX - if we were going to fix up the btree record,
412 * we'd do it right here. For now, if there's a problem,
413 * we'll bail out and presumably clear the inode.
415 if (check_dups
== 0) {
416 err
= process_bmbt_reclist(mp
, rp
, &numrecs
, type
, ino
,
417 tot
, blkmapp
, &first_key
,
418 &last_key
, whichfork
);
423 * check that key ordering is monotonically increasing.
424 * if the last_key value in the cursor is set to
425 * NULLFILEOFF, then we know this is the first block
426 * on the leaf level and we shouldn't check the
429 if (first_key
<= bm_cursor
->level
[level
].last_key
&&
430 bm_cursor
->level
[level
].last_key
!=
433 _("out-of-order bmap key (file offset) in inode %" PRIu64
", %s fork, fsbno %" PRIu64
"\n"),
438 * update cursor keys to reflect this block.
439 * don't have to check if last_key is > first_key
440 * since that gets checked by process_bmbt_reclist.
442 bm_cursor
->level
[level
].first_key
= first_key
;
443 bm_cursor
->level
[level
].last_key
= last_key
;
447 return scan_bmbt_reclist(mp
, rp
, &numrecs
, type
, ino
,
451 if (numrecs
> mp
->m_bmap_dmxr
[1] || (isroot
== 0 && numrecs
<
452 mp
->m_bmap_dmnr
[1])) {
454 _("inode %" PRIu64
" bad # of bmap records (%u, min - %u, max - %u)\n"),
455 ino
, numrecs
, mp
->m_bmap_dmnr
[1], mp
->m_bmap_dmxr
[1]);
458 pp
= XFS_BMBT_PTR_ADDR(mp
, block
, 1, mp
->m_bmap_dmxr
[1]);
459 pkey
= XFS_BMBT_KEY_ADDR(mp
, block
, 1);
461 last_key
= NULLFILEOFF
;
463 for (i
= 0, err
= 0; i
< numrecs
; i
++) {
465 * XXX - if we were going to fix up the interior btree nodes,
466 * we'd do it right here. For now, if there's a problem,
467 * we'll bail out and presumably clear the inode.
469 if (!verify_dfsbno(mp
, be64_to_cpu(pp
[i
]))) {
471 _("bad bmap btree ptr 0x%llx in ino %" PRIu64
"\n"),
472 (unsigned long long) be64_to_cpu(pp
[i
]), ino
);
476 err
= scan_lbtree(be64_to_cpu(pp
[i
]), level
, scan_bmapbt
,
477 type
, whichfork
, ino
, tot
, nex
, blkmapp
,
478 bm_cursor
, 0, check_dups
, magic
,
484 * fix key (offset) mismatches between the first key
485 * in the child block (as recorded in the cursor) and the
486 * key in the interior node referencing the child block.
488 * fixes cases where entries have been shifted between
489 * child blocks but the parent hasn't been updated. We
490 * don't have to worry about the key values in the cursor
491 * not being set since we only look at the key values of
492 * our child and those are guaranteed to be set by the
493 * call to scan_lbtree() above.
495 if (check_dups
== 0 && be64_to_cpu(pkey
[i
].br_startoff
) !=
496 bm_cursor
->level
[level
-1].first_key
) {
499 _("correcting bt key (was %llu, now %" PRIu64
") in inode %" PRIu64
"\n"
500 "\t\t%s fork, btree block %" PRIu64
"\n"),
502 be64_to_cpu(pkey
[i
].br_startoff
),
503 bm_cursor
->level
[level
-1].first_key
,
507 pkey
[i
].br_startoff
= cpu_to_be64(
508 bm_cursor
->level
[level
-1].first_key
);
511 _("bad btree key (is %llu, should be %" PRIu64
") in inode %" PRIu64
"\n"
512 "\t\t%s fork, btree block %" PRIu64
"\n"),
514 be64_to_cpu(pkey
[i
].br_startoff
),
515 bm_cursor
->level
[level
-1].first_key
,
522 * If we're the last node at our level, check that the last child
523 * block's forward sibling pointer is NULL.
525 if (check_dups
== 0 &&
526 bm_cursor
->level
[level
].right_fsbno
== NULLFSBLOCK
&&
527 bm_cursor
->level
[level
- 1].right_fsbno
!= NULLFSBLOCK
) {
529 _("bad fwd (right) sibling pointer (saw %" PRIu64
" should be NULLFSBLOCK)\n"
530 "\tin inode %" PRIu64
" (%s fork) bmap btree block %" PRIu64
"\n"),
531 bm_cursor
->level
[level
- 1].right_fsbno
,
532 ino
, forkname
, bm_cursor
->level
[level
- 1].fsbno
);
537 * update cursor keys to reflect this block
539 if (check_dups
== 0) {
540 bm_cursor
->level
[level
].first_key
=
541 be64_to_cpu(pkey
[0].br_startoff
);
542 bm_cursor
->level
[level
].last_key
=
543 be64_to_cpu(pkey
[numrecs
- 1].br_startoff
);
551 struct xfs_btree_block
*block
,
560 struct aghdr_cnts
*agcnts
= priv
;
568 xfs_extlen_t lastcount
= 0;
569 xfs_agblock_t lastblock
= 0;
572 case XFS_ABTB_CRC_MAGIC
:
576 case XFS_ABTC_CRC_MAGIC
:
586 if (be32_to_cpu(block
->bb_magic
) != magic
) {
587 do_warn(_("bad magic # %#x in bt%s block %d/%d\n"),
588 be32_to_cpu(block
->bb_magic
), name
, agno
, bno
);
595 * All freespace btree blocks except the roots are freed for a
596 * fully used filesystem, thus they are counted towards the
597 * free data block counter.
600 agcnts
->agfbtreeblks
++;
604 if (be16_to_cpu(block
->bb_level
) != level
) {
605 do_warn(_("expected level %d got %d in bt%s block %d/%d\n"),
606 level
, be16_to_cpu(block
->bb_level
), name
, agno
, bno
);
613 * check for btree blocks multiply claimed
615 state
= get_bmap(agno
, bno
);
616 if (state
!= XR_E_UNKNOWN
) {
617 set_bmap(agno
, bno
, XR_E_MULT
);
619 _("%s freespace btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
620 name
, state
, agno
, bno
, suspect
);
623 set_bmap(agno
, bno
, XR_E_FS_MAP
);
625 numrecs
= be16_to_cpu(block
->bb_numrecs
);
628 if (numrecs
> mp
->m_alloc_mxr
[0]) {
629 numrecs
= mp
->m_alloc_mxr
[0];
632 if (isroot
== 0 && numrecs
< mp
->m_alloc_mnr
[0]) {
633 numrecs
= mp
->m_alloc_mnr
[0];
639 _("bad btree nrecs (%u, min=%u, max=%u) in bt%s block %u/%u\n"),
640 be16_to_cpu(block
->bb_numrecs
),
641 mp
->m_alloc_mnr
[0], mp
->m_alloc_mxr
[0],
646 rp
= XFS_ALLOC_REC_ADDR(mp
, block
, 1);
647 for (i
= 0; i
< numrecs
; i
++) {
648 xfs_agblock_t b
, end
;
649 xfs_extlen_t len
, blen
;
651 b
= be32_to_cpu(rp
[i
].ar_startblock
);
652 len
= be32_to_cpu(rp
[i
].ar_blockcount
);
655 if (b
== 0 || !verify_agbno(mp
, agno
, b
)) {
657 _("invalid start block %u in record %u of %s btree block %u/%u\n"),
658 b
, i
, name
, agno
, bno
);
661 if (len
== 0 || !verify_agbno(mp
, agno
, end
- 1)) {
663 _("invalid length %u in record %u of %s btree block %u/%u\n"),
664 len
, i
, name
, agno
, bno
);
668 if (magic
== XFS_ABTB_MAGIC
||
669 magic
== XFS_ABTB_CRC_MAGIC
) {
670 if (b
<= lastblock
) {
672 "out-of-order bno btree record %d (%u %u) block %u/%u\n"),
673 i
, b
, len
, agno
, bno
);
678 agcnts
->fdblocks
+= len
;
679 agcnts
->agffreeblks
+= len
;
680 if (len
> agcnts
->agflongest
)
681 agcnts
->agflongest
= len
;
682 if (len
< lastcount
) {
684 "out-of-order cnt btree record %d (%u %u) block %u/%u\n"),
685 i
, b
, len
, agno
, bno
);
691 for ( ; b
< end
; b
+= blen
) {
692 state
= get_bmap_ext(agno
, b
, end
, &blen
);
695 set_bmap(agno
, b
, XR_E_FREE1
);
699 * no warning messages -- we'll catch
702 if (magic
== XFS_ABTC_MAGIC
||
703 magic
== XFS_ABTC_CRC_MAGIC
) {
704 set_bmap_ext(agno
, b
, blen
,
711 _("block (%d,%d-%d) multiply claimed by %s space tree, state - %d\n"),
712 agno
, b
, b
+ blen
- 1,
724 pp
= XFS_ALLOC_PTR_ADDR(mp
, block
, 1, mp
->m_alloc_mxr
[1]);
726 if (numrecs
> mp
->m_alloc_mxr
[1]) {
727 numrecs
= mp
->m_alloc_mxr
[1];
730 if (isroot
== 0 && numrecs
< mp
->m_alloc_mnr
[1]) {
731 numrecs
= mp
->m_alloc_mnr
[1];
736 * don't pass bogus tree flag down further if this block
737 * looked ok. bail out if two levels in a row look bad.
741 _("bad btree nrecs (%u, min=%u, max=%u) in bt%s block %u/%u\n"),
742 be16_to_cpu(block
->bb_numrecs
),
743 mp
->m_alloc_mnr
[1], mp
->m_alloc_mxr
[1],
748 } else if (suspect
) {
752 for (i
= 0; i
< numrecs
; i
++) {
753 xfs_agblock_t bno
= be32_to_cpu(pp
[i
]);
756 * XXX - put sibling detection right here.
757 * we know our sibling chain is good. So as we go,
758 * we check the entry before and after each entry.
759 * If either of the entries references a different block,
760 * check the sibling pointer. If there's a sibling
761 * pointer mismatch, try and extract as much data
764 if (bno
!= 0 && verify_agbno(mp
, agno
, bno
)) {
766 case XFS_ABTB_CRC_MAGIC
:
768 scan_sbtree(bno
, level
, agno
, suspect
,
769 scan_allocbt
, 0, magic
, priv
,
770 &xfs_allocbt_buf_ops
);
772 case XFS_ABTC_CRC_MAGIC
:
774 scan_sbtree(bno
, level
, agno
, suspect
,
775 scan_allocbt
, 0, magic
, priv
,
776 &xfs_allocbt_buf_ops
);
785 struct xfs_inobt_rec
*rp
,
788 if (!xfs_sb_version_hassparseinodes(&mp
->m_sb
))
791 return xfs_inobt_is_sparse_disk(rp
, offset
);
794 /* See if the rmapbt owners agree with our observations. */
797 struct xfs_mount
*mp
,
809 case XFS_RMAP_OWN_FS
:
810 case XFS_RMAP_OWN_LOG
:
811 set_bmap_ext(agno
, b
, blen
, XR_E_INUSE_FS1
);
813 case XFS_RMAP_OWN_AG
:
814 case XFS_RMAP_OWN_INOBT
:
815 set_bmap_ext(agno
, b
, blen
, XR_E_FS_MAP1
);
817 case XFS_RMAP_OWN_INODES
:
818 set_bmap_ext(agno
, b
, blen
, XR_E_INO1
);
820 case XFS_RMAP_OWN_REFC
:
821 set_bmap_ext(agno
, b
, blen
, XR_E_REFC
);
823 case XFS_RMAP_OWN_COW
:
824 set_bmap_ext(agno
, b
, blen
, XR_E_COW
);
826 case XFS_RMAP_OWN_NULL
:
831 set_bmap_ext(agno
, b
, blen
, XR_E_INUSE1
);
836 if (owner
== XFS_RMAP_OWN_FS
||
837 owner
== XFS_RMAP_OWN_LOG
)
840 _("Static meta block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64
"\n"),
841 agno
, b
, b
+ blen
- 1,
845 if (owner
== XFS_RMAP_OWN_AG
||
846 owner
== XFS_RMAP_OWN_INOBT
)
849 _("AG meta block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64
"\n"),
850 agno
, b
, b
+ blen
- 1,
854 if (owner
== XFS_RMAP_OWN_INODES
)
857 _("inode block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64
"\n"),
858 agno
, b
, b
+ blen
- 1,
862 if (owner
== XFS_RMAP_OWN_REFC
)
865 _("AG refcount block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64
"\n"),
866 agno
, b
, b
+ blen
- 1,
871 owner
< mp
->m_sb
.sb_dblocks
)
874 _("in use block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64
"\n"),
875 agno
, b
, b
+ blen
- 1,
881 * May be on the AGFL. If not, they'll
887 * multiple inode owners are ok with
890 if (xfs_sb_version_hasreflink(&mp
->m_sb
) &&
891 !XFS_RMAP_NON_INODE_OWNER(owner
))
896 _("unknown block (%d,%d-%d) mismatch on %s tree, state - %d,%" PRIx64
"\n"),
897 agno
, b
, b
+ blen
- 1,
904 struct aghdr_cnts
*agcnts
;
905 struct xfs_rmap_irec high_key
;
906 struct xfs_rmap_irec last_rec
;
907 xfs_agblock_t nr_blocks
;
913 xfs_agblock_t lastblock
,
921 else if (b
< lastblock
)
924 if (owner
> lastowner
)
926 else if (owner
< lastowner
)
929 return offset
> lastoffset
;
934 struct xfs_btree_block
*block
,
943 const char *name
= "rmap";
946 struct xfs_rmap_rec
*rp
;
947 struct rmap_priv
*rmap_priv
= priv
;
951 xfs_agblock_t lastblock
= 0;
952 uint64_t lastowner
= 0;
953 uint64_t lastoffset
= 0;
954 struct xfs_rmap_key
*kp
;
955 struct xfs_rmap_irec key
= {0};
957 if (magic
!= XFS_RMAP_CRC_MAGIC
) {
964 if (be32_to_cpu(block
->bb_magic
) != magic
) {
965 do_warn(_("bad magic # %#x in bt%s block %d/%d\n"),
966 be32_to_cpu(block
->bb_magic
), name
, agno
, bno
);
973 * All RMAP btree blocks except the roots are freed for a
974 * fully empty filesystem, thus they are counted towards the
975 * free data block counter.
978 rmap_priv
->agcnts
->agfbtreeblks
++;
979 rmap_priv
->agcnts
->fdblocks
++;
981 rmap_priv
->nr_blocks
++;
983 if (be16_to_cpu(block
->bb_level
) != level
) {
984 do_warn(_("expected level %d got %d in bt%s block %d/%d\n"),
985 level
, be16_to_cpu(block
->bb_level
), name
, agno
, bno
);
991 /* check for btree blocks multiply claimed */
992 state
= get_bmap(agno
, bno
);
993 if (!(state
== XR_E_UNKNOWN
|| state
== XR_E_FS_MAP1
)) {
994 set_bmap(agno
, bno
, XR_E_MULT
);
996 _("%s rmap btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
997 name
, state
, agno
, bno
, suspect
);
1000 set_bmap(agno
, bno
, XR_E_FS_MAP
);
1002 numrecs
= be16_to_cpu(block
->bb_numrecs
);
1004 if (numrecs
> mp
->m_rmap_mxr
[0]) {
1005 numrecs
= mp
->m_rmap_mxr
[0];
1008 if (isroot
== 0 && numrecs
< mp
->m_rmap_mnr
[0]) {
1009 numrecs
= mp
->m_rmap_mnr
[0];
1015 _("bad btree nrecs (%u, min=%u, max=%u) in bt%s block %u/%u\n"),
1016 be16_to_cpu(block
->bb_numrecs
),
1017 mp
->m_rmap_mnr
[0], mp
->m_rmap_mxr
[0],
1022 rp
= XFS_RMAP_REC_ADDR(block
, 1);
1023 for (i
= 0; i
< numrecs
; i
++) {
1024 xfs_agblock_t b
, end
;
1025 xfs_extlen_t len
, blen
;
1026 int64_t owner
, offset
;
1028 b
= be32_to_cpu(rp
[i
].rm_startblock
);
1029 len
= be32_to_cpu(rp
[i
].rm_blockcount
);
1030 owner
= be64_to_cpu(rp
[i
].rm_owner
);
1031 offset
= be64_to_cpu(rp
[i
].rm_offset
);
1034 key
.rm_startblock
= b
;
1035 key
.rm_blockcount
= len
;
1036 key
.rm_owner
= owner
;
1037 if (libxfs_rmap_irec_offset_unpack(offset
, &key
)) {
1038 /* Look for impossible flags. */
1040 _("invalid flags in record %u of %s btree block %u/%u\n"),
1041 i
, name
, agno
, bno
);
1045 end
= key
.rm_startblock
+ key
.rm_blockcount
;
1047 /* Make sure agbno & len make sense. */
1048 if (!verify_agbno(mp
, agno
, b
)) {
1050 _("invalid start block %u in record %u of %s btree block %u/%u\n"),
1051 b
, i
, name
, agno
, bno
);
1054 if (len
== 0 || !verify_agbno(mp
, agno
, end
- 1)) {
1056 _("invalid length %u in record %u of %s btree block %u/%u\n"),
1057 len
, i
, name
, agno
, bno
);
1061 /* Look for impossible owners. */
1062 if (!((owner
> XFS_RMAP_OWN_MIN
&&
1063 owner
<= XFS_RMAP_OWN_FS
) ||
1064 (XFS_INO_TO_AGNO(mp
, owner
) < mp
->m_sb
.sb_agcount
&&
1065 XFS_AGINO_TO_AGBNO(mp
,
1066 XFS_INO_TO_AGINO(mp
, owner
)) <
1067 mp
->m_sb
.sb_agblocks
)))
1069 _("invalid owner in rmap btree record %d (%"PRId64
" %u) block %u/%u\n"),
1070 i
, owner
, len
, agno
, bno
);
1072 /* Look for impossible record field combinations. */
1073 if (XFS_RMAP_NON_INODE_OWNER(key
.rm_owner
)) {
1076 _("record %d of block (%u/%u) in %s btree cannot have non-inode owner with flags\n"),
1077 i
, agno
, bno
, name
);
1080 _("record %d of block (%u/%u) in %s btree cannot have non-inode owner with offset\n"),
1081 i
, agno
, bno
, name
);
1084 /* Check for out of order records. */
1089 lastoffset
= offset
;
1093 if (xfs_sb_version_hasreflink(&mp
->m_sb
))
1094 bad
= !rmap_in_order(b
, lastblock
,
1096 offset
, lastoffset
);
1098 bad
= b
<= lastblock
;
1101 _("out-of-order rmap btree record %d (%u %"PRId64
" %"PRIx64
" %u) block %u/%u\n"),
1102 i
, b
, owner
, offset
, len
, agno
, bno
);
1107 /* Is this mergeable with the previous record? */
1108 if (rmaps_are_mergeable(&rmap_priv
->last_rec
, &key
)) {
1110 _("record %d in block (%u/%u) of %s tree should be merged with previous record\n"),
1111 i
, agno
, bno
, name
);
1112 rmap_priv
->last_rec
.rm_blockcount
+=
1115 rmap_priv
->last_rec
= key
;
1117 /* Check that we don't go past the high key. */
1118 key
.rm_startblock
+= key
.rm_blockcount
- 1;
1119 if (!XFS_RMAP_NON_INODE_OWNER(key
.rm_owner
) &&
1120 !(key
.rm_flags
& XFS_RMAP_BMBT_BLOCK
))
1121 key
.rm_offset
+= key
.rm_blockcount
- 1;
1122 key
.rm_blockcount
= 0;
1123 if (rmap_diffkeys(&key
, &rmap_priv
->high_key
) > 0) {
1125 _("record %d greater than high key of block (%u/%u) in %s tree\n"),
1126 i
, agno
, bno
, name
);
1129 /* Check for block owner collisions. */
1130 for ( ; b
< end
; b
+= blen
) {
1131 state
= get_bmap_ext(agno
, b
, end
, &blen
);
1132 process_rmap_rec(mp
, agno
, b
, end
, blen
, owner
,
1142 pp
= XFS_RMAP_PTR_ADDR(block
, 1, mp
->m_rmap_mxr
[1]);
1144 if (numrecs
> mp
->m_rmap_mxr
[1]) {
1145 numrecs
= mp
->m_rmap_mxr
[1];
1148 if (isroot
== 0 && numrecs
< mp
->m_rmap_mnr
[1]) {
1149 numrecs
= mp
->m_rmap_mnr
[1];
1154 * don't pass bogus tree flag down further if this block
1155 * looked ok. bail out if two levels in a row look bad.
1159 _("bad btree nrecs (%u, min=%u, max=%u) in bt%s block %u/%u\n"),
1160 be16_to_cpu(block
->bb_numrecs
),
1161 mp
->m_rmap_mnr
[1], mp
->m_rmap_mxr
[1],
1166 } else if (suspect
) {
1170 /* check the node's high keys */
1171 for (i
= 0; !isroot
&& i
< numrecs
; i
++) {
1172 kp
= XFS_RMAP_HIGH_KEY_ADDR(block
, i
+ 1);
1175 key
.rm_startblock
= be32_to_cpu(kp
->rm_startblock
);
1176 key
.rm_owner
= be64_to_cpu(kp
->rm_owner
);
1177 if (libxfs_rmap_irec_offset_unpack(be64_to_cpu(kp
->rm_offset
),
1179 /* Look for impossible flags. */
1181 _("invalid flags in key %u of %s btree block %u/%u\n"),
1182 i
, name
, agno
, bno
);
1185 if (rmap_diffkeys(&key
, &rmap_priv
->high_key
) > 0)
1187 _("key %d greater than high key of block (%u/%u) in %s tree\n"),
1188 i
, agno
, bno
, name
);
1191 for (i
= 0; i
< numrecs
; i
++) {
1192 xfs_agblock_t bno
= be32_to_cpu(pp
[i
]);
1195 * XXX - put sibling detection right here.
1196 * we know our sibling chain is good. So as we go,
1197 * we check the entry before and after each entry.
1198 * If either of the entries references a different block,
1199 * check the sibling pointer. If there's a sibling
1200 * pointer mismatch, try and extract as much data
1203 kp
= XFS_RMAP_HIGH_KEY_ADDR(block
, i
+ 1);
1204 rmap_priv
->high_key
.rm_flags
= 0;
1205 rmap_priv
->high_key
.rm_startblock
=
1206 be32_to_cpu(kp
->rm_startblock
);
1207 rmap_priv
->high_key
.rm_owner
=
1208 be64_to_cpu(kp
->rm_owner
);
1209 if (libxfs_rmap_irec_offset_unpack(be64_to_cpu(kp
->rm_offset
),
1210 &rmap_priv
->high_key
)) {
1211 /* Look for impossible flags. */
1213 _("invalid flags in high key %u of %s btree block %u/%u\n"),
1214 i
, name
, agno
, bno
);
1218 if (bno
!= 0 && verify_agbno(mp
, agno
, bno
)) {
1219 scan_sbtree(bno
, level
, agno
, suspect
, scan_rmapbt
, 0,
1220 magic
, priv
, &xfs_rmapbt_buf_ops
);
1230 struct xfs_refcount_irec last_rec
;
1231 xfs_agblock_t nr_blocks
;
1237 struct xfs_btree_block
*block
,
1240 xfs_agnumber_t agno
,
1246 const char *name
= "refcount";
1248 xfs_refcount_ptr_t
*pp
;
1249 struct xfs_refcount_rec
*rp
;
1253 xfs_agblock_t lastblock
= 0;
1254 struct refc_priv
*refc_priv
= priv
;
1256 if (magic
!= XFS_REFC_CRC_MAGIC
) {
1263 if (be32_to_cpu(block
->bb_magic
) != magic
) {
1264 do_warn(_("bad magic # %#x in %s btree block %d/%d\n"),
1265 be32_to_cpu(block
->bb_magic
), name
, agno
, bno
);
1271 if (be16_to_cpu(block
->bb_level
) != level
) {
1272 do_warn(_("expected level %d got %d in %s btree block %d/%d\n"),
1273 level
, be16_to_cpu(block
->bb_level
), name
, agno
, bno
);
1279 refc_priv
->nr_blocks
++;
1281 /* check for btree blocks multiply claimed */
1282 state
= get_bmap(agno
, bno
);
1283 if (!(state
== XR_E_UNKNOWN
|| state
== XR_E_REFC
)) {
1284 set_bmap(agno
, bno
, XR_E_MULT
);
1286 _("%s btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
1287 name
, state
, agno
, bno
, suspect
);
1290 set_bmap(agno
, bno
, XR_E_FS_MAP
);
1292 numrecs
= be16_to_cpu(block
->bb_numrecs
);
1294 if (numrecs
> mp
->m_refc_mxr
[0]) {
1295 numrecs
= mp
->m_refc_mxr
[0];
1298 if (isroot
== 0 && numrecs
< mp
->m_refc_mnr
[0]) {
1299 numrecs
= mp
->m_refc_mnr
[0];
1305 _("bad btree nrecs (%u, min=%u, max=%u) in %s btree block %u/%u\n"),
1306 be16_to_cpu(block
->bb_numrecs
),
1307 mp
->m_refc_mnr
[0], mp
->m_refc_mxr
[0],
1312 rp
= XFS_REFCOUNT_REC_ADDR(block
, 1);
1313 for (i
= 0; i
< numrecs
; i
++) {
1314 xfs_agblock_t b
, agb
, end
;
1318 b
= agb
= be32_to_cpu(rp
[i
].rc_startblock
);
1319 len
= be32_to_cpu(rp
[i
].rc_blockcount
);
1320 nr
= be32_to_cpu(rp
[i
].rc_refcount
);
1321 if (b
>= XFS_REFC_COW_START
&& nr
!= 1)
1323 _("leftover CoW extent has incorrect refcount in record %u of %s btree block %u/%u\n"),
1324 i
, name
, agno
, bno
);
1326 if (agb
< XFS_REFC_COW_START
)
1328 _("leftover CoW extent has invalid startblock in record %u of %s btree block %u/%u\n"),
1329 i
, name
, agno
, bno
);
1330 agb
-= XFS_REFC_COW_START
;
1334 if (!verify_agbno(mp
, agno
, agb
)) {
1336 _("invalid start block %u in record %u of %s btree block %u/%u\n"),
1337 b
, i
, name
, agno
, bno
);
1340 if (len
== 0 || !verify_agbno(mp
, agno
, end
- 1)) {
1342 _("invalid length %u in record %u of %s btree block %u/%u\n"),
1343 len
, i
, name
, agno
, bno
);
1351 for (c
= agb
; c
< end
; c
+= cnr
) {
1352 state
= get_bmap_ext(agno
, c
, end
, &cnr
);
1357 _("leftover CoW extent (%u/%u) len %u\n"),
1359 set_bmap_ext(agno
, c
, cnr
, XR_E_FREE
);
1363 _("extent (%u/%u) len %u claimed, state is %d\n"),
1364 agno
, c
, cnr
, state
);
1368 } else if (nr
< 2 || nr
> MAXREFCOUNT
) {
1370 _("invalid reference count %u in record %u of %s btree block %u/%u\n"),
1371 nr
, i
, name
, agno
, bno
);
1375 if (b
&& b
<= lastblock
) {
1377 "out-of-order %s btree record %d (%u %u) block %u/%u\n"),
1378 name
, i
, b
, len
, agno
, bno
);
1383 /* Is this record mergeable with the last one? */
1384 if (refc_priv
->last_rec
.rc_startblock
+
1385 refc_priv
->last_rec
.rc_blockcount
== b
&&
1386 refc_priv
->last_rec
.rc_refcount
== nr
) {
1388 _("record %d in block (%u/%u) of %s tree should be merged with previous record\n"),
1389 i
, agno
, bno
, name
);
1390 refc_priv
->last_rec
.rc_blockcount
+= len
;
1392 refc_priv
->last_rec
.rc_startblock
= b
;
1393 refc_priv
->last_rec
.rc_blockcount
= len
;
1394 refc_priv
->last_rec
.rc_refcount
= nr
;
1397 /* XXX: probably want to mark the reflinked areas? */
1405 pp
= XFS_REFCOUNT_PTR_ADDR(block
, 1, mp
->m_refc_mxr
[1]);
1407 if (numrecs
> mp
->m_refc_mxr
[1]) {
1408 numrecs
= mp
->m_refc_mxr
[1];
1411 if (isroot
== 0 && numrecs
< mp
->m_refc_mnr
[1]) {
1412 numrecs
= mp
->m_refc_mnr
[1];
1417 * don't pass bogus tree flag down further if this block
1418 * looked ok. bail out if two levels in a row look bad.
1422 _("bad btree nrecs (%u, min=%u, max=%u) in %s btree block %u/%u\n"),
1423 be16_to_cpu(block
->bb_numrecs
),
1424 mp
->m_refc_mnr
[1], mp
->m_refc_mxr
[1],
1429 } else if (suspect
) {
1433 for (i
= 0; i
< numrecs
; i
++) {
1434 xfs_agblock_t bno
= be32_to_cpu(pp
[i
]);
1436 if (bno
!= 0 && verify_agbno(mp
, agno
, bno
)) {
1437 scan_sbtree(bno
, level
, agno
, suspect
, scan_refcbt
, 0,
1438 magic
, priv
, &xfs_refcountbt_buf_ops
);
1443 refcount_avoid_check();
1448 * The following helpers are to help process and validate individual on-disk
1449 * inode btree records. We have two possible inode btrees with slightly
1450 * different semantics. Many of the validations and actions are equivalent, such
1451 * as record alignment constraints, etc. Other validations differ, such as the
1452 * fact that the inode chunk block allocation state is set by the content of the
1453 * core inobt and verified by the content of the finobt.
1455 * The following structures are used to facilitate common validation routines
1456 * where the only difference between validation of the inobt or finobt might be
1457 * the error messages that results in the event of failure.
1464 const char *inobt_names
[] = {
1470 verify_single_ino_chunk_align(
1471 xfs_agnumber_t agno
,
1472 enum inobt_type type
,
1473 struct xfs_inobt_rec
*rp
,
1477 const char *inobt_name
= inobt_names
[type
];
1480 xfs_agblock_t agbno
;
1484 ino
= be32_to_cpu(rp
->ir_startino
);
1485 off
= XFS_AGINO_TO_OFFSET(mp
, ino
);
1486 agbno
= XFS_AGINO_TO_AGBNO(mp
, ino
);
1487 lino
= XFS_AGINO_TO_INO(mp
, agno
, ino
);
1490 * on multi-block block chunks, all chunks start at the beginning of the
1491 * block. with multi-chunk blocks, all chunks must start on 64-inode
1492 * boundaries since each block can hold N complete chunks. if fs has
1493 * aligned inodes, all chunks must start at a fs_ino_alignment*N'th
1494 * agbno. skip recs with badly aligned starting inodes.
1497 (inodes_per_block
<= XFS_INODES_PER_CHUNK
&& off
!= 0) ||
1498 (inodes_per_block
> XFS_INODES_PER_CHUNK
&&
1499 off
% XFS_INODES_PER_CHUNK
!= 0) ||
1500 (fs_aligned_inodes
&& fs_ino_alignment
&&
1501 agbno
% fs_ino_alignment
!= 0)) {
1503 _("badly aligned %s rec (starting inode = %" PRIu64
")\n"),
1509 * verify numeric validity of inode chunk first before inserting into a
1510 * tree. don't have to worry about the overflow case because the
1511 * starting ino number of a chunk can only get within 255 inodes of max
1512 * (NULLAGINO). if it gets closer, the agino number will be illegal as
1513 * the agbno will be too large.
1515 if (verify_aginum(mp
, agno
, ino
)) {
1517 _("bad starting inode # (%" PRIu64
" (0x%x 0x%x)) in %s rec, skipping rec\n"),
1518 lino
, agno
, ino
, inobt_name
);
1523 if (verify_aginum(mp
, agno
,
1524 ino
+ XFS_INODES_PER_CHUNK
- 1)) {
1526 _("bad ending inode # (%" PRIu64
" (0x%x 0x%zx)) in %s rec, skipping rec\n"),
1527 lino
+ XFS_INODES_PER_CHUNK
- 1,
1529 ino
+ XFS_INODES_PER_CHUNK
- 1,
1539 * Process the state of individual inodes in an on-disk inobt record and import
1540 * into the appropriate in-core tree based on whether the on-disk tree is
1541 * suspect. Return the total and free inode counts based on the record free and
1545 import_single_ino_chunk(
1546 xfs_agnumber_t agno
,
1547 enum inobt_type type
,
1548 struct xfs_inobt_rec
*rp
,
1553 struct ino_tree_node
*ino_rec
= NULL
;
1554 const char *inobt_name
= inobt_names
[type
];
1560 ino
= be32_to_cpu(rp
->ir_startino
);
1563 if (XFS_INOBT_IS_FREE_DISK(rp
, 0))
1564 ino_rec
= set_inode_free_alloc(mp
, agno
, ino
);
1566 ino_rec
= set_inode_used_alloc(mp
, agno
, ino
);
1567 for (j
= 1; j
< XFS_INODES_PER_CHUNK
; j
++) {
1568 if (XFS_INOBT_IS_FREE_DISK(rp
, j
))
1569 set_inode_free(ino_rec
, j
);
1571 set_inode_used(ino_rec
, j
);
1574 for (j
= 0; j
< XFS_INODES_PER_CHUNK
; j
++) {
1575 if (XFS_INOBT_IS_FREE_DISK(rp
, j
))
1576 add_aginode_uncertain(mp
, agno
, ino
+ j
, 1);
1578 add_aginode_uncertain(mp
, agno
, ino
+ j
, 0);
1583 * Mark sparse inodes as such in the in-core tree. Verify that sparse
1584 * inodes are free and that freecount is consistent with the free mask.
1586 nfree
= ninodes
= 0;
1587 for (j
= 0; j
< XFS_INODES_PER_CHUNK
; j
++) {
1588 if (ino_issparse(rp
, j
)) {
1589 if (!suspect
&& !XFS_INOBT_IS_FREE_DISK(rp
, j
)) {
1591 _("ir_holemask/ir_free mismatch, %s chunk %d/%u, holemask 0x%x free 0x%llx\n"),
1592 inobt_name
, agno
, ino
,
1593 be16_to_cpu(rp
->ir_u
.sp
.ir_holemask
),
1594 (unsigned long long)be64_to_cpu(rp
->ir_free
));
1597 if (!suspect
&& ino_rec
)
1598 set_inode_sparse(ino_rec
, j
);
1600 /* count fields track non-sparse inos */
1601 if (XFS_INOBT_IS_FREE_DISK(rp
, j
))
1608 *p_ninodes
= ninodes
;
1614 scan_single_ino_chunk(
1615 xfs_agnumber_t agno
,
1616 xfs_inobt_rec_t
*rp
,
1621 xfs_agblock_t agbno
;
1627 ino_tree_node_t
*first_rec
, *last_rec
;
1631 ino
= be32_to_cpu(rp
->ir_startino
);
1632 off
= XFS_AGINO_TO_OFFSET(mp
, ino
);
1633 agbno
= XFS_AGINO_TO_AGBNO(mp
, ino
);
1634 lino
= XFS_AGINO_TO_INO(mp
, agno
, ino
);
1635 freecount
= inorec_get_freecount(mp
, rp
);
1638 * Verify record alignment, start/end inode numbers, etc.
1640 suspect
= verify_single_ino_chunk_align(agno
, INOBT
, rp
, suspect
,
1646 * set state of each block containing inodes
1648 if (off
== 0 && !suspect
) {
1650 j
< XFS_INODES_PER_CHUNK
;
1651 j
+= mp
->m_sb
.sb_inopblock
) {
1653 /* inodes in sparse chunks don't use blocks */
1654 if (ino_issparse(rp
, j
))
1657 agbno
= XFS_AGINO_TO_AGBNO(mp
, ino
+ j
);
1658 state
= get_bmap(agno
, agbno
);
1663 case XR_E_INO1
: /* seen by rmap */
1664 set_bmap(agno
, agbno
, XR_E_INO
);
1667 case XR_E_INUSE_FS1
:
1669 ino
+ j
>= first_prealloc_ino
&&
1670 ino
+ j
< last_prealloc_ino
) {
1671 set_bmap(agno
, agbno
, XR_E_INO
);
1676 /* XXX - maybe should mark block a duplicate */
1678 _("inode chunk claims used block, inobt block - agno %d, bno %d, inopb %d\n"),
1679 agno
, agbno
, mp
->m_sb
.sb_inopblock
);
1686 * ensure only one avl entry per chunk
1688 find_inode_rec_range(mp
, agno
, ino
, ino
+ XFS_INODES_PER_CHUNK
,
1689 &first_rec
, &last_rec
);
1690 if (first_rec
!= NULL
) {
1692 * this chunk overlaps with one (or more)
1693 * already in the tree
1696 _("inode rec for ino %" PRIu64
" (%d/%d) overlaps existing rec (start %d/%d)\n"),
1697 lino
, agno
, ino
, agno
, first_rec
->ino_startnum
);
1701 * if the 2 chunks start at the same place,
1702 * then we don't have to put this one
1703 * in the uncertain list. go to the next one.
1705 if (first_rec
->ino_startnum
== ino
)
1710 * Import the state of individual inodes into the appropriate in-core
1711 * trees, mark them free or used, and get the resulting total and free
1714 nfree
= ninodes
= 0;
1715 suspect
= import_single_ino_chunk(agno
, INOBT
, rp
, suspect
, &nfree
,
1718 if (nfree
!= freecount
) {
1720 _("ir_freecount/free mismatch, inode chunk %d/%u, freecount %d nfree %d\n"),
1721 agno
, ino
, freecount
, nfree
);
1724 /* verify sparse record formats have a valid inode count */
1725 if (xfs_sb_version_hassparseinodes(&mp
->m_sb
) &&
1726 ninodes
!= rp
->ir_u
.sp
.ir_count
) {
1728 _("invalid inode count, inode chunk %d/%u, count %d ninodes %d\n"),
1729 agno
, ino
, rp
->ir_u
.sp
.ir_count
, ninodes
);
1736 scan_single_finobt_chunk(
1737 xfs_agnumber_t agno
,
1738 xfs_inobt_rec_t
*rp
,
1743 xfs_agblock_t agbno
;
1749 ino_tree_node_t
*first_rec
, *last_rec
;
1753 ino
= be32_to_cpu(rp
->ir_startino
);
1754 off
= XFS_AGINO_TO_OFFSET(mp
, ino
);
1755 agbno
= XFS_AGINO_TO_AGBNO(mp
, ino
);
1756 lino
= XFS_AGINO_TO_INO(mp
, agno
, ino
);
1757 freecount
= inorec_get_freecount(mp
, rp
);
1760 * Verify record alignment, start/end inode numbers, etc.
1762 suspect
= verify_single_ino_chunk_align(agno
, FINOBT
, rp
, suspect
,
1768 * cross check state of each block containing inodes referenced by the
1769 * finobt against what we have already scanned from the alloc inobt.
1771 if (off
== 0 && !suspect
) {
1773 j
< XFS_INODES_PER_CHUNK
;
1774 j
+= mp
->m_sb
.sb_inopblock
) {
1775 agbno
= XFS_AGINO_TO_AGBNO(mp
, ino
+ j
);
1776 state
= get_bmap(agno
, agbno
);
1778 /* sparse inodes should not refer to inode blocks */
1779 if (ino_issparse(rp
, j
)) {
1780 if (state
== XR_E_INO
) {
1782 _("sparse inode chunk claims inode block, finobt block - agno %d, bno %d, inopb %d\n"),
1783 agno
, agbno
, mp
->m_sb
.sb_inopblock
);
1792 case XR_E_INO1
: /* seen by rmap */
1793 set_bmap(agno
, agbno
, XR_E_INO
);
1797 _("inode chunk claims untracked block, finobt block - agno %d, bno %d, inopb %d\n"),
1798 agno
, agbno
, mp
->m_sb
.sb_inopblock
);
1800 set_bmap(agno
, agbno
, XR_E_INO
);
1804 case XR_E_INUSE_FS1
:
1806 ino
+ j
>= first_prealloc_ino
&&
1807 ino
+ j
< last_prealloc_ino
) {
1809 _("inode chunk claims untracked block, finobt block - agno %d, bno %d, inopb %d\n"),
1810 agno
, agbno
, mp
->m_sb
.sb_inopblock
);
1812 set_bmap(agno
, agbno
, XR_E_INO
);
1819 _("inode chunk claims used block, finobt block - agno %d, bno %d, inopb %d\n"),
1820 agno
, agbno
, mp
->m_sb
.sb_inopblock
);
1827 * ensure we have an incore entry for each chunk
1829 find_inode_rec_range(mp
, agno
, ino
, ino
+ XFS_INODES_PER_CHUNK
,
1830 &first_rec
, &last_rec
);
1837 * verify consistency between finobt record and incore state
1839 if (first_rec
->ino_startnum
!= ino
) {
1841 _("finobt rec for ino %" PRIu64
" (%d/%u) does not match existing rec (%d/%d)\n"),
1842 lino
, agno
, ino
, agno
, first_rec
->ino_startnum
);
1846 nfree
= ninodes
= 0;
1847 for (j
= 0; j
< XFS_INODES_PER_CHUNK
; j
++) {
1848 int isfree
= XFS_INOBT_IS_FREE_DISK(rp
, j
);
1849 int issparse
= ino_issparse(rp
, j
);
1853 if (isfree
&& !issparse
)
1857 * inode allocation state should be consistent between
1858 * the inobt and finobt
1861 isfree
!= is_inode_free(first_rec
, j
))
1865 issparse
!= is_inode_sparse(first_rec
, j
))
1869 goto check_freecount
;
1873 * The finobt contains a record that the previous inobt scan never
1874 * found. Warn about it and import the inodes into the appropriate
1877 * Note that this should do the right thing if the previous inobt scan
1878 * had added these inodes to the uncertain tree. If the finobt is not
1879 * suspect, these inodes should supercede the uncertain ones. Otherwise,
1880 * the uncertain tree helpers handle the case where uncertain inodes
1883 do_warn(_("undiscovered finobt record, ino %" PRIu64
" (%d/%u)\n"),
1886 nfree
= ninodes
= 0;
1887 suspect
= import_single_ino_chunk(agno
, FINOBT
, rp
, suspect
, &nfree
,
1893 * Verify that the record freecount matches the actual number of free
1894 * inodes counted in the record. Don't increment 'suspect' here, since
1895 * we have already verified the allocation state of the individual
1896 * inodes against the in-core state. This will have already incremented
1897 * 'suspect' if something is wrong. If suspect hasn't been set at this
1898 * point, these warnings mean that we have a simple freecount
1899 * inconsistency or a stray finobt record (as opposed to a broader tree
1900 * corruption). Issue a warning and continue the scan. The final btree
1901 * reconstruction will correct this naturally.
1903 if (nfree
!= freecount
) {
1905 _("finobt ir_freecount/free mismatch, inode chunk %d/%u, freecount %d nfree %d\n"),
1906 agno
, ino
, freecount
, nfree
);
1911 _("finobt record with no free inodes, inode chunk %d/%u\n"), agno
, ino
);
1914 /* verify sparse record formats have a valid inode count */
1915 if (xfs_sb_version_hassparseinodes(&mp
->m_sb
) &&
1916 ninodes
!= rp
->ir_u
.sp
.ir_count
) {
1918 _("invalid inode count, inode chunk %d/%u, count %d ninodes %d\n"),
1919 agno
, ino
, rp
->ir_u
.sp
.ir_count
, ninodes
);
1926 * this one walks the inode btrees sucking the info there into
1927 * the incore avl tree. We try and rescue corrupted btree records
1928 * to minimize our chances of losing inodes. Inode info from potentially
1929 * corrupt sources could be bogus so rather than put the info straight
1930 * into the tree, instead we put it on a list and try and verify the
1931 * info in the next phase by examining what's on disk. At that point,
1932 * we'll be able to figure out what's what and stick the corrected info
1933 * into the tree. We do bail out at some point and give up on a subtree
1934 * so as to avoid walking randomly all over the ag.
1936 * Note that it's also ok if the free/inuse info wrong, we can correct
1937 * that when we examine the on-disk inode. The important thing is to
1938 * get the start and alignment of the inode chunks right. Those chunks
1939 * that we aren't sure about go into the uncertain list.
1943 struct xfs_btree_block
*block
,
1946 xfs_agnumber_t agno
,
1952 struct aghdr_cnts
*agcnts
= priv
;
1956 xfs_inobt_ptr_t
*pp
;
1957 xfs_inobt_rec_t
*rp
;
1963 if (be32_to_cpu(block
->bb_magic
) != magic
) {
1964 do_warn(_("bad magic # %#x in inobt block %d/%d\n"),
1965 be32_to_cpu(block
->bb_magic
), agno
, bno
);
1971 if (be16_to_cpu(block
->bb_level
) != level
) {
1972 do_warn(_("expected level %d got %d in inobt block %d/%d\n"),
1973 level
, be16_to_cpu(block
->bb_level
), agno
, bno
);
1981 * check for btree blocks multiply claimed, any unknown/free state
1982 * is ok in the bitmap block.
1984 state
= get_bmap(agno
, bno
);
1986 case XR_E_FS_MAP1
: /* already been seen by an rmap scan */
1990 set_bmap(agno
, bno
, XR_E_FS_MAP
);
1993 set_bmap(agno
, bno
, XR_E_MULT
);
1995 _("inode btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
1996 state
, agno
, bno
, suspect
);
1999 numrecs
= be16_to_cpu(block
->bb_numrecs
);
2002 * leaf record in btree
2005 /* check for trashed btree block */
2007 if (numrecs
> mp
->m_inobt_mxr
[0]) {
2008 numrecs
= mp
->m_inobt_mxr
[0];
2011 if (isroot
== 0 && numrecs
< mp
->m_inobt_mnr
[0]) {
2012 numrecs
= mp
->m_inobt_mnr
[0];
2018 do_warn(_("dubious inode btree block header %d/%d\n"),
2023 rp
= XFS_INOBT_REC_ADDR(mp
, block
, 1);
2026 * step through the records, each record points to
2027 * a chunk of inodes. The start of inode chunks should
2028 * be block-aligned. Each inode btree rec should point
2029 * to the start of a block of inodes or the start of a group
2030 * of INODES_PER_CHUNK (64) inodes. off is the offset into
2031 * the block. skip processing of bogus records.
2033 for (i
= 0; i
< numrecs
; i
++) {
2034 freecount
= inorec_get_freecount(mp
, &rp
[i
]);
2036 if (magic
== XFS_IBT_MAGIC
||
2037 magic
== XFS_IBT_CRC_MAGIC
) {
2038 int icount
= XFS_INODES_PER_CHUNK
;
2041 * ir_count holds the inode count for all
2042 * records on fs' with sparse inode support
2044 if (xfs_sb_version_hassparseinodes(&mp
->m_sb
))
2045 icount
= rp
[i
].ir_u
.sp
.ir_count
;
2047 agcnts
->agicount
+= icount
;
2048 agcnts
->agifreecount
+= freecount
;
2049 agcnts
->ifreecount
+= freecount
;
2051 suspect
= scan_single_ino_chunk(agno
, &rp
[i
],
2055 * the finobt tracks records with free inodes,
2056 * so only the free inode count is expected to be
2057 * consistent with the agi
2059 agcnts
->fibtfreecount
+= freecount
;
2061 suspect
= scan_single_finobt_chunk(agno
, &rp
[i
],
2073 * interior record, continue on
2075 if (numrecs
> mp
->m_inobt_mxr
[1]) {
2076 numrecs
= mp
->m_inobt_mxr
[1];
2079 if (isroot
== 0 && numrecs
< mp
->m_inobt_mnr
[1]) {
2080 numrecs
= mp
->m_inobt_mnr
[1];
2084 pp
= XFS_INOBT_PTR_ADDR(mp
, block
, 1, mp
->m_inobt_mxr
[1]);
2087 * don't pass bogus tree flag down further if this block
2088 * looked ok. bail out if two levels in a row look bad.
2091 if (suspect
&& !hdr_errors
)
2101 for (i
= 0; i
< numrecs
; i
++) {
2102 if (be32_to_cpu(pp
[i
]) != 0 && verify_agbno(mp
, agno
,
2103 be32_to_cpu(pp
[i
])))
2104 scan_sbtree(be32_to_cpu(pp
[i
]), level
, agno
,
2105 suspect
, scan_inobt
, 0, magic
, priv
,
2106 &xfs_inobt_buf_ops
);
2113 struct aghdr_cnts
*agcnts
)
2116 xfs_agnumber_t agno
;
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
);
2142 freelist
= XFS_BUF_TO_AGFL_BNO(mp
, agflbuf
);
2143 i
= be32_to_cpu(agf
->agf_flfirst
);
2146 /* agf values not fixed in verify_set_agf, so recheck */
2147 if (be32_to_cpu(agf
->agf_flfirst
) >= libxfs_agfl_size(mp
) ||
2148 be32_to_cpu(agf
->agf_fllast
) >= libxfs_agfl_size(mp
)) {
2149 do_warn(_("agf %d freelist blocks bad, skipping "
2150 "freelist scan\n"), i
);
2157 bno
= be32_to_cpu(freelist
[i
]);
2158 if (verify_agbno(mp
, agno
, bno
))
2159 set_bmap(agno
, bno
, XR_E_FREE
);
2161 do_warn(_("bad agbno %u in agfl, agno %d\n"),
2164 if (i
== be32_to_cpu(agf
->agf_fllast
))
2166 if (++i
== libxfs_agfl_size(mp
))
2169 if (count
!= be32_to_cpu(agf
->agf_flcount
)) {
2170 do_warn(_("freeblk count %d != flcount %d in ag %d\n"), count
,
2171 be32_to_cpu(agf
->agf_flcount
), agno
);
2174 agcnts
->fdblocks
+= count
;
2176 libxfs_putbuf(agflbuf
);
2181 struct xfs_agf
*agf
,
2182 xfs_agnumber_t agno
,
2183 struct aghdr_cnts
*agcnts
)
2188 bno
= be32_to_cpu(agf
->agf_roots
[XFS_BTNUM_BNO
]);
2189 if (bno
!= 0 && verify_agbno(mp
, agno
, bno
)) {
2190 magic
= xfs_sb_version_hascrc(&mp
->m_sb
) ? XFS_ABTB_CRC_MAGIC
2192 scan_sbtree(bno
, be32_to_cpu(agf
->agf_levels
[XFS_BTNUM_BNO
]),
2193 agno
, 0, scan_allocbt
, 1, magic
, agcnts
,
2194 &xfs_allocbt_buf_ops
);
2196 do_warn(_("bad agbno %u for btbno root, agno %d\n"),
2200 bno
= be32_to_cpu(agf
->agf_roots
[XFS_BTNUM_CNT
]);
2201 if (bno
!= 0 && verify_agbno(mp
, agno
, bno
)) {
2202 magic
= xfs_sb_version_hascrc(&mp
->m_sb
) ? XFS_ABTC_CRC_MAGIC
2204 scan_sbtree(bno
, be32_to_cpu(agf
->agf_levels
[XFS_BTNUM_CNT
]),
2205 agno
, 0, scan_allocbt
, 1, magic
, agcnts
,
2206 &xfs_allocbt_buf_ops
);
2208 do_warn(_("bad agbno %u for btbcnt root, agno %d\n"),
2212 if (xfs_sb_version_hasrmapbt(&mp
->m_sb
)) {
2213 struct rmap_priv priv
;
2215 memset(&priv
.high_key
, 0xFF, sizeof(priv
.high_key
));
2216 priv
.high_key
.rm_blockcount
= 0;
2217 priv
.agcnts
= agcnts
;
2218 priv
.last_rec
.rm_owner
= XFS_RMAP_OWN_UNKNOWN
;
2220 bno
= be32_to_cpu(agf
->agf_roots
[XFS_BTNUM_RMAP
]);
2221 if (bno
!= 0 && verify_agbno(mp
, agno
, bno
)) {
2223 be32_to_cpu(agf
->agf_levels
[XFS_BTNUM_RMAP
]),
2224 agno
, 0, scan_rmapbt
, 1, XFS_RMAP_CRC_MAGIC
,
2225 &priv
, &xfs_rmapbt_buf_ops
);
2226 if (be32_to_cpu(agf
->agf_rmap_blocks
) != priv
.nr_blocks
)
2227 do_warn(_("bad rmapbt block count %u, saw %u\n"),
2229 be32_to_cpu(agf
->agf_rmap_blocks
));
2231 do_warn(_("bad agbno %u for rmapbt root, agno %d\n"),
2237 if (xfs_sb_version_hasreflink(&mp
->m_sb
)) {
2238 bno
= be32_to_cpu(agf
->agf_refcount_root
);
2239 if (bno
!= 0 && verify_agbno(mp
, agno
, bno
)) {
2240 struct refc_priv priv
;
2242 memset(&priv
, 0, sizeof(priv
));
2244 be32_to_cpu(agf
->agf_refcount_level
),
2245 agno
, 0, scan_refcbt
, 1, XFS_REFC_CRC_MAGIC
,
2246 &priv
, &xfs_refcountbt_buf_ops
);
2247 if (be32_to_cpu(agf
->agf_refcount_blocks
) != priv
.nr_blocks
)
2248 do_warn(_("bad refcountbt block count %u, saw %u\n"),
2250 be32_to_cpu(agf
->agf_refcount_blocks
));
2252 do_warn(_("bad agbno %u for refcntbt root, agno %d\n"),
2254 refcount_avoid_check();
2258 if (be32_to_cpu(agf
->agf_freeblks
) != agcnts
->agffreeblks
) {
2259 do_warn(_("agf_freeblks %u, counted %u in ag %u\n"),
2260 be32_to_cpu(agf
->agf_freeblks
), agcnts
->agffreeblks
, agno
);
2263 if (be32_to_cpu(agf
->agf_longest
) != agcnts
->agflongest
) {
2264 do_warn(_("agf_longest %u, counted %u in ag %u\n"),
2265 be32_to_cpu(agf
->agf_longest
), agcnts
->agflongest
, agno
);
2268 if (xfs_sb_version_haslazysbcount(&mp
->m_sb
) &&
2269 be32_to_cpu(agf
->agf_btreeblks
) != agcnts
->agfbtreeblks
) {
2270 do_warn(_("agf_btreeblks %u, counted %" PRIu64
" in ag %u\n"),
2271 be32_to_cpu(agf
->agf_btreeblks
), agcnts
->agfbtreeblks
, agno
);
2278 struct xfs_agi
*agi
,
2279 xfs_agnumber_t agno
,
2280 struct aghdr_cnts
*agcnts
)
2286 bno
= be32_to_cpu(agi
->agi_root
);
2287 if (bno
!= 0 && verify_agbno(mp
, agno
, bno
)) {
2288 magic
= xfs_sb_version_hascrc(&mp
->m_sb
) ? XFS_IBT_CRC_MAGIC
2290 scan_sbtree(bno
, be32_to_cpu(agi
->agi_level
),
2291 agno
, 0, scan_inobt
, 1, magic
, agcnts
,
2292 &xfs_inobt_buf_ops
);
2294 do_warn(_("bad agbno %u for inobt root, agno %d\n"),
2295 be32_to_cpu(agi
->agi_root
), agno
);
2298 if (xfs_sb_version_hasfinobt(&mp
->m_sb
)) {
2299 bno
= be32_to_cpu(agi
->agi_free_root
);
2300 if (bno
!= 0 && verify_agbno(mp
, agno
, bno
)) {
2301 magic
= xfs_sb_version_hascrc(&mp
->m_sb
) ?
2302 XFS_FIBT_CRC_MAGIC
: XFS_FIBT_MAGIC
;
2303 scan_sbtree(bno
, be32_to_cpu(agi
->agi_free_level
),
2304 agno
, 0, scan_inobt
, 1, magic
, agcnts
,
2305 &xfs_inobt_buf_ops
);
2307 do_warn(_("bad agbno %u for finobt root, agno %d\n"),
2308 be32_to_cpu(agi
->agi_free_root
), agno
);
2312 if (be32_to_cpu(agi
->agi_count
) != agcnts
->agicount
) {
2313 do_warn(_("agi_count %u, counted %u in ag %u\n"),
2314 be32_to_cpu(agi
->agi_count
), agcnts
->agicount
, agno
);
2317 if (be32_to_cpu(agi
->agi_freecount
) != agcnts
->agifreecount
) {
2318 do_warn(_("agi_freecount %u, counted %u in ag %u\n"),
2319 be32_to_cpu(agi
->agi_freecount
), agcnts
->agifreecount
, agno
);
2322 if (xfs_sb_version_hasfinobt(&mp
->m_sb
) &&
2323 be32_to_cpu(agi
->agi_freecount
) != agcnts
->fibtfreecount
) {
2324 do_warn(_("agi_freecount %u, counted %u in ag %u finobt\n"),
2325 be32_to_cpu(agi
->agi_freecount
), agcnts
->fibtfreecount
,
2329 for (i
= 0; i
< XFS_AGI_UNLINKED_BUCKETS
; i
++) {
2330 xfs_agino_t agino
= be32_to_cpu(agi
->agi_unlinked
[i
]);
2332 if (agino
!= NULLAGINO
) {
2334 _("agi unlinked bucket %d is %u in ag %u (inode=%" PRIu64
")\n"),
2336 XFS_AGINO_TO_INO(mp
, agno
, agino
));
2342 * Scan an AG for obvious corruption.
2346 struct workqueue
*wq
,
2347 xfs_agnumber_t agno
,
2350 struct aghdr_cnts
*agcnts
= arg
;
2351 struct xfs_agf
*agf
;
2352 struct xfs_buf
*agfbuf
= NULL
;
2354 struct xfs_agi
*agi
;
2355 struct xfs_buf
*agibuf
= NULL
;
2357 struct xfs_sb
*sb
= NULL
;
2358 struct xfs_buf
*sbbuf
= NULL
;
2361 char *objname
= NULL
;
2363 sb
= (struct xfs_sb
*)calloc(BBTOB(XFS_FSS_TO_BB(mp
, 1)), 1);
2365 do_error(_("can't allocate memory for superblock\n"));
2369 sbbuf
= libxfs_readbuf(mp
->m_dev
, XFS_AG_DADDR(mp
, agno
, XFS_SB_DADDR
),
2370 XFS_FSS_TO_BB(mp
, 1), 0, &xfs_sb_buf_ops
);
2372 objname
= _("root superblock");
2375 libxfs_sb_from_disk(sb
, XFS_BUF_TO_SBP(sbbuf
));
2377 agfbuf
= libxfs_readbuf(mp
->m_dev
,
2378 XFS_AG_DADDR(mp
, agno
, XFS_AGF_DADDR(mp
)),
2379 XFS_FSS_TO_BB(mp
, 1), 0, &xfs_agf_buf_ops
);
2381 objname
= _("agf block");
2382 goto out_free_sbbuf
;
2384 agf
= XFS_BUF_TO_AGF(agfbuf
);
2386 agibuf
= libxfs_readbuf(mp
->m_dev
,
2387 XFS_AG_DADDR(mp
, agno
, XFS_AGI_DADDR(mp
)),
2388 XFS_FSS_TO_BB(mp
, 1), 0, &xfs_agi_buf_ops
);
2390 objname
= _("agi block");
2391 goto out_free_agfbuf
;
2393 agi
= XFS_BUF_TO_AGI(agibuf
);
2395 /* fix up bad ag headers */
2397 status
= verify_set_agheader(mp
, sbbuf
, sb
, agf
, agi
, agno
);
2399 if (status
& XR_AG_SB_SEC
) {
2403 * clear bad sector bit because we don't want
2404 * to skip further processing. we just want to
2405 * ensure that we write out the modified sb buffer.
2407 status
&= ~XR_AG_SB_SEC
;
2409 if (status
& XR_AG_SB
) {
2411 do_warn(_("reset bad sb for ag %d\n"), agno
);
2414 do_warn(_("would reset bad sb for ag %d\n"), agno
);
2417 if (status
& XR_AG_AGF
) {
2419 do_warn(_("reset bad agf for ag %d\n"), agno
);
2422 do_warn(_("would reset bad agf for ag %d\n"), agno
);
2425 if (status
& XR_AG_AGI
) {
2427 do_warn(_("reset bad agi for ag %d\n"), agno
);
2430 do_warn(_("would reset bad agi for ag %d\n"), agno
);
2434 if (status
&& no_modify
) {
2435 do_warn(_("bad uncorrected agheader %d, skipping ag...\n"),
2437 goto out_free_agibuf
;
2440 scan_freelist(agf
, agcnts
);
2442 validate_agf(agf
, agno
, agcnts
);
2443 validate_agi(agi
, agno
, agcnts
);
2445 ASSERT(agi_dirty
== 0 || (agi_dirty
&& !no_modify
));
2446 ASSERT(agf_dirty
== 0 || (agf_dirty
&& !no_modify
));
2447 ASSERT(sb_dirty
== 0 || (sb_dirty
&& !no_modify
));
2450 * Only pay attention to CRC/verifier errors if we can correct them.
2451 * Note that we can get uncorrected EFSCORRUPTED errors here because
2452 * the verifier will flag on out of range values that we can't correct
2453 * until phase 5 when we have all the information necessary to rebuild
2454 * the freespace/inode btrees. We can correct bad CRC errors
2455 * immediately, though.
2458 agi_dirty
+= (agibuf
->b_error
== -EFSBADCRC
);
2459 agf_dirty
+= (agfbuf
->b_error
== -EFSBADCRC
);
2460 sb_dirty
+= (sbbuf
->b_error
== -EFSBADCRC
);
2463 if (agi_dirty
&& !no_modify
)
2464 libxfs_writebuf(agibuf
, 0);
2466 libxfs_putbuf(agibuf
);
2468 if (agf_dirty
&& !no_modify
)
2469 libxfs_writebuf(agfbuf
, 0);
2471 libxfs_putbuf(agfbuf
);
2473 if (sb_dirty
&& !no_modify
) {
2475 memcpy(&mp
->m_sb
, sb
, sizeof(xfs_sb_t
));
2476 libxfs_sb_to_disk(XFS_BUF_TO_SBP(sbbuf
), sb
);
2477 libxfs_writebuf(sbbuf
, 0);
2479 libxfs_putbuf(sbbuf
);
2481 PROG_RPT_INC(prog_rpt_done
[agno
], 1);
2483 #ifdef XR_INODE_TRACE
2484 print_inode_list(i
);
2489 libxfs_putbuf(agibuf
);
2491 libxfs_putbuf(agfbuf
);
2493 libxfs_putbuf(sbbuf
);
2498 do_error(_("can't get %s for ag %d\n"), objname
, agno
);
2501 #define SCAN_THREADS 32
2505 struct xfs_mount
*mp
,
2508 struct aghdr_cnts
*agcnts
;
2509 uint64_t fdblocks
= 0;
2510 uint64_t icount
= 0;
2511 uint64_t ifreecount
= 0;
2512 uint64_t usedblocks
= 0;
2514 struct workqueue wq
;
2516 agcnts
= malloc(mp
->m_sb
.sb_agcount
* sizeof(*agcnts
));
2518 do_abort(_("no memory for ag header counts\n"));
2521 memset(agcnts
, 0, mp
->m_sb
.sb_agcount
* sizeof(*agcnts
));
2523 create_work_queue(&wq
, mp
, scan_threads
);
2525 for (i
= 0; i
< mp
->m_sb
.sb_agcount
; i
++)
2526 queue_work(&wq
, scan_ag
, i
, &agcnts
[i
]);
2528 destroy_work_queue(&wq
);
2530 /* tally up the counts */
2531 for (i
= 0; i
< mp
->m_sb
.sb_agcount
; i
++) {
2532 fdblocks
+= agcnts
[i
].fdblocks
;
2533 icount
+= agcnts
[i
].agicount
;
2534 ifreecount
+= agcnts
[i
].ifreecount
;
2535 usedblocks
+= agcnts
[i
].usedblocks
;
2541 * Validate that our manual counts match the superblock.
2543 if (mp
->m_sb
.sb_icount
!= icount
) {
2544 do_warn(_("sb_icount %" PRIu64
", counted %" PRIu64
"\n"),
2545 mp
->m_sb
.sb_icount
, icount
);
2548 if (mp
->m_sb
.sb_ifree
!= ifreecount
) {
2549 do_warn(_("sb_ifree %" PRIu64
", counted %" PRIu64
"\n"),
2550 mp
->m_sb
.sb_ifree
, ifreecount
);
2553 if (mp
->m_sb
.sb_fdblocks
!= fdblocks
) {
2554 do_warn(_("sb_fdblocks %" PRIu64
", counted %" PRIu64
"\n"),
2555 mp
->m_sb
.sb_fdblocks
, fdblocks
);
2559 usedblocks
!= mp
->m_sb
.sb_dblocks
- fdblocks
) {
2560 do_warn(_("used blocks %" PRIu64
", counted %" PRIu64
"\n"),
2561 mp
->m_sb
.sb_dblocks
- fdblocks
, usedblocks
);