2 * Copyright (c) 2000-2001 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 #include "attr_repair.h"
49 * inode clearing routines
53 * return the offset into the inode where the attribute fork starts
57 calc_attr_offset(xfs_mount_t
*mp
, xfs_dinode_t
*dino
)
59 xfs_dinode_core_t
*dinoc
= &dino
->di_core
;
60 int offset
= ((__psint_t
) &dino
->di_u
)
64 * don't worry about alignment when calculating offset
65 * because the data fork is already 8-byte aligned
67 switch (dinoc
->di_format
) {
68 case XFS_DINODE_FMT_DEV
:
69 offset
+= sizeof(dev_t
);
71 case XFS_DINODE_FMT_LOCAL
:
72 offset
+= INT_GET(dinoc
->di_size
, ARCH_CONVERT
);
74 case XFS_DINODE_FMT_UUID
:
75 offset
+= sizeof(uuid_t
);
77 case XFS_DINODE_FMT_EXTENTS
:
78 offset
+= INT_GET(dinoc
->di_nextents
, ARCH_CONVERT
) * sizeof(xfs_bmbt_rec_32_t
);
80 case XFS_DINODE_FMT_BTREE
:
81 offset
+= INT_GET(dino
->di_u
.di_bmbt
.bb_numrecs
, ARCH_CONVERT
) * sizeof(xfs_bmbt_rec_32_t
);
84 do_error("Unknown inode format.\n");
94 clear_dinode_attr(xfs_mount_t
*mp
, xfs_dinode_t
*dino
, xfs_ino_t ino_num
)
96 xfs_dinode_core_t
*dinoc
= &dino
->di_core
;
98 ASSERT(dinoc
->di_forkoff
!= 0);
101 fprintf(stderr
, "clearing inode %llu attributes \n",
102 (unsigned long long)ino_num
);
104 fprintf(stderr
, "would have cleared inode %llu attributes\n",
105 (unsigned long long)ino_num
);
107 if (INT_GET(dinoc
->di_anextents
, ARCH_CONVERT
) != 0) {
110 INT_ZERO(dinoc
->di_anextents
, ARCH_CONVERT
);
113 if (dinoc
->di_aformat
!= XFS_DINODE_FMT_EXTENTS
) {
116 dinoc
->di_aformat
= XFS_DINODE_FMT_EXTENTS
;
119 /* get rid of the fork by clearing forkoff */
121 /* Originally, when the attr repair code was added, the fork was cleared
122 * by turning it into shortform status. This meant clearing the
123 * hdr.totsize/count fields and also changing aformat to LOCAL
124 * (vs EXTENTS). Over various fixes, the aformat and forkoff have
125 * been updated to not show an attribute fork at all, however.
126 * It could be possible that resetting totsize/count are not needed,
127 * but just to be safe, leave it in for now.
131 xfs_attr_shortform_t
*asf
= (xfs_attr_shortform_t
*)
132 XFS_DFORK_APTR_ARCH(dino
, ARCH_CONVERT
);
133 INT_SET(asf
->hdr
.totsize
, ARCH_CONVERT
,
134 sizeof(xfs_attr_sf_hdr_t
));
135 INT_SET(asf
->hdr
.count
, ARCH_CONVERT
, 0);
136 dinoc
->di_forkoff
= 0; /* got to do this after asf is set */
140 * always returns 1 since the fork gets zapped
147 clear_dinode_core(xfs_dinode_core_t
*dinoc
, xfs_ino_t ino_num
)
151 if (INT_GET(dinoc
->di_magic
, ARCH_CONVERT
) != XFS_DINODE_MAGIC
) {
157 INT_SET(dinoc
->di_magic
, ARCH_CONVERT
, XFS_DINODE_MAGIC
);
160 if (!XFS_DINODE_GOOD_VERSION(dinoc
->di_version
) ||
161 (!fs_inode_nlink
&& dinoc
->di_version
> XFS_DINODE_VERSION_1
)) {
167 dinoc
->di_version
= (fs_inode_nlink
) ? XFS_DINODE_VERSION_2
168 : XFS_DINODE_VERSION_1
;
171 if (INT_GET(dinoc
->di_mode
, ARCH_CONVERT
) != 0) {
177 INT_ZERO(dinoc
->di_mode
, ARCH_CONVERT
);
180 if (INT_GET(dinoc
->di_flags
, ARCH_CONVERT
) != 0) {
186 INT_ZERO(dinoc
->di_flags
, ARCH_CONVERT
);
189 if (INT_GET(dinoc
->di_dmevmask
, ARCH_CONVERT
) != 0) {
195 INT_ZERO(dinoc
->di_dmevmask
, ARCH_CONVERT
);
198 if (dinoc
->di_forkoff
!= 0) {
204 dinoc
->di_forkoff
= 0;
207 if (dinoc
->di_format
!= XFS_DINODE_FMT_EXTENTS
) {
213 dinoc
->di_format
= XFS_DINODE_FMT_EXTENTS
;
216 if (dinoc
->di_aformat
!= XFS_DINODE_FMT_EXTENTS
) {
222 dinoc
->di_aformat
= XFS_DINODE_FMT_EXTENTS
;
225 if (INT_GET(dinoc
->di_size
, ARCH_CONVERT
) != 0) {
231 INT_ZERO(dinoc
->di_size
, ARCH_CONVERT
);
234 if (INT_GET(dinoc
->di_nblocks
, ARCH_CONVERT
) != 0) {
240 INT_ZERO(dinoc
->di_nblocks
, ARCH_CONVERT
);
243 if (INT_GET(dinoc
->di_onlink
, ARCH_CONVERT
) != 0) {
249 INT_ZERO(dinoc
->di_onlink
, ARCH_CONVERT
);
252 if (INT_GET(dinoc
->di_nextents
, ARCH_CONVERT
) != 0) {
258 INT_ZERO(dinoc
->di_nextents
, ARCH_CONVERT
);
261 if (INT_GET(dinoc
->di_anextents
, ARCH_CONVERT
) != 0) {
267 INT_ZERO(dinoc
->di_anextents
, ARCH_CONVERT
);
270 if (dinoc
->di_version
> XFS_DINODE_VERSION_1
&&
271 INT_GET(dinoc
->di_nlink
, ARCH_CONVERT
) != 0) {
277 INT_ZERO(dinoc
->di_nlink
, ARCH_CONVERT
);
285 clear_dinode_unlinked(xfs_mount_t
*mp
, xfs_dinode_t
*dino
)
288 if (dino
->di_next_unlinked
!= NULLAGINO
) {
290 dino
->di_next_unlinked
= NULLAGINO
;
298 * this clears the unlinked list too so it should not be called
299 * until after the agi unlinked lists are walked in phase 3.
300 * returns > zero if the inode has been altered while being cleared
303 clear_dinode(xfs_mount_t
*mp
, xfs_dinode_t
*dino
, xfs_ino_t ino_num
)
307 dirty
= clear_dinode_core(&dino
->di_core
, ino_num
);
308 dirty
+= clear_dinode_unlinked(mp
, dino
);
310 /* and clear the forks */
312 if (dirty
&& !no_modify
)
313 bzero(&dino
->di_u
, XFS_LITINO(mp
));
320 * misc. inode-related utility routines
324 * returns 0 if inode number is valid, 1 if bogus
327 verify_inum(xfs_mount_t
*mp
,
333 xfs_sb_t
*sbp
= &mp
->m_sb
;;
335 /* range check ag #, ag block. range-checking offset is pointless */
337 agno
= XFS_INO_TO_AGNO(mp
, ino
);
338 agino
= XFS_INO_TO_AGINO(mp
, ino
);
339 agbno
= XFS_AGINO_TO_AGBNO(mp
, agino
);
341 if (ino
== 0 || ino
== NULLFSINO
)
344 if (ino
!= XFS_AGINO_TO_INO(mp
, agno
, agino
))
347 if (agno
>= sbp
->sb_agcount
||
348 (agno
< sbp
->sb_agcount
&& agbno
>= sbp
->sb_agblocks
) ||
349 (agno
== sbp
->sb_agcount
&& agbno
>= sbp
->sb_dblocks
-
350 (sbp
->sb_agcount
-1) * sbp
->sb_agblocks
) ||
358 * have a separate routine to ensure that we don't accidentally
359 * lose illegally set bits in the agino by turning it into an FSINO
360 * to feed to the above routine
363 verify_aginum(xfs_mount_t
*mp
,
368 xfs_sb_t
*sbp
= &mp
->m_sb
;;
370 /* range check ag #, ag block. range-checking offset is pointless */
372 if (agino
== 0 || agino
== NULLAGINO
)
376 * agino's can't be too close to NULLAGINO because the min blocksize
377 * is 9 bits and at most 1 bit of that gets used for the inode offset
378 * so if the agino gets shifted by the # of offset bits and compared
379 * to the legal agbno values, a bogus agino will be too large. there
380 * will be extra bits set at the top that shouldn't be set.
382 agbno
= XFS_AGINO_TO_AGBNO(mp
, agino
);
384 if (agno
>= sbp
->sb_agcount
||
385 (agno
< sbp
->sb_agcount
&& agbno
>= sbp
->sb_agblocks
) ||
386 (agno
== sbp
->sb_agcount
&& agbno
>= sbp
->sb_dblocks
-
387 (sbp
->sb_agcount
-1) * sbp
->sb_agblocks
) ||
395 * return 1 if block number is good, 0 if out of range
398 verify_dfsbno(xfs_mount_t
*mp
,
403 xfs_sb_t
*sbp
= &mp
->m_sb
;;
405 /* range check ag #, ag block. range-checking offset is pointless */
407 agno
= XFS_FSB_TO_AGNO(mp
, fsbno
);
408 agbno
= XFS_FSB_TO_AGBNO(mp
, fsbno
);
410 if (agno
>= sbp
->sb_agcount
||
411 (agno
< sbp
->sb_agcount
&& agbno
>= sbp
->sb_agblocks
) ||
412 (agno
== sbp
->sb_agcount
&& agbno
>= sbp
->sb_dblocks
-
413 (sbp
->sb_agcount
-1) * sbp
->sb_agblocks
))
420 verify_agbno(xfs_mount_t
*mp
,
424 xfs_sb_t
*sbp
= &mp
->m_sb
;;
426 /* range check ag #, ag block. range-checking offset is pointless */
428 if (agno
>= sbp
->sb_agcount
||
429 (agno
< sbp
->sb_agcount
&& agbno
>= sbp
->sb_agblocks
) ||
430 (agno
== sbp
->sb_agcount
&& agbno
>= sbp
->sb_dblocks
-
431 (sbp
->sb_agcount
-1) * sbp
->sb_agblocks
))
439 xfs_bmbt_rec_32_t
*rp
,
440 xfs_dfiloff_t
*op
, /* starting offset (blockno in file) */
441 xfs_dfsbno_t
*sp
, /* starting block (fs blockno) */
442 xfs_dfilblks_t
*cp
, /* blockcount */
443 int *fp
) /* extent flag */
445 xfs_bmbt_irec_t irec
, *s
= &irec
;
446 xfs_bmbt_rec_t rpcopy
, *p
= &rpcopy
;
448 memcpy(&rpcopy
, rp
, sizeof(rpcopy
));
449 /* Just use the extent parsing routine from the kernel */
450 libxfs_bmbt_get_all(p
, s
);
452 if (fs_has_extflgbit
) {
453 if (s
->br_state
== XFS_EXT_UNWRITTEN
) {
461 *op
= s
->br_startoff
;
462 *sp
= s
->br_startblock
;
463 *cp
= s
->br_blockcount
;
467 * return address of block fblock if it's within the range described
468 * by the extent list. Otherwise, returns a null address.
474 xfs_bmbt_rec_32_t
*rp
,
476 xfs_dfiloff_t fblock
)
480 xfs_dfiloff_t off_bno
;
484 for (i
= 0; i
< numrecs
; i
++, rp
++) {
485 convert_extent(rp
, &off_bno
, &start
, &cnt
, &flag
);
486 if (off_bno
>= fblock
&& off_bno
+ cnt
< fblock
)
487 return(start
+ fblock
- off_bno
);
494 * return 1 if inode should be cleared, 0 otherwise
495 * if check_dups should be set to 1, that implies that
496 * the primary purpose of this call is to see if the
497 * file overlaps with any duplicate extents (in the
498 * duplicate extent list).
502 process_bmbt_reclist_int(
504 xfs_bmbt_rec_32_t
*rp
,
510 xfs_dfiloff_t
*first_key
,
511 xfs_dfiloff_t
*last_key
,
517 xfs_dfilblks_t c
; /* count */
518 xfs_dfilblks_t cp
= 0; /* prev count */
519 xfs_dfsbno_t s
; /* start */
520 xfs_dfsbno_t sp
= 0; /* prev start */
521 xfs_dfiloff_t o
= 0; /* offset */
522 xfs_dfiloff_t op
= 0; /* prev offset */
527 int flag
; /* extent flag */
529 if (whichfork
== XFS_DATA_FORK
)
534 if (type
== XR_INO_RTDATA
)
539 for (i
= 0; i
< numrecs
; i
++, rp
++) {
540 convert_extent(rp
, &o
, &s
, &c
, &flag
);
542 *last_key
= *first_key
= o
;
545 if (i
> 0 && op
+ cp
> o
) {
547 "bmap rec out of order, inode %llu entry %d [o s c] [%llu %llu %llu], %d [%llu %llu %llu]\n",
548 ino
, i
, o
, s
, c
, i
-1, op
, sp
, cp
);
556 * check numeric validity of the extent
560 "zero length extent (off = %llu, fsbno = %llu) in ino %llu\n",
564 if (type
== XR_INO_RTDATA
) {
565 if (s
>= mp
->m_sb
.sb_rblocks
) {
567 "inode %llu - bad rt extent starting block number %llu, offset %llu\n",
571 if (s
+ c
- 1 >= mp
->m_sb
.sb_rblocks
) {
573 "inode %llu - bad rt extent last block number %llu, offset %llu\n",
579 "inode %llu - bad rt extent overflows - start %llu, end %llu, offset %llu\n",
580 ino
, s
, s
+ c
- 1, o
);
584 if (!verify_dfsbno(mp
, s
)) {
586 "inode %llu - bad extent starting block number %llu, offset %llu\n",
590 if (!verify_dfsbno(mp
, s
+ c
- 1)) {
592 "inode %llu - bad extent last block number %llu, offset %llu\n",
598 "inode %llu - bad extent overflows - start %llu, end %llu, offset %llu\n",
599 ino
, s
, s
+ c
- 1, o
);
602 if (o
>= fs_max_file_offset
) {
604 "inode %llu - extent offset too large - start %llu, count %llu, offset %llu\n",
611 * realtime file data fork
613 if (type
== XR_INO_RTDATA
&& whichfork
== XFS_DATA_FORK
) {
615 * XXX - verify that the blocks listed in the record
616 * are multiples of an extent
618 if (XFS_SB_VERSION_HASEXTFLGBIT(&mp
->m_sb
) == 0
619 && (s
% mp
->m_sb
.sb_rextsize
!= 0 ||
620 c
% mp
->m_sb
.sb_rextsize
!= 0)) {
622 "malformed rt inode extent [%llu %llu] (fs rtext size = %u)\n",
623 s
, c
, mp
->m_sb
.sb_rextsize
);
628 * XXX - set the appropriate number of extents
630 for (b
= s
; b
< s
+ c
; b
+= mp
->m_sb
.sb_rextsize
) {
631 ext
= (xfs_drtbno_t
) b
/ mp
->m_sb
.sb_rextsize
;
633 if (check_dups
== 1) {
634 if (search_rt_dup_extent(mp
, ext
)) {
636 "data fork in rt ino %llu claims dup rt extent, off - %llu, start - %llu, count %llu\n",
643 state
= get_rtbno_state(mp
, ext
);
647 /* XXX - turn this back on after we
648 run process_rtbitmap() in phase2
650 "%s fork in rt ino %llu claims free rt block %llu\n",
653 /* fall through ... */
655 set_rtbno_state(mp
, ext
, XR_E_INUSE
);
659 "bad state in rt block map %llu\n", ext
);
666 "%s fork in rt inode %llu found metadata block %llu in %s bmap\n",
667 forkname
, ino
, ext
, ftype
);
670 set_rtbno_state(mp
, ext
, XR_E_MULT
);
672 "%s fork in rt inode %llu claims used rt block %llu\n",
678 "illegal state %d in %s block map %llu\n",
684 * bump up the block counter
689 * skip rest of loop processing since that's
690 * all for regular file forks and attr forks
697 * regular file data fork or attribute fork
699 if (blkmapp
&& *blkmapp
)
700 blkmap_set_ext(blkmapp
, o
, s
, c
);
701 for (b
= s
; b
< s
+ c
; b
++) {
702 if (check_dups
== 1) {
704 * if we're just checking the bmap for dups,
705 * return if we find one, otherwise, continue
706 * checking each entry without setting the
709 if (search_dup_extent(mp
,
710 XFS_FSB_TO_AGNO(mp
, b
),
711 XFS_FSB_TO_AGBNO(mp
, b
))) {
713 "%s fork in ino %llu claims dup extent, off - %llu, start - %llu, cnt %llu\n",
714 forkname
, ino
, o
, s
, c
);
720 /* FIX FOR BUG 653709 -- EKN
721 * realtime attribute fork, should be valid block number
722 * in regular data space, not realtime partion.
724 if (type
== XR_INO_RTDATA
&& whichfork
== XFS_ATTR_FORK
) {
725 if (mp
->m_sb
.sb_agcount
< XFS_FSB_TO_AGNO(mp
, b
))
729 state
= get_fsbno_state(mp
, b
);
734 "%s fork in ino %llu claims free block %llu\n",
735 forkname
, ino
, (__uint64_t
) b
);
736 /* fall through ... */
738 set_fsbno_state(mp
, b
, XR_E_INUSE
);
741 do_error("bad state in block map %llu\n", b
);
748 "%s fork in inode %llu claims metadata block %llu\n",
749 forkname
, ino
, (__uint64_t
) b
);
753 set_fsbno_state(mp
, b
, XR_E_MULT
);
755 "%s fork in %s inode %llu claims used block %llu\n",
756 forkname
, ftype
, ino
, (__uint64_t
) b
);
759 do_error("illegal state %d in block map %llu\n",
771 * return 1 if inode should be cleared, 0 otherwise, sets block bitmap
775 process_bmbt_reclist(
777 xfs_bmbt_rec_32_t
*rp
,
783 xfs_dfiloff_t
*first_key
,
784 xfs_dfiloff_t
*last_key
,
787 return(process_bmbt_reclist_int(mp
, rp
, numrecs
, type
, ino
, tot
,
788 blkmapp
, first_key
, last_key
, 0,
793 * return 1 if inode should be cleared, 0 otherwise, does not set
799 xfs_bmbt_rec_32_t
*rp
,
806 xfs_dfiloff_t first_key
= 0;
807 xfs_dfiloff_t last_key
= 0;
809 return(process_bmbt_reclist_int(mp
, rp
, numrecs
, type
, ino
, tot
,
810 NULL
, &first_key
, &last_key
, 1,
815 * these two are meant for routines that read and work with inodes
816 * one at a time where the inodes may be in any order (like walking
817 * the unlinked lists to look for inodes). the caller is responsible
818 * for writing/releasing the buffer.
821 get_agino_buf(xfs_mount_t
*mp
,
826 ino_tree_node_t
*irec
;
830 if ((irec
= find_inode_rec(agno
, agino
)) == NULL
)
833 size
= XFS_FSB_TO_BB(mp
, MAX(1, XFS_INODES_PER_CHUNK
/inodes_per_block
));
834 bp
= libxfs_readbuf(mp
->m_dev
, XFS_AGB_TO_DADDR(mp
, agno
,
835 XFS_AGINO_TO_AGBNO(mp
, irec
->ino_startnum
)), size
, 0);
837 do_warn("cannot read inode (%u/%u), disk block %lld\n",
838 agno
, irec
->ino_startnum
,
839 XFS_AGB_TO_DADDR(mp
, agno
,
840 XFS_AGINO_TO_AGBNO(mp
, irec
->ino_startnum
)));
844 *dipp
= XFS_MAKE_IPTR(mp
, bp
, agino
-
845 XFS_OFFBNO_TO_AGINO(mp
, XFS_AGINO_TO_AGBNO(mp
,
853 * these next routines return the filesystem blockno of the
854 * block containing the block "bno" in the file whose bmap
855 * tree (or extent list) is rooted by "rootblock".
857 * the next routines are utility routines for the third
858 * routine, get_bmapi().
862 getfunc_extlist(xfs_mount_t
*mp
,
871 xfs_dfsbno_t final_fsbno
= NULLDFSBNO
;
872 xfs_bmbt_rec_32_t
*rootblock
= (xfs_bmbt_rec_32_t
*)
873 XFS_DFORK_PTR_ARCH(dip
, whichfork
, ARCH_CONVERT
);
874 xfs_extnum_t nextents
= XFS_DFORK_NEXTENTS_ARCH(dip
, whichfork
, ARCH_CONVERT
);
878 for (i
= 0; i
< nextents
; i
++) {
879 convert_extent(rootblock
+ i
, &fbno
, &fsbno
, &bcnt
, &flag
);
881 if (fbno
<= bno
&& bno
< fbno
+ bcnt
) {
882 final_fsbno
= bno
- fbno
+ fsbno
;
891 getfunc_btree(xfs_mount_t
*mp
,
901 xfs_bmbt_rec_32_t
*rec
;
904 xfs_bmdr_key_t
*rkey
;
910 xfs_dfsbno_t final_fsbno
= NULLDFSBNO
;
911 xfs_bmbt_block_t
*block
;
912 xfs_bmdr_block_t
*rootblock
= (xfs_bmdr_block_t
*)
913 XFS_DFORK_PTR_ARCH(dip
, whichfork
, ARCH_CONVERT
);
915 ASSERT(rootblock
->bb_level
!= 0);
917 * deal with root block, it's got a slightly different
918 * header structure than interior nodes. We know that
919 * a btree should have at least 2 levels otherwise it
920 * would be an extent list.
922 rkey
= XFS_BTREE_KEY_ADDR(
923 XFS_DFORK_SIZE_ARCH(dip
, mp
, whichfork
, ARCH_CONVERT
),
924 xfs_bmdr
, rootblock
, 1,
925 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE_ARCH(dip
,
926 mp
, whichfork
, ARCH_CONVERT
),
928 rp
= XFS_BTREE_PTR_ADDR(
929 XFS_DFORK_SIZE_ARCH(dip
, mp
, whichfork
, ARCH_CONVERT
),
930 xfs_bmdr
, rootblock
, 1,
931 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE_ARCH(dip
,
932 mp
, whichfork
, ARCH_CONVERT
),
934 for (found
= -1, i
= 0; i
< rootblock
->bb_numrecs
- 1; i
++) {
935 if (rkey
[i
].br_startoff
<= bno
936 && bno
< rkey
[i
+1].br_startoff
) {
941 if (i
== rootblock
->bb_numrecs
- 1 && bno
>= rkey
[i
].br_startoff
)
946 fsbno
= INT_GET(rp
[found
], ARCH_CONVERT
);
948 ASSERT(verify_dfsbno(mp
, fsbno
));
950 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, fsbno
),
951 XFS_FSB_TO_BB(mp
, 1), 0);
953 do_error("cannot read bmap block %llu\n", fsbno
);
956 block
= XFS_BUF_TO_BMBT_BLOCK(bp
);
959 * ok, now traverse any interior btree nodes
961 prev_level
= rootblock
->bb_level
;
963 while (INT_GET(block
->bb_level
, ARCH_CONVERT
) > 0) {
964 ASSERT(INT_GET(block
->bb_level
, ARCH_CONVERT
) < prev_level
);
966 prev_level
= INT_GET(block
->bb_level
, ARCH_CONVERT
);
968 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) >
969 mp
->m_bmap_dmxr
[1]) {
970 do_warn("# of bmap records in inode %llu exceeds max "
972 ino
, INT_GET(block
->bb_numrecs
, ARCH_CONVERT
),
977 if (verbose
&& INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) <
978 mp
->m_bmap_dmnr
[1]) {
979 do_warn("- # of bmap records in inode %llu < than min "
980 "(%u, min - %u), proceeding ...\n",
981 ino
, INT_GET(block
->bb_numrecs
, ARCH_CONVERT
),
984 key
= XFS_BTREE_KEY_ADDR(mp
->m_sb
.sb_blocksize
,
985 xfs_bmbt
, block
, 1, mp
->m_bmap_dmxr
[1]);
986 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
,
987 xfs_bmbt
, block
, 1, mp
->m_bmap_dmxr
[1]);
988 for ( found
= -1, i
= 0;
989 i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) - 1;
991 if (INT_GET(key
[i
].br_startoff
, ARCH_CONVERT
) <= bno
&&
992 bno
< INT_GET(key
[i
+1].br_startoff
, ARCH_CONVERT
)) {
997 if (i
== INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) - 1 &&
998 bno
>= INT_GET(key
[i
].br_startoff
, ARCH_CONVERT
))
1001 ASSERT(found
!= -1);
1002 fsbno
= INT_GET(pp
[found
], ARCH_CONVERT
);
1004 ASSERT(verify_dfsbno(mp
, fsbno
));
1007 * release current btree block and read in the
1008 * next btree block to be traversed
1011 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, fsbno
),
1012 XFS_FSB_TO_BB(mp
, 1), 0);
1014 do_error("cannot read bmap block %llu\n", fsbno
);
1017 block
= XFS_BUF_TO_BMBT_BLOCK(bp
);
1021 * current block must be a leaf block
1023 ASSERT(INT_GET(block
->bb_level
, ARCH_CONVERT
) == 0);
1024 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_bmap_dmxr
[0]) {
1025 do_warn("# of bmap records in inode %llu greater than max "
1027 ino
, INT_GET(block
->bb_numrecs
, ARCH_CONVERT
),
1028 mp
->m_bmap_dmxr
[0]);
1032 if (verbose
&& INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) <
1034 do_warn("- # of bmap records in inode %llu < min "
1035 "(%u, min - %u), continuing...\n",
1036 ino
, INT_GET(block
->bb_numrecs
, ARCH_CONVERT
),
1037 mp
->m_bmap_dmnr
[0]);
1039 rec
= (xfs_bmbt_rec_32_t
*)XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
,
1040 xfs_bmbt
, block
, 1, mp
->m_bmap_dmxr
[0]);
1041 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++) {
1042 convert_extent(rec
+ i
, &fbno
, &fsbno
, &bcnt
, &flag
);
1044 if (fbno
<= bno
&& bno
< fbno
+ bcnt
) {
1045 final_fsbno
= bno
- fbno
+ fsbno
;
1051 if (final_fsbno
== NULLDFSBNO
)
1052 do_warn("could not map block %llu\n", bno
);
1054 return(final_fsbno
);
1058 * this could be smarter. maybe we should have an open inode
1059 * routine that would get the inode buffer and return back
1060 * an inode handle. I'm betting for the moment that this
1061 * is used only by the directory and attribute checking code
1062 * and that the avl tree find and buffer cache search are
1063 * relatively cheap. If they're too expensive, we'll just
1064 * have to fix this and add an inode handle to the da btree
1067 * caller is responsible for checking doubly referenced blocks
1068 * and references to holes
1071 get_bmapi(xfs_mount_t
*mp
, xfs_dinode_t
*dino_p
,
1072 xfs_ino_t ino_num
, xfs_dfiloff_t bno
, int whichfork
)
1076 switch (XFS_DFORK_FORMAT_ARCH(dino_p
, whichfork
, ARCH_CONVERT
)) {
1077 case XFS_DINODE_FMT_EXTENTS
:
1078 fsbno
= getfunc_extlist(mp
, ino_num
, dino_p
, bno
, whichfork
);
1080 case XFS_DINODE_FMT_BTREE
:
1081 fsbno
= getfunc_btree(mp
, ino_num
, dino_p
, bno
, whichfork
);
1083 case XFS_DINODE_FMT_LOCAL
:
1084 do_error("get_bmapi() called for local inode %llu\n", ino_num
);
1091 do_error("bad inode format for inode %llu\n", ino_num
);
1099 * higher level inode processing stuff starts here:
1100 * first, one utility routine for each type of inode
1104 * return 1 if inode should be cleared, 0 otherwise
1110 xfs_agnumber_t agno
,
1121 xfs_bmdr_block_t
*dib
;
1122 xfs_dfiloff_t last_key
;
1123 xfs_dfiloff_t first_key
= 0;
1126 xfs_bmbt_key_t
*pkey
;
1129 bmap_cursor_t cursor
;
1131 dib
= (xfs_bmdr_block_t
*)XFS_DFORK_PTR_ARCH(dip
, whichfork
, ARCH_CONVERT
);
1132 lino
= XFS_AGINO_TO_INO(mp
, agno
, ino
);
1136 if (whichfork
== XFS_DATA_FORK
)
1141 if (INT_GET(dib
->bb_level
, ARCH_CONVERT
) == 0) {
1143 * This should never happen since a btree inode
1144 * has to have at least one other block in the
1145 * bmap in addition to the root block in the
1146 * inode's data fork.
1148 * XXX - if we were going to fix up the inode,
1149 * we'd try to treat the fork as an interior
1150 * node and see if we could get an accurate
1151 * level value from one of the blocks pointed
1152 * to by the pointers in the fork. For now
1153 * though, we just bail (and blow out the inode).
1155 do_warn("bad level 0 in inode %llu bmap btree root block\n",
1156 XFS_AGINO_TO_INO(mp
, agno
, ino
));
1160 * use bmdr/dfork_dsize since the root block is in the data fork
1162 init_bm_cursor(&cursor
, INT_GET(dib
->bb_level
, ARCH_CONVERT
) + 1);
1164 if (XFS_BMDR_SPACE_CALC(INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
)) >
1165 ((whichfork
== XFS_DATA_FORK
) ?
1166 XFS_DFORK_DSIZE_ARCH(dip
, mp
, ARCH_CONVERT
) :
1167 XFS_DFORK_ASIZE_ARCH(dip
, mp
, ARCH_CONVERT
))) {
1169 "indicated size of %s btree root (%d bytes) > space in inode %llu %s fork\n",
1170 forkname
, XFS_BMDR_SPACE_CALC(INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
)),
1175 pp
= XFS_BTREE_PTR_ADDR(XFS_DFORK_SIZE_ARCH(dip
, mp
, whichfork
, ARCH_CONVERT
),
1177 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE_ARCH(dip
, mp
, whichfork
, ARCH_CONVERT
),
1179 pkey
= XFS_BTREE_KEY_ADDR(XFS_DFORK_SIZE_ARCH(dip
, mp
, whichfork
, ARCH_CONVERT
),
1181 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE_ARCH(dip
, mp
, whichfork
, ARCH_CONVERT
),
1184 last_key
= NULLDFILOFF
;
1186 for (i
= 0; i
< INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
); i
++) {
1188 * XXX - if we were going to do more to fix up the inode
1189 * btree, we'd do it right here. For now, if there's a
1190 * problem, we'll bail out and presumably clear the inode.
1192 if (!verify_dfsbno(mp
, INT_GET(pp
[i
], ARCH_CONVERT
))) {
1193 do_warn("bad bmap btree ptr 0x%llx in ino %llu\n",
1194 INT_GET(pp
[i
], ARCH_CONVERT
), lino
);
1198 if (scan_lbtree((xfs_dfsbno_t
)INT_GET(pp
[i
], ARCH_CONVERT
), INT_GET(dib
->bb_level
, ARCH_CONVERT
),
1199 scanfunc_bmap
, type
, whichfork
,
1200 lino
, tot
, nex
, blkmapp
, &cursor
,
1204 * fix key (offset) mismatches between the keys in root
1205 * block records and the first key of each child block.
1206 * fixes cases where entries have been shifted between
1207 * blocks but the parent hasn't been updated
1209 if (check_dups
== 0 &&
1210 cursor
.level
[INT_GET(dib
->bb_level
, ARCH_CONVERT
)-1].first_key
!=
1211 INT_GET(pkey
[i
].br_startoff
, ARCH_CONVERT
)) {
1214 "correcting key in bmbt root (was %llu, now %llu) in inode %llu %s fork\n",
1215 INT_GET(pkey
[i
].br_startoff
, ARCH_CONVERT
),
1216 cursor
.level
[INT_GET(dib
->bb_level
, ARCH_CONVERT
)-1].first_key
,
1217 XFS_AGINO_TO_INO(mp
, agno
, ino
),
1220 INT_SET(pkey
[i
].br_startoff
, ARCH_CONVERT
, cursor
.level
[INT_GET(dib
->bb_level
, ARCH_CONVERT
)-1].first_key
);
1223 "bad key in bmbt root (is %llu, would reset to %llu) in inode %llu %s fork\n",
1224 INT_GET(pkey
[i
].br_startoff
, ARCH_CONVERT
),
1225 cursor
.level
[INT_GET(dib
->bb_level
, ARCH_CONVERT
)-1].first_key
,
1226 XFS_AGINO_TO_INO(mp
, agno
, ino
),
1231 * make sure that keys are in ascending order. blow out
1232 * inode if the ordering doesn't hold
1234 if (check_dups
== 0) {
1235 if (last_key
!= NULLDFILOFF
&& last_key
>=
1236 cursor
.level
[INT_GET(dib
->bb_level
, ARCH_CONVERT
)-1].first_key
) {
1238 "out of order bmbt root key %llu in inode %llu %s fork\n",
1240 XFS_AGINO_TO_INO(mp
, agno
, ino
),
1244 last_key
= cursor
.level
[INT_GET(dib
->bb_level
, ARCH_CONVERT
)-1].first_key
;
1248 * Check that the last child block's forward sibling pointer
1251 if (check_dups
== 0 &&
1252 cursor
.level
[0].right_fsbno
!= NULLDFSBNO
) {
1254 "bad fwd (right) sibling pointer (saw %llu should be NULLDFSBNO)\n",
1255 cursor
.level
[0].right_fsbno
);
1257 "\tin inode %u (%s fork) bmap btree block %llu\n",
1258 XFS_AGINO_TO_INO(mp
, agno
, ino
), forkname
,
1259 cursor
.level
[0].fsbno
);
1267 * return 1 if inode should be cleared, 0 otherwise
1273 xfs_agnumber_t agno
,
1285 xfs_bmbt_rec_32_t
*rp
;
1286 xfs_dfiloff_t first_key
;
1287 xfs_dfiloff_t last_key
;
1289 lino
= XFS_AGINO_TO_INO(mp
, agno
, ino
);
1290 rp
= (xfs_bmbt_rec_32_t
*)XFS_DFORK_PTR_ARCH(dip
, whichfork
, ARCH_CONVERT
);
1292 *nex
= XFS_DFORK_NEXTENTS_ARCH(dip
, whichfork
, ARCH_CONVERT
);
1294 * XXX - if we were going to fix up the btree record,
1295 * we'd do it right here. For now, if there's a problem,
1296 * we'll bail out and presumably clear the inode.
1298 if (check_dups
== 0)
1299 return(process_bmbt_reclist(mp
, rp
, *nex
, type
, lino
,
1300 tot
, blkmapp
, &first_key
, &last_key
,
1303 return(scan_bmbt_reclist(mp
, rp
, *nex
, type
, lino
, tot
,
1308 * return 1 if inode should be cleared, 0 otherwise
1314 xfs_agnumber_t agno
,
1325 xfs_attr_shortform_t
*asf
;
1326 xfs_dinode_core_t
*dic
;
1330 *nex
= 0; /* local inodes have 0 extents */
1332 dic
= &dip
->di_core
;
1333 lino
= XFS_AGINO_TO_INO(mp
, agno
, ino
);
1334 if (whichfork
== XFS_DATA_FORK
&&
1335 INT_GET(dic
->di_size
, ARCH_CONVERT
) > XFS_DFORK_DSIZE_ARCH(dip
, mp
, ARCH_CONVERT
)) {
1337 "local inode %llu data fork is too large (size = %lld, max = %d)\n",
1338 lino
, INT_GET(dic
->di_size
, ARCH_CONVERT
), XFS_DFORK_DSIZE_ARCH(dip
, mp
, ARCH_CONVERT
));
1340 } else if (whichfork
== XFS_ATTR_FORK
) {
1341 asf
= (xfs_attr_shortform_t
*) XFS_DFORK_APTR_ARCH(dip
, ARCH_CONVERT
);
1342 if (INT_GET(asf
->hdr
.totsize
, ARCH_CONVERT
) > XFS_DFORK_ASIZE_ARCH(dip
, mp
, ARCH_CONVERT
)) {
1344 "local inode %llu attr fork too large (size %d, max = %d)\n",
1345 lino
, INT_GET(asf
->hdr
.totsize
, ARCH_CONVERT
),
1346 XFS_DFORK_ASIZE_ARCH(dip
, mp
, ARCH_CONVERT
));
1349 if (INT_GET(asf
->hdr
.totsize
, ARCH_CONVERT
) < sizeof(xfs_attr_sf_hdr_t
)) {
1351 "local inode %llu attr too small (size = %d, min size = %d)\n",
1352 lino
, INT_GET(asf
->hdr
.totsize
, ARCH_CONVERT
),
1353 sizeof(xfs_attr_sf_hdr_t
));
1362 process_symlink_extlist(xfs_mount_t
*mp
, xfs_ino_t lino
, xfs_dinode_t
*dino
)
1364 xfs_dfsbno_t start
; /* start */
1365 xfs_dfilblks_t cnt
; /* count */
1366 xfs_dfiloff_t offset
; /* offset */
1367 xfs_dfiloff_t expected_offset
;
1368 xfs_bmbt_rec_32_t
*rp
;
1372 int whichfork
= XFS_DATA_FORK
;
1375 if (INT_GET(dino
->di_core
.di_size
, ARCH_CONVERT
) <= XFS_DFORK_SIZE_ARCH(dino
, mp
, whichfork
, ARCH_CONVERT
)) {
1376 if (dino
->di_core
.di_format
== XFS_DINODE_FMT_LOCAL
) {
1380 "mismatch between format (%d) and size (%lld) in symlink ino %llu\n",
1381 dino
->di_core
.di_format
,
1382 INT_GET(dino
->di_core
.di_size
, ARCH_CONVERT
),
1386 } else if (dino
->di_core
.di_format
== XFS_DINODE_FMT_LOCAL
) {
1388 "mismatch between format (%d) and size (%lld) in symlink inode %llu\n",
1389 dino
->di_core
.di_format
,
1390 INT_GET(dino
->di_core
.di_size
, ARCH_CONVERT
),
1395 rp
= (xfs_bmbt_rec_32_t
*)XFS_DFORK_PTR_ARCH(dino
, whichfork
, ARCH_CONVERT
);
1396 numrecs
= XFS_DFORK_NEXTENTS_ARCH(dino
, whichfork
, ARCH_CONVERT
);
1399 * the max # of extents in a symlink inode is equal to the
1400 * number of max # of blocks required to store the symlink
1402 if (numrecs
> max_symlink_blocks
) {
1404 "bad number of extents (%d) in symlink %llu data fork\n",
1409 max_blocks
= max_symlink_blocks
;
1410 expected_offset
= 0;
1412 for (i
= 0; numrecs
> 0; i
++, numrecs
--) {
1413 convert_extent(rp
, &offset
, &start
, &cnt
, &flag
);
1415 if (offset
!= expected_offset
) {
1417 "bad extent #%d offset (%llu) in symlink %llu data fork\n",
1421 if (cnt
== 0 || cnt
> max_blocks
) {
1423 "bad extent #%d count (%llu) in symlink %llu data fork\n",
1429 expected_offset
+= cnt
;
1436 * takes a name and length and returns 1 if the name contains
1437 * a \0, returns 0 otherwise
1440 null_check(char *name
, int length
)
1444 ASSERT(length
< MAXPATHLEN
);
1446 for (i
= 0; i
< length
; i
++, name
++) {
1455 * like usual, returns 0 if everything's ok and 1 if something's
1459 process_symlink(xfs_mount_t
*mp
, xfs_ino_t lino
, xfs_dinode_t
*dino
,
1463 xfs_dinode_core_t
*dinoc
= &dino
->di_core
;
1464 xfs_buf_t
*bp
= NULL
;
1465 char *symlink
, *cptr
, *buf_data
;
1466 int i
, size
, amountdone
;
1467 char data
[MAXPATHLEN
];
1470 * check size against kernel symlink limits. we know
1471 * size is consistent with inode storage format -- e.g.
1472 * the inode is structurally ok so we don't have to check
1475 if (INT_GET(dinoc
->di_size
, ARCH_CONVERT
) >= MAXPATHLEN
) {
1476 do_warn("symlink in inode %llu too long (%lld chars)\n",
1477 lino
, INT_GET(dinoc
->di_size
, ARCH_CONVERT
));
1482 * have to check symlink component by component.
1483 * get symlink contents into data area
1486 if (INT_GET(dinoc
->di_size
, ARCH_CONVERT
)
1487 <= XFS_DFORK_DSIZE_ARCH(dino
, mp
, ARCH_CONVERT
)) {
1489 * local symlink, just copy the symlink out of the
1490 * inode into the data area
1492 bcopy((char *)XFS_DFORK_DPTR_ARCH(dino
, ARCH_CONVERT
),
1493 symlink
, INT_GET(dinoc
->di_size
, ARCH_CONVERT
));
1496 * stored in a meta-data file, have to bmap one block
1497 * at a time and copy the symlink into the data area
1499 i
= size
= amountdone
= 0;
1502 while (amountdone
< INT_GET(dinoc
->di_size
, ARCH_CONVERT
)) {
1503 fsbno
= blkmap_get(blkmap
, i
);
1504 if (fsbno
!= NULLDFSBNO
)
1505 bp
= libxfs_readbuf(mp
->m_dev
,
1506 XFS_FSB_TO_DADDR(mp
, fsbno
),
1507 XFS_FSB_TO_BB(mp
, 1), 0);
1508 if (!bp
|| fsbno
== NULLDFSBNO
) {
1509 do_warn("cannot read inode %llu, file block %d,"
1510 " disk block %llu\n", lino
, i
, fsbno
);
1514 buf_data
= (char *)XFS_BUF_PTR(bp
);
1515 size
= MIN(INT_GET(dinoc
->di_size
, ARCH_CONVERT
)
1516 - amountdone
, (int)XFS_FSB_TO_BB(mp
, 1)*BBSIZE
);
1517 bcopy(buf_data
, cptr
, size
);
1524 data
[INT_GET(dinoc
->di_size
, ARCH_CONVERT
)] = '\0';
1529 if (null_check(symlink
, (int) INT_GET(dinoc
->di_size
, ARCH_CONVERT
))) {
1530 do_warn("found illegal null character in symlink inode %llu\n",
1536 * check for any component being too long
1538 if (INT_GET(dinoc
->di_size
, ARCH_CONVERT
) >= MAXNAMELEN
) {
1539 cptr
= strchr(symlink
, '/');
1541 while (cptr
!= NULL
) {
1542 if (cptr
- symlink
>= MAXNAMELEN
) {
1544 "component of symlink in inode %llu too long\n",
1549 cptr
= strchr(symlink
, '/');
1552 if (strlen(symlink
) >= MAXNAMELEN
) {
1553 do_warn("component of symlink in inode %llu too long\n",
1563 * called to process the set of misc inode special inode types
1564 * that have no associated data storage (fifos, pipes, devices, etc.).
1568 process_misc_ino_types(xfs_mount_t
*mp
,
1574 * disallow mountpoint inodes until such time as the
1575 * kernel actually allows them to be created (will
1576 * probably require a superblock version rev, sigh).
1578 if (type
== XR_INO_MOUNTPOINT
) {
1579 do_warn("inode %llu has bad inode type (IFMNT)\n", lino
);
1584 * must also have a zero size
1586 if (INT_GET(dino
->di_core
.di_size
, ARCH_CONVERT
) != 0) {
1589 do_warn("size of character device inode %llu != 0 "
1590 "(%lld bytes)\n", lino
,
1591 INT_GET(dino
->di_core
.di_size
, ARCH_CONVERT
));
1594 do_warn("size of block device inode %llu != 0 "
1595 "(%lld bytes)\n", lino
,
1596 INT_GET(dino
->di_core
.di_size
, ARCH_CONVERT
));
1599 do_warn("size of socket inode %llu != 0 "
1600 "(%lld bytes)\n", lino
,
1601 INT_GET(dino
->di_core
.di_size
, ARCH_CONVERT
));
1604 do_warn("size of fifo inode %llu != 0 "
1605 "(%lld bytes)\n", lino
,
1606 INT_GET(dino
->di_core
.di_size
, ARCH_CONVERT
));
1609 do_warn("Internal error - process_misc_ino_types, "
1610 "illegal type %d\n", type
);
1621 process_misc_ino_types_blocks(xfs_drfsbno_t totblocks
, xfs_ino_t lino
, int type
)
1624 * you can not enforce all misc types have zero data fork blocks
1625 * by checking dino->di_core.di_nblocks because atotblocks (attribute
1626 * blocks) are part of nblocks. We must check this later when atotblocks
1627 * has been calculated or by doing a simple check that anExtents == 0.
1628 * We must also guarantee that totblocks is 0. Thus nblocks checking
1629 * will be done later in process_dinode_int for misc types.
1632 if (totblocks
!= 0) {
1636 "size of character device inode %llu != 0 (%llu blocks)\n",
1641 "size of block device inode %llu != 0 (%llu blocks)\n",
1646 "size of socket inode %llu != 0 (%llu blocks)\n",
1651 "size of fifo inode %llu != 0 (%llu blocks)\n",
1663 * returns 0 if the inode is ok, 1 if the inode is corrupt
1664 * check_dups can be set to 1 *only* when called by the
1665 * first pass of the duplicate block checking of phase 4.
1666 * *dirty is set > 0 if the dinode has been altered and
1667 * needs to be written out.
1669 * for detailed, info, look at process_dinode() comments.
1673 process_dinode_int(xfs_mount_t
*mp
,
1675 xfs_agnumber_t agno
,
1677 int was_free
, /* 1 if inode is currently free */
1678 int *dirty
, /* out == > 0 if inode is now dirty */
1679 int *cleared
, /* out == 1 if inode was cleared */
1680 int *used
, /* out == 1 if inode is in use */
1681 int verify_mode
, /* 1 == verify but don't modify inode */
1682 int uncertain
, /* 1 == inode is uncertain */
1683 int ino_discovery
, /* 1 == check dirs for unknown inodes */
1684 int check_dups
, /* 1 == check if inode claims
1685 * duplicate blocks */
1686 int extra_attr_check
, /* 1 == do attribute format and value checks */
1687 int *isa_dir
, /* out == 1 if inode is a directory */
1688 xfs_ino_t
*parent
) /* out -- parent if ino is a dir */
1690 xfs_drfsbno_t totblocks
= 0;
1691 xfs_drfsbno_t atotblocks
= 0;
1692 xfs_dinode_core_t
*dinoc
;
1699 __uint64_t nextents
;
1700 __uint64_t anextents
;
1702 const int is_free
= 0;
1703 const int is_used
= 1;
1705 blkmap_t
*ablkmap
= NULL
;
1706 blkmap_t
*dblkmap
= NULL
;
1707 static char okfmts
[] = {
1709 1 << XFS_DINODE_FMT_DEV
, /* FIFO */
1710 1 << XFS_DINODE_FMT_DEV
, /* CHR */
1711 0, /* type 3 unused */
1712 (1 << XFS_DINODE_FMT_LOCAL
) |
1713 (1 << XFS_DINODE_FMT_EXTENTS
) |
1714 (1 << XFS_DINODE_FMT_BTREE
), /* DIR */
1715 0, /* type 5 unused */
1716 1 << XFS_DINODE_FMT_DEV
, /* BLK */
1717 0, /* type 7 unused */
1718 (1 << XFS_DINODE_FMT_EXTENTS
) |
1719 (1 << XFS_DINODE_FMT_BTREE
), /* REG */
1720 0, /* type 9 unused */
1721 (1 << XFS_DINODE_FMT_LOCAL
) |
1722 (1 << XFS_DINODE_FMT_EXTENTS
), /* LNK */
1723 0, /* type 11 unused */
1724 1 << XFS_DINODE_FMT_DEV
, /* SOCK */
1725 0, /* type 13 unused */
1726 1 << XFS_DINODE_FMT_UUID
, /* MNT */
1727 0 /* type 15 unused */
1731 totblocks
= atotblocks
= 0;
1732 *dirty
= *isa_dir
= *cleared
= 0;
1734 type
= rtype
= XR_INO_UNKNOWN
;
1738 dinoc
= &dino
->di_core
;
1739 lino
= XFS_AGINO_TO_INO(mp
, agno
, ino
);
1742 * if in verify mode, don't modify the inode.
1744 * if correcting, reset stuff that has known values
1746 * if in uncertain mode, be silent on errors since we're
1747 * trying to find out if these are inodes as opposed
1748 * to assuming that they are. Just return the appropriate
1749 * return code in that case.
1752 if (INT_GET(dinoc
->di_magic
, ARCH_CONVERT
) != XFS_DINODE_MAGIC
) {
1755 do_warn("bad magic number 0x%x on inode %llu, ",
1756 INT_GET(dinoc
->di_magic
, ARCH_CONVERT
), lino
);
1758 do_warn("resetting magic number\n");
1760 INT_SET(dinoc
->di_magic
, ARCH_CONVERT
, XFS_DINODE_MAGIC
);
1762 do_warn("would reset magic number\n");
1764 } else if (!uncertain
) {
1765 do_warn("bad magic number 0x%x on inode %llu\n",
1766 INT_GET(dinoc
->di_magic
, ARCH_CONVERT
), lino
);
1770 if (!XFS_DINODE_GOOD_VERSION(dinoc
->di_version
) ||
1771 (!fs_inode_nlink
&& dinoc
->di_version
> XFS_DINODE_VERSION_1
)) {
1774 do_warn("bad version number 0x%x on inode %llu, ",
1775 dinoc
->di_version
, lino
);
1777 do_warn("resetting version number\n");
1779 dinoc
->di_version
= (fs_inode_nlink
) ?
1780 XFS_DINODE_VERSION_2
:
1781 XFS_DINODE_VERSION_1
;
1783 do_warn("would reset version number\n");
1785 } else if (!uncertain
) {
1786 do_warn("bad version number 0x%x on inode %llu\n",
1787 dinoc
->di_version
, lino
);
1792 * blow out of here if the inode size is < 0
1794 if (INT_GET(dinoc
->di_size
, ARCH_CONVERT
) < 0) {
1797 do_warn("bad (negative) size %lld on inode %llu\n",
1798 INT_GET(dinoc
->di_size
, ARCH_CONVERT
), lino
);
1800 *dirty
+= clear_dinode(mp
, dino
, lino
);
1807 } else if (!uncertain
) {
1808 do_warn("bad (negative) size %lld on inode %llu\n",
1809 INT_GET(dinoc
->di_size
, ARCH_CONVERT
), lino
);
1816 * was_free value is not meaningful if we're in verify mode
1818 if (!verify_mode
&& INT_GET(dinoc
->di_mode
, ARCH_CONVERT
) == 0 && was_free
== 1) {
1820 * easy case, inode free -- inode and map agree, clear
1821 * it just in case to ensure that format, etc. are
1825 err
= clear_dinode(mp
, dino
, lino
);
1833 } else if (!verify_mode
&& INT_GET(dinoc
->di_mode
, ARCH_CONVERT
) == 0 && was_free
== 0) {
1835 * the inode looks free but the map says it's in use.
1836 * clear the inode just to be safe and mark the inode
1839 do_warn("imap claims a free inode %llu is in use, ", lino
);
1842 do_warn("correcting imap and clearing inode\n");
1844 err
= clear_dinode(mp
, dino
, lino
);
1851 do_warn("would correct imap and clear inode\n");
1859 return(retval
> 0 ? 1 : 0);
1863 * because of the lack of any write ordering guarantee, it's
1864 * possible that the core got updated but the forks didn't.
1865 * so rather than be ambitious (and probably incorrect),
1866 * if there's an inconsistency, we get conservative and
1867 * just pitch the file. blow off checking formats of
1868 * free inodes since technically any format is legal
1869 * as we reset the inode when we re-use it.
1871 if (INT_GET(dinoc
->di_mode
, ARCH_CONVERT
) != 0 &&
1872 ((((INT_GET(dinoc
->di_mode
, ARCH_CONVERT
) & IFMT
) >> 12) > 15) ||
1873 dinoc
->di_format
< XFS_DINODE_FMT_DEV
||
1874 dinoc
->di_format
> XFS_DINODE_FMT_UUID
||
1875 (!(okfmts
[(INT_GET(dinoc
->di_mode
, ARCH_CONVERT
) & IFMT
) >> 12] &
1876 (1 << dinoc
->di_format
))))) {
1877 /* bad inode format */
1880 do_warn("bad inode format in inode %llu\n", lino
);
1883 *dirty
+= clear_dinode(mp
, dino
, lino
);
1890 return(retval
> 0 ? 1 : 0);
1894 return(retval
> 0 ? 1 : 0);
1897 * clear the next unlinked field if necessary on a good
1898 * inode only during phase 4 -- when checking for inodes
1899 * referencing duplicate blocks. then it's safe because
1900 * we've done the inode discovery and have found all the inodes
1901 * we're going to find. check_dups is set to 1 only during
1904 if (check_dups
&& !no_modify
)
1905 *dirty
+= clear_dinode_unlinked(mp
, dino
);
1907 /* set type and map type info */
1909 switch (INT_GET(dinoc
->di_mode
, ARCH_CONVERT
) & IFMT
) {
1915 if (INT_GET(dinoc
->di_flags
, ARCH_CONVERT
) & XFS_DIFLAG_REALTIME
)
1916 type
= XR_INO_RTDATA
;
1917 else if (lino
== mp
->m_sb
.sb_rbmino
)
1918 type
= XR_INO_RTBITMAP
;
1919 else if (lino
== mp
->m_sb
.sb_rsumino
)
1920 type
= XR_INO_RTSUM
;
1925 type
= XR_INO_SYMLINK
;
1928 type
= XR_INO_CHRDEV
;
1931 type
= XR_INO_BLKDEV
;
1940 type
= XR_INO_MOUNTPOINT
;
1943 type
= XR_INO_UNKNOWN
;
1944 do_warn("Unexpected inode type %#o inode %llu\n",
1945 (int) (INT_GET(dinoc
->di_mode
, ARCH_CONVERT
) & IFMT
), lino
);
1951 * type checks for root, realtime inodes, and quota inodes
1953 if (lino
== mp
->m_sb
.sb_rootino
&& type
!= XR_INO_DIR
) {
1954 do_warn("bad inode type for root inode %llu, ", lino
);
1958 do_warn("resetting to directory\n");
1959 INT_MOD_EXPR(dinoc
->di_mode
, ARCH_CONVERT
, &= ~(INT_GET(dinoc
->di_mode
, ARCH_CONVERT
) & IFMT
));
1960 INT_MOD_EXPR(dinoc
->di_mode
, ARCH_CONVERT
, |= INT_GET(dinoc
->di_mode
, ARCH_CONVERT
) & IFDIR
);
1962 do_warn("would reset to directory\n");
1964 } else if (lino
== mp
->m_sb
.sb_rsumino
) {
1966 rstring
= "summary";
1967 rtype
= XR_INO_RTSUM
;
1968 } else if (lino
== mp
->m_sb
.sb_rbmino
) {
1971 rtype
= XR_INO_RTBITMAP
;
1972 } else if (lino
== mp
->m_sb
.sb_uquotino
) {
1973 if (type
!= XR_INO_DATA
) {
1974 do_warn("user quota inode has bad type 0x%x\n",
1975 INT_GET(dinoc
->di_mode
, ARCH_CONVERT
) & IFMT
);
1978 *dirty
+= clear_dinode(mp
, dino
, lino
);
1986 mp
->m_sb
.sb_uquotino
= NULLFSINO
;
1990 } else if (lino
== mp
->m_sb
.sb_gquotino
) {
1991 if (type
!= XR_INO_DATA
) {
1992 do_warn("group quota inode has bad type 0x%x\n",
1993 INT_GET(dinoc
->di_mode
, ARCH_CONVERT
) & IFMT
);
1996 *dirty
+= clear_dinode(mp
, dino
, lino
);
2004 mp
->m_sb
.sb_gquotino
= NULLFSINO
;
2010 if (do_rt
&& type
!= rtype
) {
2013 do_warn("bad inode type for realtime %s inode %llu, ",
2017 do_warn("resetting to regular file\n");
2018 INT_MOD_EXPR(dinoc
->di_mode
, ARCH_CONVERT
, &= ~(INT_GET(dinoc
->di_mode
, ARCH_CONVERT
) & IFMT
));
2019 INT_MOD_EXPR(dinoc
->di_mode
, ARCH_CONVERT
, |= INT_GET(dinoc
->di_mode
, ARCH_CONVERT
) & IFREG
);
2021 do_warn("would reset to regular file\n");
2026 * only realtime inodes should have extsize set
2028 if (type
!= XR_INO_RTDATA
&& INT_GET(dinoc
->di_extsize
, ARCH_CONVERT
) != 0) {
2030 "bad non-zero extent size value %u for non-realtime inode %llu, ",
2031 INT_GET(dinoc
->di_extsize
, ARCH_CONVERT
), lino
);
2034 do_warn("resetting to zero\n");
2035 INT_ZERO(dinoc
->di_extsize
, ARCH_CONVERT
);
2038 do_warn("would reset to zero\n");
2043 * for realtime inodes, check sizes to see that
2044 * they are consistent with the # of realtime blocks.
2045 * also, verify that they contain only one extent and
2046 * are extent format files. If anything's wrong, clear
2047 * the inode -- we'll recreate it in phase 6.
2049 if (do_rt
&& INT_GET(dinoc
->di_size
, ARCH_CONVERT
)
2050 != mp
->m_sb
.sb_rbmblocks
* mp
->m_sb
.sb_blocksize
) {
2051 do_warn("bad size %llu for realtime %s inode %llu\n",
2052 INT_GET(dinoc
->di_size
, ARCH_CONVERT
), rstring
, lino
);
2055 *dirty
+= clear_dinode(mp
, dino
, lino
);
2066 if (do_rt
&& mp
->m_sb
.sb_rblocks
== 0 && INT_GET(dinoc
->di_nextents
, ARCH_CONVERT
) != 0) {
2067 do_warn("bad # of extents (%u) for realtime %s inode %llu\n",
2068 INT_GET(dinoc
->di_nextents
, ARCH_CONVERT
), rstring
, lino
);
2071 *dirty
+= clear_dinode(mp
, dino
, lino
);
2083 * Setup nextents and anextents for blkmap_alloc calls.
2085 nextents
= INT_GET(dinoc
->di_nextents
, ARCH_CONVERT
);
2086 if (nextents
> INT_GET(dinoc
->di_nblocks
, ARCH_CONVERT
) || nextents
> XFS_MAX_INCORE_EXTENTS
)
2088 anextents
= INT_GET(dinoc
->di_anextents
, ARCH_CONVERT
);
2089 if (anextents
> INT_GET(dinoc
->di_nblocks
, ARCH_CONVERT
) || anextents
> XFS_MAX_INCORE_EXTENTS
)
2093 * general size/consistency checks:
2095 * if the size <= size of the data fork, directories must be
2096 * local inodes unlike regular files which would be extent inodes.
2097 * all the other mentioned types have to have a zero size value.
2099 * if the size and format don't match, get out now rather than
2100 * risk trying to process a non-existent extents or btree
2105 if (INT_GET(dinoc
->di_size
, ARCH_CONVERT
) <= XFS_DFORK_DSIZE_ARCH(dino
, mp
, ARCH_CONVERT
)
2106 && dinoc
->di_format
!= XFS_DINODE_FMT_LOCAL
) {
2108 "mismatch between format (%d) and size (%lld) in directory ino %llu\n",
2110 INT_GET(dinoc
->di_size
, ARCH_CONVERT
),
2114 *dirty
+= clear_dinode(mp
,
2125 if (dinoc
->di_format
!= XFS_DINODE_FMT_LOCAL
)
2126 dblkmap
= blkmap_alloc(nextents
);
2128 case XR_INO_SYMLINK
:
2129 if (process_symlink_extlist(mp
, lino
, dino
)) {
2130 do_warn("bad data fork in symlink %llu\n", lino
);
2133 *dirty
+= clear_dinode(mp
,
2144 if (dinoc
->di_format
!= XFS_DINODE_FMT_LOCAL
)
2145 dblkmap
= blkmap_alloc(nextents
);
2147 case XR_INO_CHRDEV
: /* fall through to FIFO case ... */
2148 case XR_INO_BLKDEV
: /* fall through to FIFO case ... */
2149 case XR_INO_SOCK
: /* fall through to FIFO case ... */
2150 case XR_INO_MOUNTPOINT
: /* fall through to FIFO case ... */
2152 if (process_misc_ino_types(mp
, dino
, lino
, type
)) {
2154 *dirty
+= clear_dinode(mp
, dino
, lino
);
2167 * if we have no realtime blocks, any inode claiming
2168 * to be a real-time file is bogus
2170 if (mp
->m_sb
.sb_rblocks
== 0) {
2172 "found inode %llu claiming to be a real-time file\n",
2176 *dirty
+= clear_dinode(mp
, dino
, lino
);
2187 case XR_INO_RTBITMAP
:
2188 if (INT_GET(dinoc
->di_size
, ARCH_CONVERT
) != (__int64_t
) mp
->m_sb
.sb_rbmblocks
*
2189 mp
->m_sb
.sb_blocksize
) {
2191 "realtime bitmap inode %llu has bad size %lld (should be %lld)\n",
2192 lino
, INT_GET(dinoc
->di_size
, ARCH_CONVERT
),
2193 (__int64_t
) mp
->m_sb
.sb_rbmblocks
*
2194 mp
->m_sb
.sb_blocksize
);
2197 *dirty
+= clear_dinode(mp
, dino
, lino
);
2207 dblkmap
= blkmap_alloc(nextents
);
2210 if (INT_GET(dinoc
->di_size
, ARCH_CONVERT
) != mp
->m_rsumsize
) {
2212 "realtime summary inode %llu has bad size %lld (should be %d)\n",
2213 lino
, INT_GET(dinoc
->di_size
, ARCH_CONVERT
), mp
->m_rsumsize
);
2216 *dirty
+= clear_dinode(mp
, dino
, lino
);
2226 dblkmap
= blkmap_alloc(nextents
);
2233 * check for illegal values of forkoff
2236 if (dinoc
->di_forkoff
!= 0) {
2237 switch (dinoc
->di_format
) {
2238 case XFS_DINODE_FMT_DEV
:
2239 if (dinoc
->di_forkoff
!=
2240 (roundup(sizeof(dev_t
), 8) >> 3)) {
2242 "bad attr fork offset %d in dev inode %llu, should be %d\n",
2243 (int) dinoc
->di_forkoff
,
2245 (int) (roundup(sizeof(dev_t
), 8) >> 3));
2249 case XFS_DINODE_FMT_UUID
:
2250 if (dinoc
->di_forkoff
!=
2251 (roundup(sizeof(uuid_t
), 8) >> 3)) {
2253 "bad attr fork offset %d in uuid inode %llu, should be %d\n",
2254 (int) dinoc
->di_forkoff
,
2256 (int)(roundup(sizeof(uuid_t
), 8) >> 3));
2260 case XFS_DINODE_FMT_LOCAL
: /* fall through ... */
2261 case XFS_DINODE_FMT_EXTENTS
: /* fall through ... */
2262 case XFS_DINODE_FMT_BTREE
:
2263 if (dinoc
->di_forkoff
!= mp
->m_attroffset
>> 3) {
2265 "bad attr fork offset %d in inode %llu, should be %d\n",
2266 (int) dinoc
->di_forkoff
,
2268 (int) (mp
->m_attroffset
>> 3));
2273 do_error("unexpected inode format %d\n",
2274 (int) dinoc
->di_format
);
2281 *dirty
+= clear_dinode(mp
, dino
, lino
);
2288 blkmap_free(dblkmap
);
2293 * check data fork -- if it's bad, clear the inode
2296 switch (dinoc
->di_format
) {
2297 case XFS_DINODE_FMT_LOCAL
:
2298 err
= process_lclinode(mp
, agno
, ino
, dino
, type
,
2299 dirty
, &totblocks
, &nextents
, &dblkmap
,
2300 XFS_DATA_FORK
, check_dups
);
2302 case XFS_DINODE_FMT_EXTENTS
:
2303 err
= process_exinode(mp
, agno
, ino
, dino
, type
,
2304 dirty
, &totblocks
, &nextents
, &dblkmap
,
2305 XFS_DATA_FORK
, check_dups
);
2307 case XFS_DINODE_FMT_BTREE
:
2308 err
= process_btinode(mp
, agno
, ino
, dino
, type
,
2309 dirty
, &totblocks
, &nextents
, &dblkmap
,
2310 XFS_DATA_FORK
, check_dups
);
2312 case XFS_DINODE_FMT_DEV
: /* fall through */
2313 case XFS_DINODE_FMT_UUID
:
2317 do_error("unknown format %d, ino %llu (mode = %d)\n",
2318 dinoc
->di_format
, lino
, INT_GET(dinoc
->di_mode
, ARCH_CONVERT
));
2323 * problem in the data fork, clear out the inode
2326 do_warn("bad data fork in inode %llu\n", lino
);
2329 *dirty
+= clear_dinode(mp
, dino
, lino
);
2336 blkmap_free(dblkmap
);
2343 * if check_dups was non-zero, we have to
2344 * re-process data fork to set bitmap since the
2345 * bitmap wasn't set the first time through
2347 switch (dinoc
->di_format
) {
2348 case XFS_DINODE_FMT_LOCAL
:
2349 err
= process_lclinode(mp
, agno
, ino
, dino
, type
,
2350 dirty
, &totblocks
, &nextents
, &dblkmap
,
2353 case XFS_DINODE_FMT_EXTENTS
:
2354 err
= process_exinode(mp
, agno
, ino
, dino
, type
,
2355 dirty
, &totblocks
, &nextents
, &dblkmap
,
2358 case XFS_DINODE_FMT_BTREE
:
2359 err
= process_btinode(mp
, agno
, ino
, dino
, type
,
2360 dirty
, &totblocks
, &nextents
, &dblkmap
,
2363 case XFS_DINODE_FMT_DEV
: /* fall through */
2364 case XFS_DINODE_FMT_UUID
:
2368 do_error("unknown format %d, ino %llu (mode = %d)\n",
2369 dinoc
->di_format
, lino
, INT_GET(dinoc
->di_mode
, ARCH_CONVERT
));
2372 if (no_modify
&& err
!= 0) {
2376 blkmap_free(dblkmap
);
2385 * check attribute fork if necessary. attributes are
2386 * always stored in the regular filesystem.
2389 if (!XFS_DFORK_Q_ARCH(dino
, ARCH_CONVERT
) && dinoc
->di_aformat
!= XFS_DINODE_FMT_EXTENTS
) {
2390 do_warn("bad attribute format %d in inode %llu, ",
2391 dinoc
->di_aformat
, lino
);
2393 do_warn("resetting value\n");
2394 dinoc
->di_aformat
= XFS_DINODE_FMT_EXTENTS
;
2397 do_warn("would reset value\n");
2399 } else if (XFS_DFORK_Q_ARCH(dino
, ARCH_CONVERT
)) {
2400 switch (dinoc
->di_aformat
) {
2401 case XFS_DINODE_FMT_LOCAL
:
2403 err
= process_lclinode(mp
, agno
, ino
, dino
,
2404 type
, dirty
, &atotblocks
, &anextents
, &ablkmap
,
2405 XFS_ATTR_FORK
, check_dups
);
2407 case XFS_DINODE_FMT_EXTENTS
:
2408 ablkmap
= blkmap_alloc(anextents
);
2410 err
= process_exinode(mp
, agno
, ino
, dino
,
2411 type
, dirty
, &atotblocks
, &anextents
, &ablkmap
,
2412 XFS_ATTR_FORK
, check_dups
);
2414 case XFS_DINODE_FMT_BTREE
:
2415 ablkmap
= blkmap_alloc(anextents
);
2417 err
= process_btinode(mp
, agno
, ino
, dino
,
2418 type
, dirty
, &atotblocks
, &anextents
, &ablkmap
,
2419 XFS_ATTR_FORK
, check_dups
);
2423 do_warn("illegal attribute format %d, ino %llu\n",
2424 dinoc
->di_aformat
, lino
);
2431 * clear the attribute fork if necessary. we can't
2432 * clear the inode because we've already put the
2433 * inode space info into the blockmap.
2435 * XXX - put the inode onto the "move it" list and
2436 * log the the attribute scrubbing
2438 do_warn("bad attribute fork in inode %llu", lino
);
2441 if (delete_attr_ok
) {
2442 do_warn(", clearing attr fork\n");
2443 *dirty
+= clear_dinode_attr(mp
,
2447 *dirty
+= clear_dinode(mp
,
2452 do_warn(", would clear attr fork\n");
2458 if (delete_attr_ok
) {
2460 dinoc
->di_aformat
= XFS_DINODE_FMT_LOCAL
;
2465 blkmap_free(dblkmap
);
2466 blkmap_free(ablkmap
);
2470 } else if (check_dups
) {
2471 switch (dinoc
->di_aformat
) {
2472 case XFS_DINODE_FMT_LOCAL
:
2473 err
= process_lclinode(mp
, agno
, ino
, dino
,
2474 type
, dirty
, &atotblocks
, &anextents
,
2475 &ablkmap
, XFS_ATTR_FORK
, 0);
2477 case XFS_DINODE_FMT_EXTENTS
:
2478 err
= process_exinode(mp
, agno
, ino
, dino
,
2479 type
, dirty
, &atotblocks
, &anextents
,
2480 &ablkmap
, XFS_ATTR_FORK
, 0);
2482 case XFS_DINODE_FMT_BTREE
:
2483 err
= process_btinode(mp
, agno
, ino
, dino
,
2484 type
, dirty
, &atotblocks
, &anextents
,
2485 &ablkmap
, XFS_ATTR_FORK
, 0);
2488 do_error("illegal attribute fmt %d, ino %llu\n",
2489 dinoc
->di_aformat
, lino
);
2492 if (no_modify
&& err
!= 0) {
2496 blkmap_free(dblkmap
);
2497 blkmap_free(ablkmap
);
2506 * do attribute semantic-based consistency checks now
2509 /* get this only in phase 3, not in both phase 3 and 4 */
2510 if (extra_attr_check
) {
2511 if ((err
= process_attributes(mp
, lino
, dino
, ablkmap
,
2513 do_warn("problem with attribute contents in inode %llu\n",lino
);
2515 /* clear attributes if not done already */
2517 *dirty
+= clear_dinode_attr(
2520 XFS_DINODE_FMT_LOCAL
;
2522 do_warn("would clear attr fork\n");
2528 *dirty
= 1; /* it's been repaired */
2532 blkmap_free(ablkmap
);
2538 * enforce totblocks is 0 for misc types
2540 if (process_misc_ino_types_blocks(totblocks
, lino
, type
)) {
2542 *dirty
+= clear_dinode(mp
, dino
, lino
);
2548 blkmap_free(dblkmap
);
2554 * correct space counters if required
2556 if (totblocks
+ atotblocks
!= INT_GET(dinoc
->di_nblocks
, ARCH_CONVERT
)) {
2558 do_warn("correcting nblocks for inode %llu, was %llu - counted %llu\n",
2559 lino
, INT_GET(dinoc
->di_nblocks
, ARCH_CONVERT
),
2560 totblocks
+ atotblocks
);
2562 INT_SET(dinoc
->di_nblocks
, ARCH_CONVERT
, totblocks
+ atotblocks
);
2565 "bad nblocks %llu for inode %llu, would reset to %llu\n",
2566 INT_GET(dinoc
->di_nblocks
, ARCH_CONVERT
), lino
,
2567 totblocks
+ atotblocks
);
2571 if (nextents
> MAXEXTNUM
) {
2572 do_warn("too many data fork extents (%llu) in inode %llu\n",
2576 *dirty
+= clear_dinode(mp
, dino
, lino
);
2582 blkmap_free(dblkmap
);
2586 if (nextents
!= INT_GET(dinoc
->di_nextents
, ARCH_CONVERT
)) {
2588 do_warn("correcting nextents for inode %llu, was %d - counted %llu\n",
2589 lino
, INT_GET(dinoc
->di_nextents
, ARCH_CONVERT
), nextents
);
2591 INT_SET(dinoc
->di_nextents
, ARCH_CONVERT
, (xfs_extnum_t
) nextents
);
2594 "bad nextents %d for inode %llu, would reset to %llu\n",
2595 INT_GET(dinoc
->di_nextents
, ARCH_CONVERT
), lino
, nextents
);
2599 if (anextents
> MAXAEXTNUM
) {
2600 do_warn("too many attr fork extents (%llu) in inode %llu\n",
2604 *dirty
+= clear_dinode(mp
, dino
, lino
);
2610 blkmap_free(dblkmap
);
2614 if (anextents
!= INT_GET(dinoc
->di_anextents
, ARCH_CONVERT
)) {
2616 do_warn("correcting anextents for inode %llu, was %d - counted %llu\n",
2617 lino
, INT_GET(dinoc
->di_anextents
, ARCH_CONVERT
), anextents
);
2619 INT_SET(dinoc
->di_anextents
, ARCH_CONVERT
, (xfs_aextnum_t
) anextents
);
2622 "bad anextents %d for inode %llu, would reset to %llu\n",
2623 INT_GET(dinoc
->di_anextents
, ARCH_CONVERT
), lino
, anextents
);
2628 * do any semantic type-based checking here
2632 if (XFS_SB_VERSION_HASDIRV2(&mp
->m_sb
))
2633 err
= process_dir2(mp
, lino
, dino
, ino_discovery
,
2634 dirty
, "", parent
, dblkmap
);
2636 err
= process_dir(mp
, lino
, dino
, ino_discovery
,
2637 dirty
, "", parent
, dblkmap
);
2640 "problem with directory contents in inode %llu\n",
2643 case XR_INO_RTBITMAP
:
2644 /* process_rtbitmap XXX */
2648 /* process_rtsummary XXX */
2651 case XR_INO_SYMLINK
:
2652 if ((err
= process_symlink(mp
, lino
, dino
, dblkmap
)))
2653 do_warn("problem with symbolic link in inode %llu\n",
2656 case XR_INO_DATA
: /* fall through to FIFO case ... */
2657 case XR_INO_RTDATA
: /* fall through to FIFO case ... */
2658 case XR_INO_CHRDEV
: /* fall through to FIFO case ... */
2659 case XR_INO_BLKDEV
: /* fall through to FIFO case ... */
2660 case XR_INO_SOCK
: /* fall through to FIFO case ... */
2665 printf("Unexpected inode type\n");
2669 blkmap_free(dblkmap
);
2673 * problem in the inode type-specific semantic
2674 * checking, clear out the inode and get out
2677 *dirty
+= clear_dinode(mp
, dino
, lino
);
2688 * check nlinks feature, if it's a version 1 inode,
2689 * just leave nlinks alone. even if it's set wrong,
2690 * it'll be reset when read in.
2692 if (dinoc
->di_version
> XFS_DINODE_VERSION_1
&& !fs_inode_nlink
) {
2694 * do we have a fs/inode version mismatch with a valid
2695 * version 2 inode here that has to stay version 2 or
2698 if (INT_GET(dinoc
->di_nlink
, ARCH_CONVERT
) > XFS_MAXLINK_1
) {
2700 * yes. are nlink inodes allowed?
2702 if (fs_inode_nlink_allowed
) {
2704 * yes, update status variable which will
2705 * cause sb to be updated later.
2709 "version 2 inode %llu claims > %u links,",
2710 lino
, XFS_MAXLINK_1
);
2713 "updating superblock version number\n");
2716 "would update superblock version number\n");
2720 * no, have to convert back to onlinks
2721 * even if we lose some links
2724 "WARNING: version 2 inode %llu claims > %u links,",
2725 lino
, XFS_MAXLINK_1
);
2728 "converting back to version 1,\n\tthis may destroy %d links\n",
2729 INT_GET(dinoc
->di_nlink
, ARCH_CONVERT
)
2733 XFS_DINODE_VERSION_1
;
2734 INT_SET(dinoc
->di_nlink
, ARCH_CONVERT
, XFS_MAXLINK_1
);
2735 INT_SET(dinoc
->di_onlink
, ARCH_CONVERT
, XFS_MAXLINK_1
);
2740 "would convert back to version 1,\n\tthis might destroy %d links\n",
2741 INT_GET(dinoc
->di_nlink
, ARCH_CONVERT
)
2747 * do we have a v2 inode that we could convert back
2748 * to v1 without losing any links? if we do and
2749 * we have a mismatch between superblock bits and the
2750 * version bit, alter the version bit in this case.
2752 * the case where we lost links was handled above.
2754 do_warn("found version 2 inode %llu, ", lino
);
2756 do_warn("converting back to version 1\n");
2759 XFS_DINODE_VERSION_1
;
2760 INT_SET(dinoc
->di_onlink
, ARCH_CONVERT
, INT_GET(dinoc
->di_nlink
, ARCH_CONVERT
));
2764 do_warn("would convert back to version 1\n");
2770 * ok, if it's still a version 2 inode, it's going
2771 * to stay a version 2 inode. it should have a zero
2772 * onlink field, so clear it.
2774 if (dinoc
->di_version
> XFS_DINODE_VERSION_1
&&
2775 INT_GET(dinoc
->di_onlink
, ARCH_CONVERT
) > 0 && fs_inode_nlink
> 0) {
2778 "clearing obsolete nlink field in version 2 inode %llu, was %d, now 0\n",
2779 lino
, INT_GET(dinoc
->di_onlink
, ARCH_CONVERT
));
2780 INT_ZERO(dinoc
->di_onlink
, ARCH_CONVERT
);
2784 "would clear obsolete nlink field in version 2 inode %llu, currently %d\n",
2785 lino
, INT_GET(dinoc
->di_onlink
, ARCH_CONVERT
));
2790 return(retval
> 0 ? 1 : 0);
2794 * returns 1 if inode is used, 0 if free.
2795 * performs any necessary salvaging actions.
2796 * note that we leave the generation count alone
2797 * because nothing we could set it to would be
2798 * guaranteed to be correct so the best guess for
2799 * the correct value is just to leave it alone.
2801 * The trick is detecting empty files. For those,
2802 * the core and the forks should all be in the "empty"
2803 * or zero-length state -- a zero or possibly minimum length
2804 * (in the case of dirs) extent list -- although inline directories
2805 * and symlinks might be handled differently. So it should be
2806 * possible to sanity check them against each other.
2808 * If the forks are an empty extent list though, then forget it.
2809 * The file is toast anyway since we can't recover its storage.
2813 * mp -- mount structure
2814 * dino -- pointer to on-disk inode structure
2815 * agno/ino -- inode numbers
2816 * free -- whether the map thinks the inode is free (1 == free)
2817 * ino_discovery -- whether we should examine directory
2818 * contents to discover new inodes
2819 * check_dups -- whether we should check to see if the
2820 * inode references duplicate blocks
2821 * if so, we compare the inode's claimed
2822 * blocks against the contents of the
2823 * duplicate extent list but we don't
2824 * set the bitmap. If not, we set the
2825 * bitmap and try and detect multiply
2826 * claimed blocks using the bitmap.
2828 * dirty -- whether we changed the inode (1 == yes)
2829 * cleared -- whether we cleared the inode (1 == yes). In
2830 * no modify mode, if we would have cleared it
2831 * used -- 1 if the inode is used, 0 if free. In no modify
2832 * mode, whether the inode should be used or free
2833 * isa_dir -- 1 if the inode is a directory, 0 if not. In
2834 * no modify mode, if the inode would be a dir or not.
2836 * Return value -- 0 if the inode is good, 1 if it is/was corrupt
2840 process_dinode(xfs_mount_t
*mp
,
2842 xfs_agnumber_t agno
,
2850 int extra_attr_check
,
2854 const int verify_mode
= 0;
2855 const int uncertain
= 0;
2857 #ifdef XR_INODE_TRACE
2858 fprintf(stderr
, "processing inode %d/%d\n", agno
, ino
);
2860 return(process_dinode_int(mp
, dino
, agno
, ino
, was_free
, dirty
,
2861 cleared
, used
, verify_mode
, uncertain
,
2862 ino_discovery
, check_dups
, extra_attr_check
,
2867 * a more cursory check, check inode core, *DON'T* check forks
2868 * this basically just verifies whether the inode is an inode
2869 * and whether or not it has been totally trashed. returns 0
2870 * if the inode passes the cursory sanity check, 1 otherwise.
2873 verify_dinode(xfs_mount_t
*mp
,
2875 xfs_agnumber_t agno
,
2883 const int verify_mode
= 1;
2884 const int check_dups
= 0;
2885 const int ino_discovery
= 0;
2886 const int uncertain
= 0;
2888 return(process_dinode_int(mp
, dino
, agno
, ino
, 0, &dirty
,
2889 &cleared
, &used
, verify_mode
,
2890 uncertain
, ino_discovery
, check_dups
,
2891 0, &isa_dir
, &parent
));
2895 * like above only for inode on the uncertain list. it sets
2896 * the uncertain flag which makes process_dinode_int quieter.
2897 * returns 0 if the inode passes the cursory sanity check, 1 otherwise.
2900 verify_uncertain_dinode(xfs_mount_t
*mp
,
2902 xfs_agnumber_t agno
,
2910 const int verify_mode
= 1;
2911 const int check_dups
= 0;
2912 const int ino_discovery
= 0;
2913 const int uncertain
= 1;
2915 return(process_dinode_int(mp
, dino
, agno
, ino
, 0, &dirty
,
2916 &cleared
, &used
, verify_mode
,
2917 uncertain
, ino_discovery
, check_dups
,
2918 0, &isa_dir
, &parent
));