2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
39 #include "err_protos.h"
45 extern int verify_set_agheader(xfs_mount_t
*mp
, xfs_buf_t
*sbuf
, xfs_sb_t
*sb
,
46 xfs_agf_t
*agf
, xfs_agi_t
*agi
, xfs_agnumber_t i
);
48 static xfs_mount_t
*mp
= NULL
;
49 static xfs_extlen_t bno_agffreeblks
;
50 static xfs_extlen_t cnt_agffreeblks
;
51 static xfs_extlen_t bno_agflongest
;
52 static xfs_extlen_t cnt_agflongest
;
53 static xfs_agino_t agicount
;
54 static xfs_agino_t agifreecount
;
57 set_mp(xfs_mount_t
*mpp
)
68 void (*func
)(xfs_btree_sblock_t
*block
,
78 bp
= libxfs_readbuf(mp
->m_dev
, XFS_AGB_TO_DADDR(mp
, agno
, root
),
79 XFS_FSB_TO_BB(mp
, 1), 0);
81 do_error("can't read btree block %d/%d\n", agno
, root
);
84 (*func
)((xfs_btree_sblock_t
*)XFS_BUF_PTR(bp
),
85 nlevels
- 1, root
, agno
, suspect
, isroot
);
90 * returns 1 on bad news (inode needs to be cleared), 0 on good
96 int (*func
)(xfs_btree_lblock_t
*block
,
105 bmap_cursor_t
*bm_cursor
,
115 bmap_cursor_t
*bm_cursor
,
123 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, root
),
124 XFS_FSB_TO_BB(mp
, 1), 0);
126 do_error("can't read btree block %d/%d\n",
127 XFS_FSB_TO_AGNO(mp
, root
),
128 XFS_FSB_TO_AGBNO(mp
, root
));
131 err
= (*func
)((xfs_btree_lblock_t
*)XFS_BUF_PTR(bp
), nlevels
- 1,
132 type
, whichfork
, root
, ino
, tot
, nex
, blkmapp
,
133 bm_cursor
, isroot
, check_dups
, &dirty
);
135 ASSERT(dirty
== 0 || (dirty
&& !no_modify
));
137 if (dirty
&& !no_modify
)
138 libxfs_writebuf(bp
, 0);
147 xfs_btree_lblock_t
*ablock
,
156 bmap_cursor_t
*bm_cursor
,
161 xfs_bmbt_block_t
*block
= (xfs_bmbt_block_t
*)ablock
;
165 xfs_bmbt_key_t
*pkey
;
166 xfs_bmbt_rec_32_t
*rp
;
167 xfs_dfiloff_t first_key
;
168 xfs_dfiloff_t last_key
;
171 if (whichfork
== XFS_DATA_FORK
)
177 * unlike the ag freeblock btrees, if anything looks wrong
178 * in an inode bmap tree, just bail. it's possible that
179 * we'll miss a case where the to-be-toasted inode and
180 * another inode are claiming the same block but that's
183 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_BMAP_MAGIC
) {
185 "bad magic # %#x in inode %llu (%s fork) bmbt block %llu\n",
186 INT_GET(block
->bb_magic
, ARCH_CONVERT
), ino
, forkname
, bno
);
189 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
191 "expected level %d got %d in inode %llu, (%s fork) bmbt block %llu\n",
192 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), ino
, forkname
, bno
);
196 if (check_dups
== 0) {
198 * check sibling pointers. if bad we have a conflict
199 * between the sibling pointers and the child pointers
200 * in the parent block. blow out the inode if that happens
202 if (bm_cursor
->level
[level
].fsbno
!= NULLDFSBNO
) {
204 * this is not the first block on this level
205 * so the cursor for this level has recorded the
206 * values for this's block left-sibling.
208 if (bno
!= bm_cursor
->level
[level
].right_fsbno
) {
210 "bad fwd (right) sibling pointer (saw %llu parent block says %llu)\n",
211 bm_cursor
->level
[level
].right_fsbno
,
214 "\tin inode %llu (%s fork) bmap btree block %llu\n",
216 bm_cursor
->level
[level
].fsbno
);
219 if (INT_GET(block
->bb_leftsib
, ARCH_CONVERT
) !=
220 bm_cursor
->level
[level
].fsbno
) {
222 "bad back (left) sibling pointer (saw %llu parent block says %llu)\n",
223 INT_GET(block
->bb_leftsib
, ARCH_CONVERT
),
224 bm_cursor
->level
[level
].fsbno
);
226 "\tin inode %llu (%s fork) bmap btree block %llu\n",
232 * This is the first or only block on this level.
233 * Check that the left sibling pointer is NULL
235 if (INT_GET(block
->bb_leftsib
, ARCH_CONVERT
) !=
238 "bad back (left) sibling pointer (saw %llu should be NULL (0))\n",
239 INT_GET(block
->bb_leftsib
, ARCH_CONVERT
));
241 "\tin inode %llu (%s fork) bmap btree block %llu\n",
248 * update cursor block pointers to reflect this block
250 bm_cursor
->level
[level
].fsbno
= bno
;
251 bm_cursor
->level
[level
].left_fsbno
= INT_GET(block
->bb_leftsib
, ARCH_CONVERT
);
252 bm_cursor
->level
[level
].right_fsbno
= INT_GET(block
->bb_rightsib
, ARCH_CONVERT
);
254 switch (get_fsbno_state(mp
, bno
)) {
258 set_fsbno_state(mp
, bno
, XR_E_INUSE
);
263 * we'll try and continue searching here since
264 * the block looks like it's been claimed by file
265 * to store user data, a directory to store directory
266 * data, or the space allocation btrees but since
267 * we made it here, the block probably
268 * contains btree data.
270 set_fsbno_state(mp
, bno
, XR_E_MULT
);
272 "inode 0x%llx bmap block 0x%llx claimed, state is %d\n",
273 ino
, (__uint64_t
) bno
,
274 get_fsbno_state(mp
, bno
));
278 set_fsbno_state(mp
, bno
, XR_E_MULT
);
280 "inode 0x%llx bmap block 0x%llx claimed, state is %d\n",
281 ino
, (__uint64_t
) bno
,
282 get_fsbno_state(mp
, bno
));
284 * if we made it to here, this is probably a bmap block
285 * that is being used by *another* file as a bmap block
286 * so the block will be valid. Both files should be
287 * trashed along with any other file that impinges on
288 * any blocks referenced by either file. So we
289 * continue searching down this btree to mark all
296 "bad state %d, inode 0x%llx bmap block 0x%llx\n",
297 get_fsbno_state(mp
, bno
),
298 ino
, (__uint64_t
) bno
);
303 * attribute fork for realtime files is in the regular
306 if (type
!= XR_INO_RTDATA
|| whichfork
!= XFS_DATA_FORK
) {
307 if (search_dup_extent(mp
, XFS_FSB_TO_AGNO(mp
, bno
),
308 XFS_FSB_TO_AGBNO(mp
, bno
)))
311 if (search_rt_dup_extent(mp
, bno
))
317 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_bmap_dmxr
[0] ||
318 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_bmap_dmnr
[0])) {
319 do_warn("inode 0x%llx bad # of bmap records (%u, min - %u, max - %u)\n",
320 ino
, INT_GET(block
->bb_numrecs
, ARCH_CONVERT
),
321 mp
->m_bmap_dmnr
[0], mp
->m_bmap_dmxr
[0]);
324 rp
= (xfs_bmbt_rec_32_t
*)
325 XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_bmbt
,
326 block
, 1, mp
->m_bmap_dmxr
[0]);
327 *nex
+= INT_GET(block
->bb_numrecs
, ARCH_CONVERT
);
329 * XXX - if we were going to fix up the btree record,
330 * we'd do it right here. For now, if there's a problem,
331 * we'll bail out and presumably clear the inode.
333 if (check_dups
== 0) {
334 err
= process_bmbt_reclist(mp
, rp
, INT_GET(block
->bb_numrecs
, ARCH_CONVERT
),
335 type
, ino
, tot
, blkmapp
,
336 &first_key
, &last_key
,
341 * check that key ordering is monotonically increasing.
342 * if the last_key value in the cursor is set to
343 * NULLDFILOFF, then we know this is the first block
344 * on the leaf level and we shouldn't check the
347 if (first_key
<= bm_cursor
->level
[level
].last_key
&&
348 bm_cursor
->level
[level
].last_key
!=
351 "out-of-order bmap key (file offset) in inode %llu, %s fork, fsbno %llu\n",
356 * update cursor keys to reflect this block.
357 * don't have to check if last_key is > first_key
358 * since that gets checked by process_bmbt_reclist.
360 bm_cursor
->level
[level
].first_key
= first_key
;
361 bm_cursor
->level
[level
].last_key
= last_key
;
365 return(scan_bmbt_reclist(mp
, rp
, INT_GET(block
->bb_numrecs
, ARCH_CONVERT
),
366 type
, ino
, tot
, whichfork
));
368 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_bmap_dmxr
[1] ||
369 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_bmap_dmnr
[1])) {
370 do_warn("inode 0x%llx bad # of bmap records (%u, min - %u, max - %u)\n",
371 ino
, INT_GET(block
->bb_numrecs
, ARCH_CONVERT
),
372 mp
->m_bmap_dmnr
[1], mp
->m_bmap_dmxr
[1]);
375 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_bmbt
, block
, 1,
377 pkey
= XFS_BTREE_KEY_ADDR(mp
->m_sb
.sb_blocksize
, xfs_bmbt
, block
, 1,
380 last_key
= NULLDFILOFF
;
382 for (i
= 0, err
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++) {
384 * XXX - if we were going to fix up the interior btree nodes,
385 * we'd do it right here. For now, if there's a problem,
386 * we'll bail out and presumably clear the inode.
388 if (!verify_dfsbno(mp
, INT_GET(pp
[i
], ARCH_CONVERT
))) {
389 do_warn("bad bmap btree ptr 0x%llx in ino %llu\n",
390 INT_GET(pp
[i
], ARCH_CONVERT
), ino
);
394 err
= scan_lbtree(INT_GET(pp
[i
], ARCH_CONVERT
), level
, scanfunc_bmap
, type
, whichfork
,
395 ino
, tot
, nex
, blkmapp
, bm_cursor
, 0,
401 * fix key (offset) mismatches between the first key
402 * in the child block (as recorded in the cursor) and the
403 * key in the interior node referencing the child block.
405 * fixes cases where entries have been shifted between
406 * child blocks but the parent hasn't been updated. We
407 * don't have to worry about the key values in the cursor
408 * not being set since we only look at the key values of
409 * our child and those are guaranteed to be set by the
410 * call to scan_lbtree() above.
412 if (check_dups
== 0 && INT_GET(pkey
[i
].br_startoff
, ARCH_CONVERT
) !=
413 bm_cursor
->level
[level
-1].first_key
) {
416 "correcting bt key (was %llu, now %llu) in inode %llu\n",
417 INT_GET(pkey
[i
].br_startoff
, ARCH_CONVERT
),
418 bm_cursor
->level
[level
-1].first_key
,
420 do_warn("\t\t%s fork, btree block %llu\n",
423 INT_SET(pkey
[i
].br_startoff
, ARCH_CONVERT
, bm_cursor
->level
[level
-1].first_key
);
426 "bad btree key (is %llu, should be %llu) in inode %llu\n",
427 INT_GET(pkey
[i
].br_startoff
, ARCH_CONVERT
),
428 bm_cursor
->level
[level
-1].first_key
,
430 do_warn("\t\t%s fork, btree block %llu\n",
437 * Check that the last child block's forward sibling pointer
440 if (check_dups
== 0 &&
441 bm_cursor
->level
[level
- 1].right_fsbno
!= NULLDFSBNO
) {
443 "bad fwd (right) sibling pointer (saw %llu should be NULLDFSBNO)\n",
444 bm_cursor
->level
[level
- 1].right_fsbno
);
446 "\tin inode %llu (%s fork) bmap btree block %llu\n",
448 bm_cursor
->level
[level
].fsbno
);
453 * update cursor keys to reflect this block
455 if (check_dups
== 0) {
456 bm_cursor
->level
[level
].first_key
=
457 INT_GET(pkey
[0].br_startoff
, ARCH_CONVERT
);
458 i
= INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) - 1;
459 bm_cursor
->level
[level
].last_key
=
460 INT_GET(pkey
[i
].br_startoff
, ARCH_CONVERT
);
468 xfs_btree_sblock_t
*ablock
,
477 xfs_alloc_block_t
*block
= (xfs_alloc_block_t
*)ablock
;
485 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_ABTB_MAGIC
) {
486 do_warn("bad magic # %#x in btbno block %d/%d\n",
487 INT_GET(block
->bb_magic
, ARCH_CONVERT
), agno
, bno
);
492 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
493 do_warn("expected level %d got %d in btbno block %d/%d\n",
494 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), agno
, bno
);
501 * check for btree blocks multiply claimed
503 state
= get_agbno_state(mp
, agno
, bno
);
507 set_agbno_state(mp
, agno
, bno
, XR_E_FS_MAP
);
510 set_agbno_state(mp
, agno
, bno
, XR_E_MULT
);
512 "bno freespace btree block claimed (state %d), agno %d, bno %d, suspect %d\n",
513 state
, agno
, bno
, suspect
);
518 numrecs
= INT_GET(block
->bb_numrecs
, ARCH_CONVERT
);
520 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[0]) {
521 numrecs
= mp
->m_alloc_mxr
[0];
524 if (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[0]) {
525 numrecs
= mp
->m_alloc_mnr
[0];
532 rp
= XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
,
533 1, mp
->m_alloc_mxr
[0]);
534 for (i
= 0; i
< numrecs
; i
++) {
535 if (INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
) == 0 ||
536 INT_GET(rp
[i
].ar_startblock
, ARCH_CONVERT
) == 0 ||
537 !verify_agbno(mp
, agno
, INT_GET(rp
[i
].ar_startblock
, ARCH_CONVERT
)) ||
538 INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
) > MAXEXTLEN
)
541 bno_agffreeblks
+= INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
);
542 if (INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
) > bno_agflongest
)
543 bno_agflongest
= INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
);
544 for (b
= INT_GET(rp
[i
].ar_startblock
, ARCH_CONVERT
);
545 b
< INT_GET(rp
[i
].ar_startblock
, ARCH_CONVERT
) + INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
);
547 if (get_agbno_state(mp
, agno
, b
)
549 set_agbno_state(mp
, agno
, b
,
552 do_warn("block (%d,%d) multiply claimed by bno space tree, state - %d\n",
553 agno
, b
, get_agbno_state(mp
, agno
, b
));
563 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
, 1,
566 numrecs
= INT_GET(block
->bb_numrecs
, ARCH_CONVERT
);
567 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[1]) {
568 numrecs
= mp
->m_alloc_mxr
[1];
571 if (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[1]) {
572 numrecs
= mp
->m_alloc_mnr
[1];
577 * don't pass bogus tree flag down further if this block
578 * looked ok. bail out if two levels in a row look bad.
581 if (suspect
&& !hdr_errors
)
590 for (i
= 0; i
< numrecs
; i
++) {
592 * XXX - put sibling detection right here.
593 * we know our sibling chain is good. So as we go,
594 * we check the entry before and after each entry.
595 * If either of the entries references a different block,
596 * check the sibling pointer. If there's a sibling
597 * pointer mismatch, try and extract as much data
600 if (INT_GET(pp
[i
], ARCH_CONVERT
) != 0 && verify_agbno(mp
, agno
, INT_GET(pp
[i
], ARCH_CONVERT
)))
601 scan_sbtree(INT_GET(pp
[i
], ARCH_CONVERT
), level
, agno
, suspect
,
608 xfs_btree_sblock_t
*ablock
,
616 xfs_alloc_block_t
*block
;
625 block
= (xfs_alloc_block_t
*)ablock
;
628 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_ABTC_MAGIC
) {
629 do_warn("bad magic # %#x in btcnt block %d/%d\n",
630 INT_GET(block
->bb_magic
, ARCH_CONVERT
), agno
, bno
);
635 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
636 do_warn("expected level %d got %d in btcnt block %d/%d\n",
637 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), agno
, bno
);
644 * check for btree blocks multiply claimed
646 state
= get_agbno_state(mp
, agno
, bno
);
650 set_agbno_state(mp
, agno
, bno
, XR_E_FS_MAP
);
653 set_agbno_state(mp
, agno
, bno
, XR_E_MULT
);
655 "bcnt freespace btree block claimed (state %d), agno %d, bno %d, suspect %d\n",
656 state
, agno
, bno
, suspect
);
661 numrecs
= INT_GET(block
->bb_numrecs
, ARCH_CONVERT
);
663 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[0]) {
664 numrecs
= mp
->m_alloc_mxr
[0];
667 if (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[0]) {
668 numrecs
= mp
->m_alloc_mnr
[0];
675 rp
= XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
,
676 1, mp
->m_alloc_mxr
[0]);
677 for (i
= 0; i
< numrecs
; i
++) {
678 if (INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
) == 0 ||
679 INT_GET(rp
[i
].ar_startblock
, ARCH_CONVERT
) == 0 ||
680 !verify_agbno(mp
, agno
, INT_GET(rp
[i
].ar_startblock
, ARCH_CONVERT
)) ||
681 INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
) > MAXEXTLEN
)
684 cnt_agffreeblks
+= INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
);
685 if (INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
) > cnt_agflongest
)
686 cnt_agflongest
= INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
);
687 for (b
= INT_GET(rp
[i
].ar_startblock
, ARCH_CONVERT
);
688 b
< INT_GET(rp
[i
].ar_startblock
, ARCH_CONVERT
) + INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
);
690 state
= get_agbno_state(mp
, agno
, b
);
692 * no warning messages -- we'll catch
697 set_agbno_state(mp
, agno
, b
, XR_E_FREE
);
700 set_agbno_state(mp
, agno
, b
,
705 "block (%d,%d) already used, state %d\n",
717 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
, 1,
720 numrecs
= INT_GET(block
->bb_numrecs
, ARCH_CONVERT
);
721 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[1]) {
722 numrecs
= mp
->m_alloc_mxr
[1];
725 if (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[1]) {
726 numrecs
= mp
->m_alloc_mnr
[1];
731 * don't pass bogus tree flag down further if this block
732 * looked ok. bail out if two levels in a row look bad.
735 if (suspect
&& !hdr_errors
)
744 for (i
= 0; i
< numrecs
; i
++)
745 if (INT_GET(pp
[i
], ARCH_CONVERT
) != 0 && verify_agbno(mp
, agno
, INT_GET(pp
[i
], ARCH_CONVERT
)))
746 scan_sbtree(INT_GET(pp
[i
], ARCH_CONVERT
), level
, agno
,
747 suspect
, scanfunc_cnt
, 0);
751 * this one walks the inode btrees sucking the info there into
752 * the incore avl tree. We try and rescue corrupted btree records
753 * to minimize our chances of losing inodes. Inode info from potentially
754 * corrupt sources could be bogus so rather than put the info straight
755 * into the tree, instead we put it on a list and try and verify the
756 * info in the next phase by examining what's on disk. At that point,
757 * we'll be able to figure out what's what and stick the corrected info
758 * into the tree. We do bail out at some point and give up on a subtree
759 * so as to avoid walking randomly all over the ag.
761 * Note that it's also ok if the free/inuse info wrong, we can correct
762 * that when we examine the on-disk inode. The important thing is to
763 * get the start and alignment of the inode chunks right. Those chunks
764 * that we aren't sure about go into the uncertain list.
768 xfs_btree_sblock_t
*ablock
,
777 xfs_inobt_block_t
*block
;
788 ino_tree_node_t
*ino_rec
, *first_rec
, *last_rec
;
791 block
= (xfs_inobt_block_t
*)ablock
;
794 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_IBT_MAGIC
) {
795 do_warn("bad magic # %#x in inobt block %d/%d\n",
796 INT_GET(block
->bb_magic
, ARCH_CONVERT
), agno
, bno
);
802 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
803 do_warn("expected level %d got %d in inobt block %d/%d\n",
804 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), agno
, bno
);
812 * check for btree blocks multiply claimed, any unknown/free state
813 * is ok in the bitmap block.
815 state
= get_agbno_state(mp
, agno
, bno
);
821 set_agbno_state(mp
, agno
, bno
, XR_E_FS_MAP
);
824 set_agbno_state(mp
, agno
, bno
, XR_E_MULT
);
826 "inode btree block claimed (state %d), agno %d, bno %d, suspect %d\n",
827 state
, agno
, bno
, suspect
);
830 numrecs
= INT_GET(block
->bb_numrecs
, ARCH_CONVERT
);
833 * leaf record in btree
836 /* check for trashed btree block */
838 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_inobt_mxr
[0]) {
839 numrecs
= mp
->m_inobt_mxr
[0];
842 if (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_inobt_mnr
[0]) {
843 numrecs
= mp
->m_inobt_mnr
[0];
849 do_warn("dubious inode btree block header %d/%d\n",
854 rp
= XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_inobt
, block
,
855 1, mp
->m_inobt_mxr
[0]);
858 * step through the records, each record points to
859 * a chunk of inodes. The start of inode chunks should
860 * be block-aligned. Each inode btree rec should point
861 * to the start of a block of inodes or the start of a group
862 * of INODES_PER_CHUNK (64) inodes. off is the offset into
863 * the block. skip processing of bogus records.
865 for (i
= 0; i
< numrecs
; i
++) {
866 ino
= INT_GET(rp
[i
].ir_startino
, ARCH_CONVERT
);
867 off
= XFS_AGINO_TO_OFFSET(mp
, ino
);
868 agbno
= XFS_AGINO_TO_AGBNO(mp
, ino
);
869 lino
= XFS_AGINO_TO_INO(mp
, agno
, ino
);
871 * on multi-block block chunks, all chunks start
872 * at the beginning of the block. with multi-chunk
873 * blocks, all chunks must start on 64-inode boundaries
874 * since each block can hold N complete chunks. if
875 * fs has aligned inodes, all chunks must start
876 * at a fs_ino_alignment*N'th agbno. skip recs
877 * with badly aligned starting inodes.
880 (inodes_per_block
<= XFS_INODES_PER_CHUNK
&&
882 (inodes_per_block
> XFS_INODES_PER_CHUNK
&&
883 off
% XFS_INODES_PER_CHUNK
!= 0) ||
884 (fs_aligned_inodes
&&
885 agbno
% fs_ino_alignment
!= 0)) {
887 "badly aligned inode rec (starting inode = %llu)\n",
893 * verify numeric validity of inode chunk first
894 * before inserting into a tree. don't have to
895 * worry about the overflow case because the
896 * starting ino number of a chunk can only get
897 * within 255 inodes of max (NULLAGINO). if it
898 * gets closer, the agino number will be illegal
899 * as the agbno will be too large.
901 if (verify_aginum(mp
, agno
, ino
)) {
903 "bad starting inode # (%llu (0x%x 0x%x)) in ino rec, skipping rec\n",
909 if (verify_aginum(mp
, agno
,
910 ino
+ XFS_INODES_PER_CHUNK
- 1)) {
912 "bad ending inode # (%llu (0x%x 0x%x)) in ino rec, skipping rec\n",
913 lino
+ XFS_INODES_PER_CHUNK
- 1,
914 agno
, ino
+ XFS_INODES_PER_CHUNK
- 1);
920 * set state of each block containing inodes
922 if (off
== 0 && !suspect
) {
924 j
< XFS_INODES_PER_CHUNK
;
925 j
+= mp
->m_sb
.sb_inopblock
) {
926 agbno
= XFS_AGINO_TO_AGBNO(mp
, ino
+ j
);
927 state
= get_agbno_state(mp
,
930 if (state
== XR_E_UNKNOWN
) {
931 set_agbno_state(mp
, agno
,
933 } else if (state
== XR_E_INUSE_FS
&&
935 ino
+ j
>= first_prealloc_ino
&&
936 ino
+ j
< last_prealloc_ino
) {
937 set_agbno_state(mp
, agno
,
941 "inode chunk claims used block, inobt block - agno %d, bno %d, inopb %d\n",
943 mp
->m_sb
.sb_inopblock
);
946 * XXX - maybe should mark
954 * ensure only one avl entry per chunk
956 find_inode_rec_range(agno
, ino
,
957 ino
+ XFS_INODES_PER_CHUNK
,
960 if (first_rec
!= NULL
) {
962 * this chunk overlaps with one (or more)
963 * already in the tree
966 "inode rec for ino %llu (%d/%d) overlaps existing rec (start %d/%d)\n",
968 agno
, first_rec
->ino_startnum
);
972 * if the 2 chunks start at the same place,
973 * then we don't have to put this one
974 * in the uncertain list. go to the next one.
976 if (first_rec
->ino_startnum
== ino
)
980 agicount
+= XFS_INODES_PER_CHUNK
;
981 agifreecount
+= INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
);
985 * now mark all the inodes as existing and free or used.
986 * if the tree is suspect, put them into the uncertain
990 if (XFS_INOBT_IS_FREE(&rp
[i
], 0, ARCH_CONVERT
)) {
992 ino_rec
= set_inode_free_alloc(agno
,
995 ino_rec
= set_inode_used_alloc(agno
,
998 for (j
= 1; j
< XFS_INODES_PER_CHUNK
; j
++) {
999 if (XFS_INOBT_IS_FREE(&rp
[i
], j
, ARCH_CONVERT
)) {
1001 set_inode_free(ino_rec
, j
);
1003 set_inode_used(ino_rec
, j
);
1007 for (j
= 0; j
< XFS_INODES_PER_CHUNK
; j
++) {
1008 if (XFS_INOBT_IS_FREE(&rp
[i
], j
, ARCH_CONVERT
)) {
1010 add_aginode_uncertain(agno
,
1013 add_aginode_uncertain(agno
,
1019 if (nfree
!= INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
)) {
1020 do_warn( "ir_freecount/free mismatch, inode chunk \
1021 %d/%d, freecount %d nfree %d\n",
1022 agno
, ino
, INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
), nfree
);
1033 * interior record, continue on
1035 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_inobt_mxr
[1]) {
1036 numrecs
= mp
->m_inobt_mxr
[1];
1039 if (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_inobt_mnr
[1]) {
1040 numrecs
= mp
->m_inobt_mnr
[1];
1044 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_inobt
, block
, 1,
1045 mp
->m_inobt_mxr
[1]);
1048 * don't pass bogus tree flag down further if this block
1049 * looked ok. bail out if two levels in a row look bad.
1052 if (suspect
&& !hdr_errors
)
1062 for (i
= 0; i
< numrecs
; i
++) {
1063 if (INT_GET(pp
[i
], ARCH_CONVERT
) != 0 && verify_agbno(mp
, agno
, INT_GET(pp
[i
], ARCH_CONVERT
)))
1064 scan_sbtree(INT_GET(pp
[i
], ARCH_CONVERT
), level
, agno
, suspect
,
1079 if (XFS_SB_BLOCK(mp
) != XFS_AGFL_BLOCK(mp
) &&
1080 XFS_AGF_BLOCK(mp
) != XFS_AGFL_BLOCK(mp
) &&
1081 XFS_AGI_BLOCK(mp
) != XFS_AGFL_BLOCK(mp
))
1082 set_agbno_state(mp
, INT_GET(agf
->agf_seqno
, ARCH_CONVERT
),
1083 XFS_AGFL_BLOCK(mp
), XR_E_FS_MAP
);
1084 if (INT_GET(agf
->agf_flcount
, ARCH_CONVERT
) == 0)
1086 agflbuf
= libxfs_readbuf(mp
->m_dev
,
1087 XFS_AG_DADDR(mp
, INT_GET(agf
->agf_seqno
, ARCH_CONVERT
),
1088 XFS_AGFL_DADDR
), 1, 0);
1090 do_abort("can't read agfl block for ag %d\n",
1091 INT_GET(agf
->agf_seqno
, ARCH_CONVERT
));
1094 agfl
= XFS_BUF_TO_AGFL(agflbuf
);
1095 i
= INT_GET(agf
->agf_flfirst
, ARCH_CONVERT
);
1098 bno
= INT_GET(agfl
->agfl_bno
[i
], ARCH_CONVERT
);
1099 if (verify_agbno(mp
, INT_GET(agf
->agf_seqno
,ARCH_CONVERT
), bno
))
1101 INT_GET(agf
->agf_seqno
, ARCH_CONVERT
),
1104 do_warn("bad agbno %u in agfl, agno %d\n",
1105 bno
, INT_GET(agf
->agf_seqno
, ARCH_CONVERT
));
1107 if (i
== INT_GET(agf
->agf_fllast
, ARCH_CONVERT
))
1109 if (++i
== XFS_AGFL_SIZE
)
1112 if (count
!= INT_GET(agf
->agf_flcount
, ARCH_CONVERT
)) {
1113 do_warn("freeblk count %d != flcount %d in ag %d\n", count
,
1114 INT_GET(agf
->agf_flcount
, ARCH_CONVERT
),
1115 INT_GET(agf
->agf_seqno
, ARCH_CONVERT
));
1117 libxfs_putbuf(agflbuf
);
1122 xfs_agnumber_t agno
)
1135 cnt_agffreeblks
= cnt_agflongest
= 0;
1136 bno_agffreeblks
= bno_agflongest
= 0;
1138 agi_dirty
= agf_dirty
= sb_dirty
= 0;
1140 agicount
= agifreecount
= 0;
1142 sbbuf
= libxfs_readbuf(mp
->m_dev
, XFS_AG_DADDR(mp
, agno
, XFS_SB_DADDR
),
1145 do_error("can't get root superblock for ag %d\n", agno
);
1149 sb
= (xfs_sb_t
*)calloc(BBSIZE
, 1);
1151 do_error("can't allocate memory for superblock\n");
1152 libxfs_putbuf(sbbuf
);
1155 libxfs_xlate_sb(XFS_BUF_TO_SBP(sbbuf
), sb
, 1, ARCH_CONVERT
,
1158 agfbuf
= libxfs_readbuf(mp
->m_dev
,
1159 XFS_AG_DADDR(mp
, agno
, XFS_AGF_DADDR
), 1, 0);
1161 do_error("can't read agf block for ag %d\n", agno
);
1162 libxfs_putbuf(sbbuf
);
1166 agf
= XFS_BUF_TO_AGF(agfbuf
);
1168 agibuf
= libxfs_readbuf(mp
->m_dev
,
1169 XFS_AG_DADDR(mp
, agno
, XFS_AGI_DADDR
), 1, 0);
1171 do_error("can't read agi block for ag %d\n", agno
);
1172 libxfs_putbuf(agfbuf
);
1173 libxfs_putbuf(sbbuf
);
1177 agi
= XFS_BUF_TO_AGI(agibuf
);
1179 /* fix up bad ag headers */
1181 status
= verify_set_agheader(mp
, sbbuf
, sb
, agf
, agi
, agno
);
1183 if (status
& XR_AG_SB_SEC
) {
1187 * clear bad sector bit because we don't want
1188 * to skip further processing. we just want to
1189 * ensure that we write out the modified sb buffer.
1191 status
&= ~XR_AG_SB_SEC
;
1193 if (status
& XR_AG_SB
) {
1199 do_warn("reset bad sb for ag %d\n", agno
);
1201 if (status
& XR_AG_AGF
) {
1207 do_warn("reset bad agf for ag %d\n", agno
);
1209 if (status
& XR_AG_AGI
) {
1215 do_warn("reset bad agi for ag %d\n", agno
);
1218 if (status
&& no_modify
) {
1219 libxfs_putbuf(agibuf
);
1220 libxfs_putbuf(agfbuf
);
1221 libxfs_putbuf(sbbuf
);
1224 do_warn("bad uncorrected agheader %d, skipping ag...\n", agno
);
1231 if (INT_GET(agf
->agf_roots
[XFS_BTNUM_BNO
], ARCH_CONVERT
) != 0 &&
1232 verify_agbno(mp
, agno
, INT_GET(agf
->agf_roots
[XFS_BTNUM_BNO
], ARCH_CONVERT
)))
1233 scan_sbtree(INT_GET(agf
->agf_roots
[XFS_BTNUM_BNO
], ARCH_CONVERT
),
1234 INT_GET(agf
->agf_levels
[XFS_BTNUM_BNO
], ARCH_CONVERT
),
1235 agno
, 0, scanfunc_bno
, 1);
1237 do_warn("bad agbno %u for btbno root, agno %d\n",
1238 INT_GET(agf
->agf_roots
[XFS_BTNUM_BNO
], ARCH_CONVERT
), agno
);
1240 if (INT_GET(agf
->agf_roots
[XFS_BTNUM_CNT
], ARCH_CONVERT
) != 0 &&
1241 verify_agbno(mp
, agno
, INT_GET(agf
->agf_roots
[XFS_BTNUM_CNT
], ARCH_CONVERT
)))
1242 scan_sbtree(INT_GET(agf
->agf_roots
[XFS_BTNUM_CNT
], ARCH_CONVERT
),
1243 INT_GET(agf
->agf_levels
[XFS_BTNUM_CNT
], ARCH_CONVERT
),
1244 agno
, 0, scanfunc_cnt
, 1);
1246 do_warn("bad agbno %u for btbcnt root, agno %d\n",
1247 INT_GET(agf
->agf_roots
[XFS_BTNUM_CNT
], ARCH_CONVERT
), agno
);
1249 if (INT_GET(agi
->agi_root
, ARCH_CONVERT
) != 0 && verify_agbno(mp
, agno
, INT_GET(agi
->agi_root
, ARCH_CONVERT
)))
1250 scan_sbtree(INT_GET(agi
->agi_root
, ARCH_CONVERT
), INT_GET(agi
->agi_level
, ARCH_CONVERT
), agno
, 0,
1253 do_warn("bad agbno %u for inobt root, agno %d\n",
1254 INT_GET(agi
->agi_root
, ARCH_CONVERT
), agno
);
1256 ASSERT(agi_dirty
== 0 || (agi_dirty
&& !no_modify
));
1258 if (agi_dirty
&& !no_modify
)
1259 libxfs_writebuf(agibuf
, 0);
1261 libxfs_putbuf(agibuf
);
1263 ASSERT(agf_dirty
== 0 || (agf_dirty
&& !no_modify
));
1265 if (agf_dirty
&& !no_modify
)
1266 libxfs_writebuf(agfbuf
, 0);
1268 libxfs_putbuf(agfbuf
);
1270 ASSERT(sb_dirty
== 0 || (sb_dirty
&& !no_modify
));
1272 if (sb_dirty
&& !no_modify
) {
1273 libxfs_xlate_sb(XFS_BUF_PTR(sbbuf
), sb
, -1, ARCH_CONVERT
,
1275 libxfs_writebuf(sbbuf
, 0);
1277 libxfs_putbuf(sbbuf
);