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/
37 #include "err_protos.h"
44 * Tag bad directory entries with this.
45 * We can't tag them with -1 since that will look like a
46 * data_unused_t instead of a data_entry_t.
48 #define BADFSINO ((xfs_ino_t)0xfeffffffffffffffULL)
51 * Known bad inode list. These are seen when the leaf and node
52 * block linkages are incorrect.
54 typedef struct dir2_bad
{
56 struct dir2_bad
*next
;
58 dir2_bad_t
*dir2_bad_list
;
66 if ((l
= malloc(sizeof(dir2_bad_t
))) == NULL
) {
67 do_error("malloc failed (%u bytes) dir2_add_badlist:ino %llu\n",
68 sizeof(dir2_bad_t
), ino
);
71 l
->next
= dir2_bad_list
;
82 for (l
= dir2_bad_list
; l
; l
= l
->next
)
89 * Multibuffer handling.
90 * V2 directory blocks can be noncontiguous, needing multiple buffers.
104 bplist
= calloc(nex
, sizeof(*bplist
));
105 if (bplist
== NULL
) {
106 do_error("couldn't malloc dir2 buffer list\n");
109 for (i
= 0; i
< nex
; i
++) {
110 bplist
[i
] = libxfs_readbuf(mp
->m_dev
,
111 XFS_FSB_TO_DADDR(mp
, bmp
[i
].startblock
),
112 XFS_FSB_TO_BB(mp
, bmp
[i
].blockcount
), 0);
116 dabuf
= malloc(XFS_DA_BUF_SIZE(nex
));
118 do_error("couldn't malloc dir2 buffer header\n");
125 dabuf
->bbcount
= (short)BTOBB(XFS_BUF_COUNT(bp
));
126 dabuf
->data
= XFS_BUF_PTR(bp
);
129 for (i
= 0, dabuf
->bbcount
= 0; i
< nex
; i
++) {
130 dabuf
->bps
[i
] = bp
= bplist
[i
];
131 dabuf
->bbcount
+= BTOBB(XFS_BUF_COUNT(bp
));
133 dabuf
->data
= malloc(BBTOB(dabuf
->bbcount
));
134 if (dabuf
->data
== NULL
) {
135 do_error("couldn't malloc dir2 buffer data\n");
138 for (i
= off
= 0; i
< nex
; i
++, off
+= XFS_BUF_COUNT(bp
)) {
140 bcopy(XFS_BUF_PTR(bp
), (char *)dabuf
->data
+ off
,
146 for (i
= 0; i
< nex
; i
++)
147 libxfs_putbuf(bplist
[i
]);
162 for (i
=off
=0; i
< dabuf
->nbuf
; i
++, off
+= XFS_BUF_COUNT(bp
)) {
164 bcopy((char *)dabuf
->data
+ off
, XFS_BUF_PTR(bp
),
193 if ((nbuf
= dabuf
->nbuf
) == 1) {
197 bplist
= malloc(nbuf
* sizeof(*bplist
));
198 if (bplist
== NULL
) {
199 do_error("couldn't malloc dir2 buffer list\n");
202 bcopy(dabuf
->bps
, bplist
, nbuf
* sizeof(*bplist
));
203 for (i
= off
= 0; i
< nbuf
; i
++, off
+= XFS_BUF_COUNT(bp
)) {
205 bcopy((char *)dabuf
->data
+ off
, XFS_BUF_PTR(bp
),
210 for (i
= error
= 0; i
< nbuf
; i
++) {
211 e
= libxfs_writebuf(bplist
[i
], 0);
229 if ((nbuf
= dabuf
->nbuf
) == 1) {
233 bplist
= malloc(nbuf
* sizeof(*bplist
));
234 if (bplist
== NULL
) {
235 do_error("couldn't malloc dir2 buffer list\n");
238 bcopy(dabuf
->bps
, bplist
, nbuf
* sizeof(*bplist
));
241 for (i
= 0; i
< nbuf
; i
++)
242 libxfs_putbuf(bplist
[i
]);
248 * walk tree from root to the left-most leaf block reading in
249 * blocks and setting up cursor. passes back file block number of the
250 * left-most leaf block if successful (bno). returns 1 if successful,
254 traverse_int_dir2block(xfs_mount_t
*mp
,
255 dir2_bt_cursor_t
*da_cursor
,
263 xfs_da_intnode_t
*node
;
266 * traverse down left-side of tree until we hit the
267 * left-most leaf block setting up the btree cursor along
270 bno
= mp
->m_dirleafblk
;
273 da_cursor
->active
= 0;
277 * read in each block along the way and set up cursor
279 nex
= blkmap_getn(da_cursor
->blkmap
, bno
, mp
->m_dirblkfsbs
,
285 bp
= da_read_buf(mp
, nex
, bmp
);
288 do_warn("can't read block %u for directory inode "
290 bno
, da_cursor
->ino
);
296 if (INT_GET(node
->hdr
.info
.magic
, ARCH_CONVERT
) ==
297 XFS_DIR2_LEAFN_MAGIC
) {
299 do_warn("found non-root LEAFN node in inode "
301 da_cursor
->ino
, bno
);
303 if (INT_GET(node
->hdr
.level
, ARCH_CONVERT
) >= 1) {
304 do_warn("LEAFN node level is %d inode %llu "
306 INT_GET(node
->hdr
.level
, ARCH_CONVERT
),
307 da_cursor
->ino
, bno
);
312 } else if (INT_GET(node
->hdr
.info
.magic
, ARCH_CONVERT
) !=
315 do_warn("bad dir magic number 0x%x in inode %llu "
317 INT_GET(node
->hdr
.info
.magic
, ARCH_CONVERT
),
318 da_cursor
->ino
, bno
);
321 if (INT_GET(node
->hdr
.count
, ARCH_CONVERT
) >
322 XFS_DA_NODE_ENTRIES(mp
)) {
324 do_warn("bad record count in inode %llu, count = %d, "
325 "max = %d\n", da_cursor
->ino
,
326 INT_GET(node
->hdr
.count
, ARCH_CONVERT
),
327 XFS_DA_NODE_ENTRIES(mp
));
332 * maintain level counter
335 i
= da_cursor
->active
=
336 INT_GET(node
->hdr
.level
, ARCH_CONVERT
);
338 if (INT_GET(node
->hdr
.level
, ARCH_CONVERT
) == i
- 1) {
341 do_warn("bad directory btree for directory "
349 da_cursor
->level
[i
].hashval
=
350 INT_GET(node
->btree
[0].hashval
, ARCH_CONVERT
);
351 da_cursor
->level
[i
].bp
= bp
;
352 da_cursor
->level
[i
].bno
= bno
;
353 da_cursor
->level
[i
].index
= 0;
356 * set up new bno for next level down
358 bno
= INT_GET(node
->btree
[0].before
, ARCH_CONVERT
);
359 } while (node
!= NULL
&& i
> 1);
362 * now return block number and get out
364 *rbno
= da_cursor
->level
[0].bno
= bno
;
368 while (i
> 1 && i
<= da_cursor
->active
) {
369 da_brelse(da_cursor
->level
[i
].bp
);
377 * blow out buffer for this level and all the rest above as well
378 * if error == 0, we are not expecting to encounter any unreleased
379 * buffers (e.g. if we do, it's a mistake). if error == 1, we're
380 * in an error-handling case so unreleased buffers may exist.
383 release_dir2_cursor_int(xfs_mount_t
*mp
,
384 dir2_bt_cursor_t
*cursor
,
388 int level
= prev_level
+ 1;
390 if (cursor
->level
[level
].bp
!= NULL
) {
392 do_warn("release_dir2_cursor_int got unexpected "
393 "non-null bp, dabno = %u\n",
394 cursor
->level
[level
].bno
);
398 da_brelse(cursor
->level
[level
].bp
);
399 cursor
->level
[level
].bp
= NULL
;
402 if (level
< cursor
->active
)
403 release_dir2_cursor_int(mp
, cursor
, level
, error
);
409 release_dir2_cursor(xfs_mount_t
*mp
,
410 dir2_bt_cursor_t
*cursor
,
413 release_dir2_cursor_int(mp
, cursor
, prev_level
, 0);
417 err_release_dir2_cursor(xfs_mount_t
*mp
,
418 dir2_bt_cursor_t
*cursor
,
421 release_dir2_cursor_int(mp
, cursor
, prev_level
, 1);
425 * make sure that all entries in all blocks along the right side of
426 * of the tree are used and hashval's are consistent. level is the
427 * level of the descendent block. returns 0 if good (even if it had
428 * to be fixed up), and 1 if bad. The right edge of the tree is
429 * technically a block boundary. This routine should be used then
430 * instead of verify_dir2_path().
433 verify_final_dir2_path(xfs_mount_t
*mp
,
434 dir2_bt_cursor_t
*cursor
,
437 xfs_da_intnode_t
*node
;
440 int this_level
= p_level
+ 1;
443 * the index should point to the next "unprocessed" entry
444 * in the block which should be the final (rightmost) entry
446 entry
= cursor
->level
[this_level
].index
;
447 node
= (xfs_da_intnode_t
*)(cursor
->level
[this_level
].bp
->data
);
449 * check internal block consistency on this level -- ensure
450 * that all entries are used, encountered and expected hashvals
453 if (entry
!= INT_GET(node
->hdr
.count
, ARCH_CONVERT
) - 1) {
454 do_warn("directory block used/count inconsistency - %d / %hu\n",
455 entry
, INT_GET(node
->hdr
.count
, ARCH_CONVERT
));
459 * hash values monotonically increasing ???
461 if (cursor
->level
[this_level
].hashval
>= INT_GET(node
->btree
[entry
].hashval
, ARCH_CONVERT
)) {
462 do_warn("directory/attribute block hashvalue inconsistency, "
463 "expected > %u / saw %u\n",
464 cursor
->level
[this_level
].hashval
,
465 INT_GET(node
->btree
[entry
].hashval
, ARCH_CONVERT
));
468 if (INT_GET(node
->hdr
.info
.forw
, ARCH_CONVERT
) != 0) {
469 do_warn("bad directory/attribute forward block pointer, "
470 "expected 0, saw %u\n",
471 INT_GET(node
->hdr
.info
.forw
, ARCH_CONVERT
));
475 do_warn("bad directory block in inode %llu\n", cursor
->ino
);
479 * keep track of greatest block # -- that gets
480 * us the length of the directory
482 if (cursor
->level
[this_level
].bno
> cursor
->greatest_bno
)
483 cursor
->greatest_bno
= cursor
->level
[this_level
].bno
;
486 * ok, now check descendant block number against this level
488 if (cursor
->level
[p_level
].bno
!= INT_GET(node
->btree
[entry
].before
, ARCH_CONVERT
)) {
492 if (cursor
->level
[p_level
].hashval
!= INT_GET(node
->btree
[entry
].hashval
, ARCH_CONVERT
)) {
494 do_warn("correcting bad hashval in non-leaf dir "
496 do_warn("\tin (level %d) in inode %llu.\n",
497 this_level
, cursor
->ino
);
498 INT_SET(node
->btree
[entry
].hashval
, ARCH_CONVERT
, cursor
->level
[p_level
].hashval
);
499 cursor
->level
[this_level
].dirty
++;
501 do_warn("would correct bad hashval in non-leaf dir "
503 do_warn("\tin (level %d) in inode %llu.\n",
504 this_level
, cursor
->ino
);
509 * release/write buffer
511 ASSERT(cursor
->level
[this_level
].dirty
== 0 ||
512 (cursor
->level
[this_level
].dirty
&& !no_modify
));
514 if (cursor
->level
[this_level
].dirty
&& !no_modify
)
515 da_bwrite(mp
, cursor
->level
[this_level
].bp
);
517 da_brelse(cursor
->level
[this_level
].bp
);
519 cursor
->level
[this_level
].bp
= NULL
;
522 * bail out if this is the root block (top of tree)
524 if (this_level
>= cursor
->active
) {
528 * set hashvalue to correctl reflect the now-validated
529 * last entry in this block and continue upwards validation
531 cursor
->level
[this_level
].hashval
= INT_GET(node
->btree
[entry
].hashval
, ARCH_CONVERT
);
533 return(verify_final_dir2_path(mp
, cursor
, this_level
));
537 * Verifies the path from a descendant block up to the root.
538 * Should be called when the descendant level traversal hits
539 * a block boundary before crossing the boundary (reading in a new
542 * the directory/attr btrees work differently to the other fs btrees.
543 * each interior block contains records that are <hashval, bno>
544 * pairs. The bno is a file bno, not a filesystem bno. The last
545 * hashvalue in the block <bno> will be <hashval>. BUT unlike
546 * the freespace btrees, the *last* value in each block gets
547 * propagated up the tree instead of the first value in each block.
548 * that is, the interior records point to child blocks and the *greatest*
549 * hash value contained by the child block is the one the block above
550 * uses as the key for the child block.
552 * level is the level of the descendent block. returns 0 if good,
553 * and 1 if bad. The descendant block may be a leaf block.
555 * the invariant here is that the values in the cursor for the
556 * levels beneath this level (this_level) and the cursor index
557 * for this level *must* be valid.
559 * that is, the hashval/bno info is accurate for all
560 * DESCENDANTS and match what the node[index] information
561 * for the current index in the cursor for this level.
563 * the index values in the cursor for the descendant level
564 * are allowed to be off by one as they will reflect the
565 * next entry at those levels to be processed.
567 * the hashvalue for the current level can't be set until
568 * we hit the last entry in the block so, it's garbage
569 * until set by this routine.
571 * bno and bp for the current block/level are always valid
572 * since they have to be set so we can get a buffer for the
576 verify_dir2_path(xfs_mount_t
*mp
,
577 dir2_bt_cursor_t
*cursor
,
580 xfs_da_intnode_t
*node
;
581 xfs_da_intnode_t
*newnode
;
586 int this_level
= p_level
+ 1;
591 * index is currently set to point to the entry that
592 * should be processed now in this level.
594 entry
= cursor
->level
[this_level
].index
;
595 node
= cursor
->level
[this_level
].bp
->data
;
598 * if this block is out of entries, validate this
599 * block and move on to the next block.
600 * and update cursor value for said level
602 if (entry
>= INT_GET(node
->hdr
.count
, ARCH_CONVERT
)) {
604 * update the hash value for this level before
605 * validating it. bno value should be ok since
606 * it was set when the block was first read in.
608 cursor
->level
[this_level
].hashval
=
609 INT_GET(node
->btree
[entry
- 1].hashval
, ARCH_CONVERT
);
612 * keep track of greatest block # -- that gets
613 * us the length of the directory
615 if (cursor
->level
[this_level
].bno
> cursor
->greatest_bno
)
616 cursor
->greatest_bno
= cursor
->level
[this_level
].bno
;
619 * validate the path for the current used-up block
622 if (verify_dir2_path(mp
, cursor
, this_level
))
625 * ok, now get the next buffer and check sibling pointers
627 dabno
= INT_GET(node
->hdr
.info
.forw
, ARCH_CONVERT
);
629 nex
= blkmap_getn(cursor
->blkmap
, dabno
, mp
->m_dirblkfsbs
,
632 do_warn("can't get map info for block %u of directory "
638 bp
= da_read_buf(mp
, nex
, bmp
);
641 do_warn("can't read block %u for directory inode "
649 * verify magic number and back pointer, sanity-check
650 * entry count, verify level
653 if (INT_GET(newnode
->hdr
.info
.magic
, ARCH_CONVERT
) != XFS_DA_NODE_MAGIC
) {
654 do_warn("bad magic number %x in block %u for directory "
656 INT_GET(newnode
->hdr
.info
.magic
, ARCH_CONVERT
), dabno
, cursor
->ino
);
659 if (INT_GET(newnode
->hdr
.info
.back
, ARCH_CONVERT
) != cursor
->level
[this_level
].bno
) {
660 do_warn("bad back pointer in block %u for directory "
665 if (INT_GET(newnode
->hdr
.count
, ARCH_CONVERT
) > XFS_DA_NODE_ENTRIES(mp
)) {
666 do_warn("entry count %d too large in block %u for "
667 "directory inode %llu\n",
668 INT_GET(newnode
->hdr
.count
, ARCH_CONVERT
), dabno
, cursor
->ino
);
671 if (INT_GET(newnode
->hdr
.level
, ARCH_CONVERT
) != this_level
) {
672 do_warn("bad level %d in block %u for directory inode "
674 INT_GET(newnode
->hdr
.level
, ARCH_CONVERT
), dabno
, cursor
->ino
);
682 * update cursor, write out the *current* level if
683 * required. don't write out the descendant level
685 ASSERT(cursor
->level
[this_level
].dirty
== 0 ||
686 (cursor
->level
[this_level
].dirty
&& !no_modify
));
688 if (cursor
->level
[this_level
].dirty
&& !no_modify
)
689 da_bwrite(mp
, cursor
->level
[this_level
].bp
);
691 da_brelse(cursor
->level
[this_level
].bp
);
692 cursor
->level
[this_level
].bp
= bp
;
693 cursor
->level
[this_level
].dirty
= 0;
694 cursor
->level
[this_level
].bno
= dabno
;
695 cursor
->level
[this_level
].hashval
= INT_GET(newnode
->btree
[0].hashval
, ARCH_CONVERT
);
698 entry
= cursor
->level
[this_level
].index
= 0;
701 * ditto for block numbers
703 if (cursor
->level
[p_level
].bno
!= INT_GET(node
->btree
[entry
].before
, ARCH_CONVERT
)) {
707 * ok, now validate last hashvalue in the descendant
708 * block against the hashval in the current entry
710 if (cursor
->level
[p_level
].hashval
!= INT_GET(node
->btree
[entry
].hashval
, ARCH_CONVERT
)) {
712 do_warn("correcting bad hashval in interior dir "
714 do_warn("\tin (level %d) in inode %llu.\n",
715 this_level
, cursor
->ino
);
716 INT_SET(node
->btree
[entry
].hashval
, ARCH_CONVERT
, cursor
->level
[p_level
].hashval
);
717 cursor
->level
[this_level
].dirty
++;
719 do_warn("would correct bad hashval in interior dir "
721 do_warn("\tin (level %d) in inode %llu.\n",
722 this_level
, cursor
->ino
);
726 * increment index for this level to point to next entry
727 * (which should point to the next descendant block)
729 cursor
->level
[this_level
].index
++;
734 * Fix up a shortform directory which was in long form (i8count set)
735 * and is now in short form (i8count clear).
736 * Return pointer to the end of the data when done.
739 process_sf_dir2_fixi8(
741 xfs_dir2_sf_entry_t
**next_sfep
)
744 xfs_dir2_sf_t
*newsfp
;
745 xfs_dir2_sf_entry_t
*newsfep
;
746 xfs_dir2_sf_t
*oldsfp
;
747 xfs_dir2_sf_entry_t
*oldsfep
;
751 oldsize
= (__psint_t
)*next_sfep
- (__psint_t
)sfp
;
752 oldsfp
= malloc(oldsize
);
753 if (oldsfp
== NULL
) {
754 do_error("couldn't malloc dir2 shortform copy\n");
757 memmove(oldsfp
, newsfp
, oldsize
);
758 INT_SET(newsfp
->hdr
.count
, ARCH_CONVERT
, INT_GET(oldsfp
->hdr
.count
, ARCH_CONVERT
));
759 newsfp
->hdr
.i8count
= 0;
760 ino
= XFS_DIR2_SF_GET_INUMBER_ARCH(oldsfp
, &oldsfp
->hdr
.parent
, ARCH_CONVERT
);
761 XFS_DIR2_SF_PUT_INUMBER_ARCH(newsfp
, &ino
, &newsfp
->hdr
.parent
, ARCH_CONVERT
);
762 oldsfep
= XFS_DIR2_SF_FIRSTENTRY(oldsfp
);
763 newsfep
= XFS_DIR2_SF_FIRSTENTRY(newsfp
);
764 while ((int)((char *)oldsfep
- (char *)oldsfp
) < oldsize
) {
765 newsfep
->namelen
= oldsfep
->namelen
;
766 XFS_DIR2_SF_PUT_OFFSET_ARCH(newsfep
,
767 XFS_DIR2_SF_GET_OFFSET_ARCH(oldsfep
, ARCH_CONVERT
), ARCH_CONVERT
);
768 memmove(newsfep
->name
, oldsfep
->name
, newsfep
->namelen
);
769 ino
= XFS_DIR2_SF_GET_INUMBER_ARCH(oldsfp
,
770 XFS_DIR2_SF_INUMBERP(oldsfep
), ARCH_CONVERT
);
771 XFS_DIR2_SF_PUT_INUMBER_ARCH(newsfp
, &ino
,
772 XFS_DIR2_SF_INUMBERP(newsfep
), ARCH_CONVERT
);
773 oldsfep
= XFS_DIR2_SF_NEXTENTRY(oldsfp
, oldsfep
);
774 newsfep
= XFS_DIR2_SF_NEXTENTRY(newsfp
, newsfep
);
776 *next_sfep
= newsfep
;
781 * Regenerate legal (minimal) offsets for the shortform directory.
784 process_sf_dir2_fixoff(
789 xfs_dir2_sf_entry_t
*sfep
;
792 for (i
= 0, sfp
= &dip
->di_u
.di_dir2sf
,
793 sfep
= XFS_DIR2_SF_FIRSTENTRY(sfp
),
794 offset
= XFS_DIR2_DATA_FIRST_OFFSET
;
795 i
< INT_GET(sfp
->hdr
.count
, ARCH_CONVERT
);
796 i
++, sfep
= XFS_DIR2_SF_NEXTENTRY(sfp
, sfep
)) {
797 XFS_DIR2_SF_PUT_OFFSET_ARCH(sfep
, offset
, ARCH_CONVERT
);
798 offset
+= XFS_DIR2_DATA_ENTSIZE(sfep
->namelen
);
803 * this routine performs inode discovery and tries to fix things
804 * in place. available redundancy -- inode data size should match
805 * used directory space in inode.
806 * a non-zero return value means the directory is bogus and should be blasted.
815 int *dino_dirty
, /* out - 1 if dinode buffer dirty */
816 char *dirname
, /* directory pathname */
817 xfs_ino_t
*parent
, /* out - NULLFSINO if entry not exist */
818 int *repair
) /* out - 1 if dir was fixed up */
824 __int64_t ino_dir_size
;
826 ino_tree_node_t
*irec_p
;
828 char *junkreason
= NULL
;
831 char name
[MAXNAMELEN
+ 1];
833 xfs_dir2_sf_entry_t
*next_sfep
;
837 xfs_dir2_sf_entry_t
*sfep
;
840 xfs_dir2_sf_entry_t
*tmp_sfep
;
843 sfp
= &dip
->di_u
.di_dir2sf
;
844 max_size
= XFS_DFORK_DSIZE_ARCH(dip
, mp
, ARCH_CONVERT
);
845 num_entries
= INT_GET(sfp
->hdr
.count
, ARCH_CONVERT
);
846 ino_dir_size
= INT_GET(dip
->di_core
.di_size
, ARCH_CONVERT
);
847 offset
= XFS_DIR2_DATA_FIRST_OFFSET
;
848 i8
= bad_offset
= *repair
= 0;
850 ASSERT(ino_dir_size
<= max_size
);
853 * check for bad entry count
855 if (num_entries
* XFS_DIR2_SF_ENTSIZE_BYNAME(sfp
, 1) +
856 XFS_DIR2_SF_HDR_SIZE(0) > max_size
||
861 * run through entries, stop at first bad entry, don't need
862 * to check for .. since that's encoded in its own field
864 sfep
= next_sfep
= XFS_DIR2_SF_FIRSTENTRY(sfp
);
866 i
< num_entries
&& ino_dir_size
> (char *)next_sfep
- (char *)sfp
;
872 lino
= XFS_DIR2_SF_GET_INUMBER_ARCH(sfp
, XFS_DIR2_SF_INUMBERP(sfep
), ARCH_CONVERT
);
874 * if entry points to self, junk it since only '.' or '..'
875 * should do that and shortform dirs don't contain either
876 * entry. if inode number is invalid, trash entry.
877 * if entry points to special inodes, trash it.
878 * if inode is unknown but number is valid,
879 * add it to the list of uncertain inodes. don't
880 * have to worry about an entry pointing to a
881 * deleted lost+found inode because the entry was
882 * deleted at the same time that the inode was cleared.
886 junkreason
= "current";
887 } else if (verify_inum(mp
, lino
)) {
889 junkreason
= "invalid";
890 } else if (lino
== mp
->m_sb
.sb_rbmino
) {
892 junkreason
= "realtime bitmap";
893 } else if (lino
== mp
->m_sb
.sb_rsumino
) {
895 junkreason
= "realtime summary";
896 } else if (lino
== mp
->m_sb
.sb_uquotino
) {
898 junkreason
= "user quota";
899 } else if (lino
== mp
->m_sb
.sb_gquotino
) {
901 junkreason
= "group quota";
902 } else if ((irec_p
= find_inode_rec(XFS_INO_TO_AGNO(mp
, lino
),
903 XFS_INO_TO_AGINO(mp
, lino
))) != NULL
) {
905 * if inode is marked free and we're in inode
906 * discovery mode, leave the entry alone for now.
907 * if the inode turns out to be used, we'll figure
908 * that out when we scan it. If the inode really
909 * is free, we'll hit this code again in phase 4
910 * after we've finished inode discovery and blow
911 * out the entry then.
913 ino_off
= XFS_INO_TO_AGINO(mp
, lino
) -
914 irec_p
->ino_startnum
;
915 ASSERT(is_inode_confirmed(irec_p
, ino_off
));
916 if (is_inode_free(irec_p
, ino_off
) && !ino_discovery
) {
920 } else if (ino_discovery
) {
922 * put the inode on the uncertain list. we'll
923 * pull the inode off the list and check it later.
924 * if the inode turns out be bogus, we'll delete
925 * this entry in phase 6.
927 add_inode_uncertain(mp
, lino
, 0);
930 * blow the entry out. we know about all
931 * undiscovered entries now (past inode discovery
932 * phase) so this is clearly a bogus entry.
935 junkreason
= "non-existent";
937 namelen
= sfep
->namelen
;
939 do_warn("entry \"%*.*s\" in shortform directory %llu "
940 "references %s inode %llu\n",
941 namelen
, namelen
, sfep
->name
, ino
, junkreason
,
945 * if we're really lucky, this is
946 * the last entry in which case we
947 * can use the dir size to set the
948 * namelen value. otherwise, forget
949 * it because we're not going to be
950 * able to find the next entry.
954 if (i
== num_entries
- 1) {
955 namelen
= ino_dir_size
-
956 ((__psint_t
) &sfep
->name
[0] -
959 do_warn("zero length entry in "
960 "shortform dir %llu, resetting "
963 sfep
->namelen
= namelen
;
965 do_warn("zero length entry in "
966 "shortform dir %llu, would set "
971 do_warn("zero length entry in shortform dir "
975 do_warn(", junking %d entries\n",
978 do_warn(", would junk %d entries\n",
981 * don't process the rest of the directory,
982 * break out of processing looop
986 } else if ((__psint_t
) sfep
- (__psint_t
) sfp
+
987 + XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp
, sfep
)
991 if (i
== num_entries
- 1) {
992 namelen
= ino_dir_size
-
993 ((__psint_t
) &sfep
->name
[0] -
995 do_warn("size of last entry overflows space "
996 "left in in shortform dir %llu, ",
999 do_warn("resetting to %d\n",
1001 sfep
->namelen
= namelen
;
1004 do_warn("would reset to %d\n",
1008 do_warn("size of entry #%d overflows space "
1009 "left in in shortform dir %llu\n",
1012 if (i
== num_entries
- 1)
1013 do_warn("junking entry #%d\n",
1016 do_warn("junking %d entries\n",
1019 if (i
== num_entries
- 1)
1020 do_warn("would junk entry "
1024 do_warn("would junk %d "
1034 * check for illegal chars in name.
1035 * no need to check for bad length because
1036 * the length value is stored in a byte
1037 * so it can't be too big, it can only wrap
1039 if (namecheck((char *)&sfep
->name
[0], namelen
)) {
1043 do_warn("entry contains illegal character in shortform "
1049 if (XFS_DIR2_SF_GET_OFFSET_ARCH(sfep
, ARCH_CONVERT
) < offset
) {
1050 do_warn("entry contains offset out of order in "
1051 "shortform dir %llu\n",
1055 offset
= XFS_DIR2_SF_GET_OFFSET_ARCH(sfep
, ARCH_CONVERT
) +
1056 XFS_DIR2_DATA_ENTSIZE(namelen
);
1059 * junk the entry by copying up the rest of the
1060 * fork over the current entry and decrementing
1061 * the entry count. if we're in no_modify mode,
1062 * just issue the warning instead. then continue
1063 * the loop with the next_sfep pointer set to the
1064 * correct place in the fork and other counters
1065 * properly set to reflect the deletion if it
1069 bcopy(sfep
->name
, name
, namelen
);
1070 name
[namelen
] = '\0';
1074 XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp
, sfep
);
1075 INT_MOD(dip
->di_core
.di_size
, ARCH_CONVERT
, -(tmp_elen
));
1076 ino_dir_size
-= tmp_elen
;
1078 tmp_sfep
= (xfs_dir2_sf_entry_t
*)
1079 ((__psint_t
) sfep
+ tmp_elen
);
1080 tmp_len
= max_size
- ((__psint_t
) tmp_sfep
1083 memmove(sfep
, tmp_sfep
, tmp_len
);
1085 INT_MOD(sfp
->hdr
.count
, ARCH_CONVERT
, -1);
1087 bzero((void *) ((__psint_t
) sfep
+ tmp_len
),
1091 * reset the tmp value to the current
1092 * pointer so we'll process the entry
1098 * WARNING: drop the index i by one
1099 * so it matches the decremented count
1100 * for accurate comparisons later
1107 do_warn("junking entry \"%s\" in directory "
1111 do_warn("would have junked entry \"%s\" in "
1112 "directory inode %llu\n",
1115 } else if (lino
> XFS_DIR2_MAX_SHORT_INUM
)
1118 * go onto next entry unless we've just junked an
1119 * entry in which the current entry pointer points
1120 * to an unprocessed entry. have to take into zero-len
1121 * entries into account in no modify mode since we
1122 * calculate size based on next_sfep.
1124 next_sfep
= (tmp_sfep
== NULL
)
1125 ? (xfs_dir2_sf_entry_t
*) ((__psint_t
) sfep
1127 ? XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp
,
1129 : XFS_DIR2_SF_ENTSIZE_BYNAME(sfp
,
1134 /* sync up sizes and entry counts */
1136 if (INT_GET(sfp
->hdr
.count
, ARCH_CONVERT
) != i
) {
1138 do_warn("would have corrected entry count in directory "
1139 "%llu from %d to %d\n",
1140 ino
, INT_GET(sfp
->hdr
.count
, ARCH_CONVERT
), i
);
1142 do_warn("corrected entry count in directory %llu, was "
1144 ino
, INT_GET(sfp
->hdr
.count
, ARCH_CONVERT
), i
);
1145 INT_SET(sfp
->hdr
.count
, ARCH_CONVERT
, i
);
1151 if (sfp
->hdr
.i8count
!= i8
) {
1153 do_warn("would have corrected i8 count in directory "
1154 "%llu from %d to %d\n",
1155 ino
, sfp
->hdr
.i8count
, i8
);
1157 do_warn("corrected i8 count in directory %llu, was %d, "
1159 ino
, sfp
->hdr
.i8count
, i8
);
1161 process_sf_dir2_fixi8(sfp
, &next_sfep
);
1163 sfp
->hdr
.i8count
= i8
;
1169 if ((__psint_t
) next_sfep
- (__psint_t
) sfp
!= ino_dir_size
) {
1171 do_warn("would have corrected directory %llu size from "
1173 ino
, (__int64_t
) ino_dir_size
,
1174 (__int64_t
)((__psint_t
)next_sfep
-
1177 do_warn("corrected directory %llu size, was %lld, now "
1179 ino
, (__int64_t
) ino_dir_size
,
1180 (__int64_t
)((__psint_t
)next_sfep
-
1183 INT_SET(dip
->di_core
.di_size
, ARCH_CONVERT
, (xfs_fsize_t
)((__psint_t
)next_sfep
-
1189 if (offset
+ (INT_GET(sfp
->hdr
.count
, ARCH_CONVERT
) + 2) * sizeof(xfs_dir2_leaf_entry_t
) +
1190 sizeof(xfs_dir2_block_tail_t
) > mp
->m_dirblksize
) {
1191 do_warn("directory %llu offsets too high\n", ino
);
1196 do_warn("would have corrected entry offsets in "
1200 do_warn("corrected entry offsets in directory %llu\n",
1202 process_sf_dir2_fixoff(dip
);
1209 * check parent (..) entry
1211 *parent
= XFS_DIR2_SF_GET_INUMBER_ARCH(sfp
, &sfp
->hdr
.parent
, ARCH_CONVERT
);
1214 * if parent entry is bogus, null it out. we'll fix it later .
1216 if (verify_inum(mp
, *parent
)) {
1218 do_warn("bogus .. inode number (%llu) in directory inode "
1221 *parent
= NULLFSINO
;
1223 do_warn("clearing inode number\n");
1225 XFS_DIR2_SF_PUT_INUMBER_ARCH(sfp
, &zero
, &sfp
->hdr
.parent
, ARCH_CONVERT
);
1229 do_warn("would clear inode number\n");
1231 } else if (ino
== mp
->m_sb
.sb_rootino
&& ino
!= *parent
) {
1233 * root directories must have .. == .
1236 do_warn("corrected root directory %llu .. entry, was "
1240 XFS_DIR2_SF_PUT_INUMBER_ARCH(sfp
, parent
, &sfp
->hdr
.parent
, ARCH_CONVERT
);
1244 do_warn("would have corrected root directory %llu .. "
1245 "entry from %llu to %llu\n",
1248 } else if (ino
== *parent
&& ino
!= mp
->m_sb
.sb_rootino
) {
1250 * likewise, non-root directories can't have .. pointing
1253 *parent
= NULLFSINO
;
1254 do_warn("bad .. entry in directory inode %llu, points to "
1258 do_warn(" clearing inode number\n");
1260 XFS_DIR2_SF_PUT_INUMBER_ARCH(sfp
, &zero
, &sfp
->hdr
.parent
, ARCH_CONVERT
);
1264 do_warn(" would clear inode number\n");
1272 * Process one directory data block.
1281 char *dirname
, /* directory pathname */
1282 xfs_ino_t
*parent
, /* out - NULLFSINO if entry not exist */
1284 int *dot
, /* out - 1 if there is a dot, else 0 */
1285 int *dotdot
, /* out - 1 if there's a dotdot, else 0 */
1290 xfs_dir2_data_free_t
*bf
;
1292 char *clearreason
= NULL
;
1294 xfs_dir2_data_entry_t
*dep
;
1295 xfs_dir2_data_free_t
*dfp
;
1296 xfs_dir2_data_unused_t
*dup
;
1300 ino_tree_node_t
*irec_p
;
1307 bf
= d
->hdr
.bestfree
;
1309 badbest
= lastfree
= freeseen
= 0;
1310 if (INT_GET(bf
[0].length
, ARCH_CONVERT
) == 0) {
1311 badbest
|= INT_GET(bf
[0].offset
, ARCH_CONVERT
) != 0;
1314 if (INT_GET(bf
[1].length
, ARCH_CONVERT
) == 0) {
1315 badbest
|= INT_GET(bf
[1].offset
, ARCH_CONVERT
) != 0;
1318 if (INT_GET(bf
[2].length
, ARCH_CONVERT
) == 0) {
1319 badbest
|= INT_GET(bf
[2].offset
, ARCH_CONVERT
) != 0;
1322 badbest
|= INT_GET(bf
[0].length
, ARCH_CONVERT
) < INT_GET(bf
[1].length
, ARCH_CONVERT
);
1323 badbest
|= INT_GET(bf
[1].length
, ARCH_CONVERT
) < INT_GET(bf
[2].length
, ARCH_CONVERT
);
1324 while (ptr
< endptr
) {
1325 dup
= (xfs_dir2_data_unused_t
*)ptr
;
1327 * If it's unused, look for the space in the bestfree table.
1328 * If we find it, account for that, else make sure it doesn't
1331 if (INT_GET(dup
->freetag
, ARCH_CONVERT
) == XFS_DIR2_DATA_FREE_TAG
) {
1332 if (ptr
+ INT_GET(dup
->length
, ARCH_CONVERT
) > endptr
|| INT_GET(dup
->length
, ARCH_CONVERT
) == 0 ||
1333 (INT_GET(dup
->length
, ARCH_CONVERT
) & (XFS_DIR2_DATA_ALIGN
- 1)))
1335 if (INT_GET(*XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(dup
, ARCH_CONVERT
), ARCH_CONVERT
) !=
1336 (char *)dup
- (char *)d
)
1338 badbest
|= lastfree
!= 0;
1339 dfp
= xfs_dir2_data_freefind(d
, dup
);
1342 badbest
|= (freeseen
& (1 << i
)) != 0;
1345 badbest
|= INT_GET(dup
->length
, ARCH_CONVERT
) > INT_GET(bf
[2].length
, ARCH_CONVERT
);
1346 ptr
+= INT_GET(dup
->length
, ARCH_CONVERT
);
1350 dep
= (xfs_dir2_data_entry_t
*)ptr
;
1351 if (ptr
+ XFS_DIR2_DATA_ENTSIZE(dep
->namelen
) > endptr
)
1353 if (INT_GET(*XFS_DIR2_DATA_ENTRY_TAG_P(dep
), ARCH_CONVERT
) != (char *)dep
- (char *)d
)
1355 ptr
+= XFS_DIR2_DATA_ENTSIZE(dep
->namelen
);
1359 * Dropped out before we processed everything, give up.
1360 * Phase 6 will kill this block if we don't kill the inode.
1362 if (ptr
!= endptr
) {
1363 do_warn("corrupt block %u in directory inode %llu\n",
1366 do_warn("\twill junk block\n");
1368 do_warn("\twould junk block\n");
1373 * Process the entries now.
1375 while (ptr
< endptr
) {
1376 dup
= (xfs_dir2_data_unused_t
*)ptr
;
1377 if (INT_GET(dup
->freetag
, ARCH_CONVERT
) == XFS_DIR2_DATA_FREE_TAG
) {
1378 ptr
+= INT_GET(dup
->length
, ARCH_CONVERT
);
1381 dep
= (xfs_dir2_data_entry_t
*)ptr
;
1383 * We may have to blow out an entry because of bad inode
1384 * numbers. Do NOT touch the name until after we've computed
1385 * the hashvalue and done a namecheck() on the name.
1387 if (!ino_discovery
&& INT_GET(dep
->inumber
, ARCH_CONVERT
) == BADFSINO
) {
1389 * Don't do a damned thing. We already found this
1390 * (or did it ourselves) during phase 3.
1393 } else if (verify_inum(mp
, INT_GET(dep
->inumber
, ARCH_CONVERT
))) {
1395 * Bad inode number. Clear the inode number and the
1396 * entry will get removed later. We don't trash the
1397 * directory since it's still structurally intact.
1400 clearreason
= "invalid";
1401 } else if (INT_GET(dep
->inumber
, ARCH_CONVERT
) == mp
->m_sb
.sb_rbmino
) {
1403 clearreason
= "realtime bitmap";
1404 } else if (INT_GET(dep
->inumber
, ARCH_CONVERT
) == mp
->m_sb
.sb_rsumino
) {
1406 clearreason
= "realtime summary";
1407 } else if (INT_GET(dep
->inumber
, ARCH_CONVERT
) == mp
->m_sb
.sb_uquotino
) {
1409 clearreason
= "user quota";
1410 } else if (INT_GET(dep
->inumber
, ARCH_CONVERT
) == mp
->m_sb
.sb_gquotino
) {
1412 clearreason
= "group quota";
1413 } else if (INT_GET(dep
->inumber
, ARCH_CONVERT
) == old_orphanage_ino
) {
1415 * Do nothing, silently ignore it, entry has already
1416 * been marked TBD since old_orphanage_ino is set
1420 } else if ((irec_p
= find_inode_rec(
1421 XFS_INO_TO_AGNO(mp
, INT_GET(dep
->inumber
, ARCH_CONVERT
)),
1422 XFS_INO_TO_AGINO(mp
, INT_GET(dep
->inumber
, ARCH_CONVERT
)))) != NULL
) {
1424 * Inode recs should have only confirmed inodes in them.
1427 XFS_INO_TO_AGINO(mp
, INT_GET(dep
->inumber
, ARCH_CONVERT
)) -
1428 irec_p
->ino_startnum
;
1429 ASSERT(is_inode_confirmed(irec_p
, ino_off
));
1431 * If inode is marked free and we're in inode discovery
1432 * mode, leave the entry alone for now. If the inode
1433 * turns out to be used, we'll figure that out when we
1434 * scan it. If the inode really is free, we'll hit this
1435 * code again in phase 4 after we've finished inode
1436 * discovery and blow out the entry then.
1438 if (!ino_discovery
&& is_inode_free(irec_p
, ino_off
)) {
1440 clearreason
= "free";
1443 } else if (ino_discovery
) {
1444 add_inode_uncertain(mp
, INT_GET(dep
->inumber
, ARCH_CONVERT
), 0);
1448 clearreason
= "non-existent";
1451 do_warn("entry \"%*.*s\" at block %u offset %d in "
1452 "directory inode %llu references %s inode "
1454 dep
->namelen
, dep
->namelen
, dep
->name
,
1455 da_bno
, (char *)ptr
- (char *)d
, ino
,
1456 clearreason
, INT_GET(dep
->inumber
, ARCH_CONVERT
));
1458 * If the name length is 0 (illegal) make it 1 and blast
1461 if (dep
->namelen
== 0) {
1462 do_warn("entry at block %u offset %d in directory "
1463 "inode %llu has 0 namelength\n",
1464 da_bno
, (char *)ptr
- (char *)d
, ino
);
1470 * If needed to clear the inode number, do it now.
1474 do_warn("\tclearing inode number in entry at "
1476 (char *)ptr
- (char *)d
);
1477 INT_SET(dep
->inumber
, ARCH_CONVERT
, BADFSINO
);
1480 do_warn("\twould clear inode number in entry "
1481 "at offset %d...\n",
1482 (char *)ptr
- (char *)d
);
1486 * Only complain about illegal names in phase 3 (when inode
1487 * discovery is turned on). Otherwise, we'd complain a lot
1490 junkit
= INT_GET(dep
->inumber
, ARCH_CONVERT
) == BADFSINO
;
1491 nm_illegal
= namecheck((char *)dep
->name
, dep
->namelen
);
1492 if (ino_discovery
&& nm_illegal
) {
1493 do_warn("entry at block %u offset %d in directory "
1494 "inode %llu has illegal name \"%*.*s\": ",
1495 da_bno
, (char *)ptr
- (char *)d
, ino
,
1496 dep
->namelen
, dep
->namelen
, dep
->name
);
1500 * Now we can mark entries with BADFSINO's bad.
1502 if (!no_modify
&& INT_GET(dep
->inumber
, ARCH_CONVERT
) == BADFSINO
) {
1508 * Special .. entry processing.
1510 if (dep
->namelen
== 2 &&
1511 dep
->name
[0] == '.' && dep
->name
[1] == '.') {
1514 *parent
= INT_GET(dep
->inumber
, ARCH_CONVERT
);
1516 * What if .. == .? Legal only in the root
1517 * inode. Blow out entry and set parent to
1518 * NULLFSINO otherwise.
1520 if (ino
== INT_GET(dep
->inumber
, ARCH_CONVERT
) &&
1521 ino
!= mp
->m_sb
.sb_rootino
) {
1522 *parent
= NULLFSINO
;
1523 do_warn("bad .. entry in directory "
1524 "inode %llu, points to self: ",
1529 * We have to make sure that . == .. in the
1532 else if (ino
!= INT_GET(dep
->inumber
, ARCH_CONVERT
) &&
1533 ino
== mp
->m_sb
.sb_rootino
) {
1534 do_warn("bad .. entry in root "
1535 "directory inode %llu, was "
1537 ino
, INT_GET(dep
->inumber
, ARCH_CONVERT
));
1539 do_warn("correcting\n");
1540 INT_SET(dep
->inumber
, ARCH_CONVERT
, ino
);
1543 do_warn("would correct\n");
1548 * Can't fix the directory unless we know which ..
1549 * entry is the right one. Both have valid inode
1550 * numbers or we wouldn't be here. So since both
1551 * seem equally valid, trash this one.
1554 do_warn("multiple .. entries in directory "
1561 * Special . entry processing.
1563 else if (dep
->namelen
== 1 && dep
->name
[0] == '.') {
1566 if (INT_GET(dep
->inumber
, ARCH_CONVERT
) != ino
) {
1567 do_warn("bad . entry in directory "
1568 "inode %llu, was %llu: ",
1569 ino
, INT_GET(dep
->inumber
, ARCH_CONVERT
));
1571 do_warn("correcting\n");
1572 INT_SET(dep
->inumber
, ARCH_CONVERT
, ino
);
1575 do_warn("would correct\n");
1579 do_warn("multiple . entries in directory "
1586 * All other entries -- make sure only . references self.
1588 else if (INT_GET(dep
->inumber
, ARCH_CONVERT
) == ino
) {
1589 do_warn("entry \"%*.*s\" in directory inode %llu "
1591 dep
->namelen
, dep
->namelen
, dep
->name
, ino
);
1595 * Clear junked entries.
1601 do_warn("clearing entry\n");
1603 do_warn("would clear entry\n");
1607 * Advance to the next entry.
1609 ptr
+= XFS_DIR2_DATA_ENTSIZE(dep
->namelen
);
1612 * Check the bestfree table.
1614 if (freeseen
!= 7 || badbest
) {
1615 do_warn("bad bestfree table in block %u in directory inode "
1619 do_warn("repairing table\n");
1620 libxfs_dir2_data_freescan(mp
, d
, &i
, endptr
);
1623 do_warn("would repair table\n");
1630 * Process a block-format directory.
1639 int *dino_dirty
, /* out - 1 if dinode buffer dirty */
1640 char *dirname
, /* directory pathname */
1641 xfs_ino_t
*parent
, /* out - NULLFSINO if entry not exist */
1643 int *dot
, /* out - 1 if there is a dot, else 0 */
1644 int *dotdot
, /* out - 1 if there's a dotdot, else 0 */
1645 int *repair
) /* out - 1 if something was fixed */
1647 xfs_dir2_block_t
*block
;
1648 xfs_dir2_leaf_entry_t
*blp
;
1651 xfs_dir2_block_tail_t
*btp
;
1655 *repair
= *dot
= *dotdot
= 0;
1656 *parent
= NULLFSINO
;
1657 nex
= blkmap_getn(blkmap
, mp
->m_dirdatablk
, mp
->m_dirblkfsbs
, &bmp
);
1659 do_warn("block %u for directory inode %llu is missing\n",
1660 mp
->m_dirdatablk
, ino
);
1663 bp
= da_read_buf(mp
, nex
, bmp
);
1666 do_warn("can't read block %u for directory inode %llu\n",
1667 mp
->m_dirdatablk
, ino
);
1674 if (INT_GET(block
->hdr
.magic
, ARCH_CONVERT
) != XFS_DIR2_BLOCK_MAGIC
)
1675 do_warn("bad directory block magic # %#x in block %u for "
1676 "directory inode %llu\n",
1677 INT_GET(block
->hdr
.magic
, ARCH_CONVERT
), mp
->m_dirdatablk
, ino
);
1679 * process the data area
1680 * this also checks & fixes the bestfree
1682 btp
= XFS_DIR2_BLOCK_TAIL_P(mp
, block
);
1683 blp
= XFS_DIR2_BLOCK_LEAF_P_ARCH(btp
, ARCH_CONVERT
);
1685 * Don't let this go past the end of the block.
1687 if ((char *)blp
> (char *)btp
)
1688 blp
= (xfs_dir2_leaf_entry_t
*)btp
;
1689 rval
= process_dir2_data(mp
, ino
, dip
, ino_discovery
, dirname
, parent
,
1690 bp
, dot
, dotdot
, mp
->m_dirdatablk
, (char *)blp
);
1691 if (bp
->dirty
&& !no_modify
) {
1700 * Validates leaf contents, node format directories only.
1701 * magic number and sibling pointers checked by caller.
1702 * Returns 0 if block is ok, 1 if the block is bad.
1703 * Looking for: out of order hash values, bad stale counts.
1706 process_leaf_block_dir2(
1708 xfs_dir2_leaf_t
*leaf
,
1711 xfs_dahash_t last_hashval
,
1712 xfs_dahash_t
*next_hashval
)
1717 for (i
= stale
= 0; i
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
); i
++) {
1718 if ((char *)&leaf
->ents
[i
] >= (char *)leaf
+ mp
->m_dirblksize
) {
1719 do_warn("bad entry count in block %u of directory "
1724 if (INT_GET(leaf
->ents
[i
].address
, ARCH_CONVERT
) == XFS_DIR2_NULL_DATAPTR
)
1726 else if (INT_GET(leaf
->ents
[i
].hashval
, ARCH_CONVERT
) < last_hashval
) {
1727 do_warn("bad hash ordering in block %u of directory "
1732 *next_hashval
= last_hashval
= INT_GET(leaf
->ents
[i
].hashval
, ARCH_CONVERT
);
1734 if (stale
!= INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
)) {
1735 do_warn("bad stale count in block %u of directory inode %llu\n",
1743 * Returns 0 if the directory is ok, 1 if it has to be rebuilt.
1746 process_leaf_level_dir2(
1748 dir2_bt_cursor_t
*da_cursor
,
1754 xfs_dahash_t current_hashval
;
1756 xfs_dahash_t greatest_hashval
;
1758 xfs_dir2_leaf_t
*leaf
;
1760 xfs_dablk_t prev_bno
;
1762 da_bno
= da_cursor
->level
[0].bno
;
1763 ino
= da_cursor
->ino
;
1766 current_hashval
= 0;
1770 nex
= blkmap_getn(da_cursor
->blkmap
, da_bno
, mp
->m_dirblkfsbs
,
1773 * Directory code uses 0 as the NULL block pointer since 0
1774 * is the root block and no directory block pointer can point
1775 * to the root block of the btree.
1777 ASSERT(da_bno
!= 0);
1780 do_warn("can't map block %u for directory inode %llu\n",
1784 bp
= da_read_buf(mp
, nex
, bmp
);
1788 do_warn("can't read file block %u for directory inode "
1795 * Check magic number for leaf directory btree block.
1797 if (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) != XFS_DIR2_LEAFN_MAGIC
) {
1798 do_warn("bad directory leaf magic # %#x for directory "
1799 "inode %llu block %u\n",
1800 INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
), ino
, da_bno
);
1806 * For each block, process the block, verify its path,
1807 * then get next block. Update cursor values along the way.
1809 if (process_leaf_block_dir2(mp
, leaf
, da_bno
, ino
,
1810 current_hashval
, &greatest_hashval
)) {
1815 * Index can be set to hdr.count so match the indices of the
1816 * interior blocks -- which at the end of the block will point
1817 * to 1 after the final real entry in the block.
1819 da_cursor
->level
[0].hashval
= greatest_hashval
;
1820 da_cursor
->level
[0].bp
= bp
;
1821 da_cursor
->level
[0].bno
= da_bno
;
1822 da_cursor
->level
[0].index
= INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
);
1823 da_cursor
->level
[0].dirty
= buf_dirty
;
1825 if (INT_GET(leaf
->hdr
.info
.back
, ARCH_CONVERT
) != prev_bno
) {
1826 do_warn("bad sibling back pointer for block %u in "
1827 "directory inode %llu\n",
1833 da_bno
= INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
);
1835 if (verify_dir2_path(mp
, da_cursor
, 0)) {
1840 current_hashval
= greatest_hashval
;
1841 ASSERT(buf_dirty
== 0 || (buf_dirty
&& !no_modify
));
1842 if (buf_dirty
&& !no_modify
) {
1847 } while (da_bno
!= 0);
1848 if (verify_final_dir2_path(mp
, da_cursor
, 0)) {
1850 * Verify the final path up (right-hand-side) if still ok.
1852 do_warn("bad hash path in directory %llu\n", ino
);
1856 * Redundant but just for testing.
1858 release_dir2_cursor(mp
, da_cursor
, 0);
1863 * Release all buffers holding interior btree blocks.
1865 err_release_dir2_cursor(mp
, da_cursor
, 0);
1872 * Return 1 if the directory's leaf/node space is corrupted and
1873 * needs to be rebuilt, 0 if it's ok.
1884 dir2_bt_cursor_t da_cursor
;
1887 * Try again -- traverse down left-side of tree until we hit the
1888 * left-most leaf block setting up the btree cursor along the way.
1889 * Then walk the leaf blocks left-to-right, calling a parent
1890 * verification routine each time we traverse a block.
1892 bzero(&da_cursor
, sizeof(da_cursor
));
1893 da_cursor
.ino
= ino
;
1894 da_cursor
.dip
= dip
;
1895 da_cursor
.blkmap
= blkmap
;
1898 * Now process interior node.
1900 if (traverse_int_dir2block(mp
, &da_cursor
, &bno
) == 0)
1904 * Skip directories with a root marked XFS_DIR2_LEAFN_MAGIC
1907 release_dir2_cursor(mp
, &da_cursor
, 0);
1911 * Now pass cursor and bno into leaf-block processing routine.
1912 * The leaf dir level routine checks the interior paths up to
1913 * the root including the final right-most path.
1915 return process_leaf_level_dir2(mp
, &da_cursor
, repair
);
1920 * Process leaf and node directories.
1921 * Process the data blocks then, if it's a node directory, check
1922 * the consistency of those blocks.
1925 process_leaf_node_dir2(
1930 char *dirname
, /* directory pathname */
1931 xfs_ino_t
*parent
, /* out - NULLFSINO if entry not exist */
1933 int *dot
, /* out - 1 if there is a dot, else 0 */
1934 int *dotdot
, /* out - 1 if there's a dotdot, else 0 */
1935 int *repair
, /* out - 1 if something was fixed */
1936 int isnode
) /* node directory not leaf */
1940 xfs_dir2_data_t
*data
;
1944 xfs_dfiloff_t ndbno
;
1948 *repair
= *dot
= *dotdot
= good
= 0;
1949 *parent
= NULLFSINO
;
1950 ndbno
= NULLDFILOFF
;
1951 while ((dbno
= blkmap_next_off(blkmap
, ndbno
, &t
)) < mp
->m_dirleafblk
) {
1952 nex
= blkmap_getn(blkmap
, dbno
, mp
->m_dirblkfsbs
, &bmp
);
1953 ndbno
= dbno
+ mp
->m_dirblkfsbs
- 1;
1955 do_warn("block %llu for directory inode %llu is "
1960 bp
= da_read_buf(mp
, nex
, bmp
);
1963 do_warn("can't read block %llu for directory inode "
1969 if (INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) != XFS_DIR2_DATA_MAGIC
)
1970 do_warn("bad directory block magic # %#x in block %llu "
1971 "for directory inode %llu\n",
1972 INT_GET(data
->hdr
.magic
, ARCH_CONVERT
), dbno
, ino
);
1973 i
= process_dir2_data(mp
, ino
, dip
, ino_discovery
, dirname
,
1974 parent
, bp
, dot
, dotdot
, (xfs_dablk_t
)dbno
,
1975 (char *)data
+ mp
->m_dirblksize
);
1978 if (bp
->dirty
&& !no_modify
) {
1988 if (dir2_is_badino(ino
))
1991 if (process_node_dir2(mp
, ino
, dip
, blkmap
, repair
))
1992 dir2_add_badlist(ino
);
1998 * Returns 1 if things are bad (directory needs to be junked)
1999 * and 0 if things are ok. If ino_discovery is 1, add unknown
2000 * inodes to uncertain inode list.
2019 *parent
= NULLFSINO
;
2024 * branch off depending on the type of inode. This routine
2025 * is only called ONCE so all the subordinate routines will
2026 * fix '.' and junk '..' if they're bogus.
2029 last
= blkmap_last_off(blkmap
);
2030 if (INT_GET(dip
->di_core
.di_size
, ARCH_CONVERT
) <= XFS_DFORK_DSIZE_ARCH(dip
, mp
, ARCH_CONVERT
) &&
2031 dip
->di_core
.di_format
== XFS_DINODE_FMT_LOCAL
) {
2033 res
= process_sf_dir2(mp
, ino
, dip
, ino_discovery
, dino_dirty
,
2034 dirname
, parent
, &repair
);
2035 } else if (last
== mp
->m_dirblkfsbs
&&
2036 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2037 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
)) {
2038 res
= process_block_dir2(mp
, ino
, dip
, ino_discovery
,
2039 dino_dirty
, dirname
, parent
, blkmap
, &dot
, &dotdot
,
2041 } else if (last
>= mp
->m_dirleafblk
+ mp
->m_dirblkfsbs
&&
2042 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2043 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
)) {
2044 res
= process_leaf_node_dir2(mp
, ino
, dip
, ino_discovery
,
2045 dirname
, parent
, blkmap
, &dot
, &dotdot
, &repair
,
2046 last
> mp
->m_dirleafblk
+ mp
->m_dirblkfsbs
);
2048 do_warn("bad size/format for directory %llu\n", ino
);
2052 * bad . entries in all directories will be fixed up in phase 6
2055 do_warn("no . entry for directory %llu\n", ino
);
2059 * shortform dirs always have a .. entry. .. for all longform
2060 * directories will get fixed in phase 6. .. for other shortform
2061 * dirs also get fixed there. .. for a shortform root was
2062 * fixed in place since we know what it should be
2064 if (dotdot
== 0 && ino
!= mp
->m_sb
.sb_rootino
) {
2065 do_warn("no .. entry for directory %llu\n", ino
);
2066 } else if (dotdot
== 0 && ino
== mp
->m_sb
.sb_rootino
) {
2067 do_warn("no .. entry for root directory %llu\n", ino
);
2068 need_root_dotdot
= 1;
2071 ASSERT((ino
!= mp
->m_sb
.sb_rootino
&& ino
!= *parent
) ||
2072 (ino
== mp
->m_sb
.sb_rootino
&&
2073 (ino
== *parent
|| need_root_dotdot
== 1)));