2 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "err_protos.h"
30 #if XFS_DIR_LEAF_MAPSIZE >= XFS_ATTR_LEAF_MAPSIZE
31 #define XR_DA_LEAF_MAPSIZE XFS_DIR_LEAF_MAPSIZE
33 #define XR_DA_LEAF_MAPSIZE XFS_ATTR_LEAF_MAPSIZE
38 typedef struct da_hole_map
{
44 } hentries
[XR_DA_LEAF_MAPSIZE
];
48 * takes a name and length (name need not be null-terminated)
49 * and returns 1 if the name contains a '/' or a \0, returns 0
53 namecheck(char *name
, int length
)
58 ASSERT(length
< MAXNAMELEN
);
60 for (c
= name
, i
= 0; i
< length
; i
++, c
++) {
61 if (*c
== '/' || *c
== '\0')
69 * this routine performs inode discovery and tries to fix things
70 * in place. available redundancy -- inode data size should match
71 * used directory space in inode. returns number of valid directory
72 * entries. a non-zero return value means the directory is bogus
73 * and should be blasted.
77 process_shortform_dir(
82 int *dino_dirty
, /* out - 1 if dinode buffer dirty? */
83 xfs_ino_t
*parent
, /* out - NULLFSINO if entry doesn't exist */
84 char *dirname
, /* directory pathname */
85 int *repair
) /* out - 1 if dir was fixed up */
87 xfs_dir_shortform_t
*sf
;
88 xfs_dir_sf_entry_t
*sf_entry
, *next_sfe
, *tmp_sfe
;
91 __int64_t ino_dir_size
;
100 ino_tree_node_t
*irec_p
;
101 char name
[MAXNAMELEN
+ 1];
104 fprintf(stderr
, "process_shortform_dir - inode %llu\n", ino
);
107 sf
= &dip
->di_u
.di_dirsf
;
109 max_size
= XFS_DFORK_DSIZE(dip
, mp
);
110 num_entries
= INT_GET(sf
->hdr
.count
, ARCH_CONVERT
);
111 ino_dir_size
= INT_GET(dip
->di_core
.di_size
, ARCH_CONVERT
);
114 ASSERT(ino_dir_size
<= max_size
);
117 * check for bad entry count
119 if (num_entries
* sizeof(xfs_dir_sf_entry_t
) + sizeof(xfs_dir_sf_hdr_t
)
120 > max_size
|| num_entries
== 0)
124 * run through entries, stop at first bad entry, don't need
125 * to check for .. since that's encoded in its own field
127 sf_entry
= next_sfe
= &sf
->list
[0];
128 for (i
= 0; i
< num_entries
&& ino_dir_size
>
129 (__psint_t
)next_sfe
- (__psint_t
)sf
; i
++) {
134 XFS_DIR_SF_GET_DIRINO(&sf_entry
->inumber
, &lino
);
137 * if entry points to self, junk it since only '.' or '..'
138 * should do that and shortform dirs don't contain either
139 * entry. if inode number is invalid, trash entry.
140 * if entry points to special inodes, trash it.
141 * if inode is unknown but number is valid,
142 * add it to the list of uncertain inodes. don't
143 * have to worry about an entry pointing to a
144 * deleted lost+found inode because the entry was
145 * deleted at the same time that the inode was cleared.
149 } else if (verify_inum(mp
, lino
)) {
151 * junk the entry, mark lino as NULL since it's bad
154 _("invalid inode number %llu in directory %llu\n"), lino
, ino
);
157 } else if (lino
== mp
->m_sb
.sb_rbmino
) {
159 _("entry in shortform dir %llu references rt bitmap inode %llu\n"),
162 } else if (lino
== mp
->m_sb
.sb_rsumino
) {
164 _("entry in shortform dir %llu references rt summary inode %llu\n"),
167 } else if (lino
== mp
->m_sb
.sb_uquotino
) {
169 _("entry in shortform dir %llu references user quota inode %llu\n"),
172 } else if (lino
== mp
->m_sb
.sb_gquotino
) {
174 _("entry in shortform dir %llu references group quota inode %llu\n"),
177 } else if ((irec_p
= find_inode_rec(XFS_INO_TO_AGNO(mp
, lino
),
178 XFS_INO_TO_AGINO(mp
, lino
))) != NULL
) {
180 * if inode is marked free and we're in inode
181 * discovery mode, leave the entry alone for now.
182 * if the inode turns out to be used, we'll figure
183 * that out when we scan it. If the inode really
184 * is free, we'll hit this code again in phase 4
185 * after we've finished inode discovery and blow
186 * out the entry then.
188 ino_off
= XFS_INO_TO_AGINO(mp
, lino
) -
189 irec_p
->ino_startnum
;
190 ASSERT(is_inode_confirmed(irec_p
, ino_off
));
192 if (!ino_discovery
&& is_inode_free(irec_p
, ino_off
)) {
194 _("entry references free inode %llu in shortform directory %llu\n"),
198 } else if (ino_discovery
) {
200 * put the inode on the uncertain list. we'll
201 * pull the inode off the list and check it later.
202 * if the inode turns out be bogus, we'll delete
203 * this entry in phase 6.
205 add_inode_uncertain(mp
, lino
, 0);
208 * blow the entry out. we know about all
209 * undiscovered entries now (past inode discovery
210 * phase) so this is clearly a bogus entry.
213 _("entry references non-existent inode %llu in shortform dir %llu\n"),
218 namelen
= sf_entry
->namelen
;
222 * if we're really lucky, this is
223 * the last entry in which case we
224 * can use the dir size to set the
225 * namelen value. otherwise, forget
226 * it because we're not going to be
227 * able to find the next entry.
231 if (i
== num_entries
- 1) {
232 namelen
= ino_dir_size
-
233 ((__psint_t
) &sf_entry
->name
[0] -
237 _("zero length entry in shortform dir %llu, resetting to %d\n"),
239 sf_entry
->namelen
= namelen
;
242 _("zero length entry in shortform dir %llu, would set to %d\n"),
247 _("zero length entry in shortform dir %llu, "),
250 do_warn(_("junking %d entries\n"),
253 do_warn(_("would junk %d entries\n"),
256 * don't process the rest of the directory,
257 * break out of processing looop
261 } else if ((__psint_t
) sf_entry
- (__psint_t
) sf
+
262 + XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
)
266 if (i
== num_entries
- 1) {
267 namelen
= ino_dir_size
-
268 ((__psint_t
) &sf_entry
->name
[0] -
271 _("size of last entry overflows space left in in shortform dir %llu, "),
274 do_warn(_("resetting to %d\n"),
276 sf_entry
->namelen
= namelen
;
279 do_warn(_("would reset to %d\n"),
284 _("size of entry #%d overflows space left in in shortform dir %llu\n"),
287 if (i
== num_entries
- 1)
289 _("junking entry #%d\n"),
293 _("junking %d entries\n"),
296 if (i
== num_entries
- 1)
298 _("would junk entry #%d\n"),
302 _("would junk %d entries\n"),
311 * check for illegal chars in name.
312 * no need to check for bad length because
313 * the length value is stored in a byte
314 * so it can't be too big, it can only wrap
316 if (namecheck((char *)&sf_entry
->name
[0], namelen
)) {
321 _("entry contains illegal character in shortform dir %llu\n"),
327 * junk the entry by copying up the rest of the
328 * fork over the current entry and decrementing
329 * the entry count. if we're in no_modify mode,
330 * just issue the warning instead. then continue
331 * the loop with the next_sfe pointer set to the
332 * correct place in the fork and other counters
333 * properly set to reflect the deletion if it
337 bcopy(sf_entry
->name
, name
, namelen
);
338 name
[namelen
] = '\0';
341 tmp_elen
= XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
);
342 INT_MOD(dip
->di_core
.di_size
,
343 ARCH_CONVERT
, -(tmp_elen
));
344 ino_dir_size
-= tmp_elen
;
346 tmp_sfe
= (xfs_dir_sf_entry_t
*)
347 ((__psint_t
) sf_entry
+ tmp_elen
);
348 tmp_len
= max_size
- ((__psint_t
) tmp_sfe
351 memmove(sf_entry
, tmp_sfe
, tmp_len
);
353 INT_MOD(sf
->hdr
.count
, ARCH_CONVERT
, -1);
355 bzero((void *) ((__psint_t
) sf_entry
+ tmp_len
),
359 * reset the tmp value to the current
360 * pointer so we'll process the entry
366 * WARNING: drop the index i by one
367 * so it matches the decremented count
368 * for accurate comparisons later
376 _("junking entry \"%s\" in directory inode %llu\n"),
380 _("would have junked entry \"%s\" in directory inode %llu\n"),
386 * go onto next entry unless we've just junked an
387 * entry in which the current entry pointer points
388 * to an unprocessed entry. have to take into zero-len
389 * entries into account in no modify mode since we
390 * calculate size based on next_sfe.
392 next_sfe
= (tmp_sfe
== NULL
)
393 ? (xfs_dir_sf_entry_t
*) ((__psint_t
) sf_entry
395 ? XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry
)
396 : sizeof(xfs_dir_sf_entry_t
) - 1
401 /* sync up sizes and entry counts */
403 if (INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) != i
) {
406 _("would have corrected entry count in directory %llu from %d to %d\n"),
407 ino
, INT_GET(sf
->hdr
.count
, ARCH_CONVERT
), i
);
410 _("corrected entry count in directory %llu, was %d, now %d\n"),
411 ino
, INT_GET(sf
->hdr
.count
, ARCH_CONVERT
), i
);
412 INT_SET(sf
->hdr
.count
, ARCH_CONVERT
, i
);
418 if ((__psint_t
) next_sfe
- (__psint_t
) sf
!= ino_dir_size
) {
421 _("would have corrected directory %llu size from %lld to %lld\n"),
422 ino
, (__int64_t
) ino_dir_size
,
423 (__int64_t
)((__psint_t
) next_sfe
- (__psint_t
) sf
));
426 _("corrected directory %llu size, was %lld, now %lld\n"),
427 ino
, (__int64_t
) ino_dir_size
,
428 (__int64_t
)((__psint_t
) next_sfe
- (__psint_t
) sf
));
430 INT_SET(dip
->di_core
.di_size
,
431 ARCH_CONVERT
, (xfs_fsize_t
)
432 ((__psint_t
) next_sfe
- (__psint_t
) sf
));
438 * check parent (..) entry
440 XFS_DIR_SF_GET_DIRINO(&sf
->hdr
.parent
, parent
);
443 * if parent entry is bogus, null it out. we'll fix it later .
445 if (verify_inum(mp
, *parent
)) {
449 _("bogus .. inode number (%llu) in directory inode %llu, "),
452 do_warn(_("clearing inode number\n"));
454 XFS_DIR_SF_PUT_DIRINO(parent
, &sf
->hdr
.parent
);
458 do_warn(_("would clear inode number\n"));
460 } else if (ino
== mp
->m_sb
.sb_rootino
&& ino
!= *parent
) {
462 * root directories must have .. == .
466 _("corrected root directory %llu .. entry, was %llu, now %llu\n"),
469 XFS_DIR_SF_PUT_DIRINO(parent
, &sf
->hdr
.parent
);
474 _("would have corrected root directory %llu .. entry from %llu to %llu\n"),
477 } else if (ino
== *parent
&& ino
!= mp
->m_sb
.sb_rootino
) {
479 * likewise, non-root directories can't have .. pointing
483 do_warn(_("bad .. entry in dir ino %llu, points to self, "),
486 do_warn(_("clearing inode number\n"));
488 XFS_DIR_SF_PUT_DIRINO(parent
, &sf
->hdr
.parent
);
492 do_warn(_("would clear inode number\n"));
500 * freespace map for directory leaf blocks (1 bit per byte)
501 * 1 == used, 0 == free
503 static da_freemap_t dir_freemap
[DA_BMAP_SIZE
];
507 alloc_da_freemap(xfs_mount_t
*mp
)
509 unsigned char *freemap
;
511 if ((freemap
= malloc(mp
->m_sb
.sb_blocksize
)) == NULL
)
514 bzero(freemap
, mp
->m_sb
.sb_blocksize
/NBBY
);
521 init_da_freemap(da_freemap_t
*dir_freemap
)
523 bzero(dir_freemap
, sizeof(da_freemap_t
) * DA_BMAP_SIZE
);
527 * sets directory freemap, returns 1 if there is a conflict
528 * returns 0 if everything's good. the range [start, stop) is set.
529 * right now, we just use the static array since only one directory
530 * block will be processed at once even though the interface allows
531 * you to pass in arbitrary da_freemap_t array's.
533 * Within a char, the lowest bit of the char represents the byte with
534 * the smallest address
537 set_da_freemap(xfs_mount_t
*mp
, da_freemap_t
*map
, int start
, int stop
)
539 const da_freemap_t mask
= 0x1;
544 * allow == relation since [x, x) claims 1 byte
546 do_warn(_("bad range claimed [%d, %d) in da block\n"),
551 if (stop
> mp
->m_sb
.sb_blocksize
) {
553 _("byte range end [%d %d) in da block larger than blocksize %d\n"),
554 start
, stop
, mp
->m_sb
.sb_blocksize
);
558 for (i
= start
; i
< stop
; i
++) {
559 if (map
[i
/ NBBY
] & (mask
<< i
% NBBY
)) {
560 do_warn(_("multiply claimed byte %d in da block\n"), i
);
563 map
[i
/ NBBY
] |= (mask
<< i
% NBBY
);
570 * returns 0 if holemap is consistent with reality (as expressed by
571 * the da_freemap_t). returns 1 if there's a conflict.
574 verify_da_freemap(xfs_mount_t
*mp
, da_freemap_t
*map
, da_hole_map_t
*holes
,
575 xfs_ino_t ino
, xfs_dablk_t da_bno
)
577 int i
, j
, start
, len
;
578 const da_freemap_t mask
= 0x1;
580 for (i
= 0; i
< XFS_DIR_LEAF_MAPSIZE
; i
++) {
581 if (holes
->hentries
[i
].size
== 0)
584 start
= holes
->hentries
[i
].base
;
585 len
= holes
->hentries
[i
].size
;
587 if (start
>= mp
->m_sb
.sb_blocksize
||
588 start
+ len
> mp
->m_sb
.sb_blocksize
) {
590 _("hole (start %d, len %d) out of range, block %d, dir ino %llu\n"),
591 start
, len
, da_bno
, ino
);
595 for (j
= start
; j
< start
+ len
; j
++) {
596 if ((map
[j
/ NBBY
] & (mask
<< (j
% NBBY
))) != 0) {
598 * bad news -- hole claims a used byte is free
601 _("hole claims used byte %d, block %d, dir ino %llu\n"),
612 process_da_freemap(xfs_mount_t
*mp
, da_freemap_t
*map
, da_hole_map_t
*holes
)
614 int i
, j
, in_hole
, start
, length
, smallest
, num_holes
;
615 const da_freemap_t mask
= 0x1;
617 num_holes
= in_hole
= start
= length
= 0;
619 for (i
= 0; i
< mp
->m_sb
.sb_blocksize
; i
++) {
620 if ((map
[i
/ NBBY
] & (mask
<< (i
% NBBY
))) == 0) {
622 * byte is free (unused)
627 * start of a new hole
642 * if the hole disappears, throw it away
651 for (smallest
= j
= 0; j
< XR_DA_LEAF_MAPSIZE
; j
++) {
652 if (holes
->hentries
[j
].size
<
653 holes
->hentries
[smallest
].size
)
657 if (length
> holes
->hentries
[smallest
].size
) {
658 holes
->hentries
[smallest
].base
= start
;
659 holes
->hentries
[smallest
].size
= length
;
665 * see if we have a big hole at the end
669 * duplicate of hole placement code above
676 for (smallest
= j
= 0; j
< XR_DA_LEAF_MAPSIZE
; j
++) {
677 if (holes
->hentries
[j
].size
<
678 holes
->hentries
[smallest
].size
)
682 if (length
> holes
->hentries
[smallest
].size
) {
683 holes
->hentries
[smallest
].base
= start
;
684 holes
->hentries
[smallest
].size
= length
;
689 holes
->lost_holes
= MAX(num_holes
- XR_DA_LEAF_MAPSIZE
, 0);
690 holes
->num_holes
= num_holes
;
696 * returns 1 if the hole info doesn't match, 0 if it does
700 compare_da_freemaps(xfs_mount_t
*mp
, da_hole_map_t
*holemap
,
701 da_hole_map_t
*block_hmap
, int entries
,
702 xfs_ino_t ino
, xfs_dablk_t da_bno
)
704 int i
, k
, res
, found
;
709 * we chop holemap->lost_holes down to being two-valued
710 * value (1 or 0) for the test because the filesystem
711 * value is two-valued
713 if ((holemap
->lost_holes
> 0 ? 1 : 0) != block_hmap
->lost_holes
) {
716 _("- derived hole value %d, saw %d, block %d, dir ino %llu\n"),
717 holemap
->lost_holes
, block_hmap
->lost_holes
,
724 for (i
= 0; i
< entries
; i
++) {
725 for (found
= k
= 0; k
< entries
; k
++) {
726 if (holemap
->hentries
[i
].base
==
727 block_hmap
->hentries
[k
].base
728 && holemap
->hentries
[i
].size
==
729 block_hmap
->hentries
[k
].size
)
735 _("- derived hole (base %d, size %d) in block %d, dir inode %llu not found\n"),
736 holemap
->hentries
[i
].base
,
737 holemap
->hentries
[i
].size
,
750 test(xfs_mount_t
*mp
)
753 da_hole_map_t holemap
;
755 init_da_freemap(dir_freemap
);
756 bzero(&holemap
, sizeof(da_hole_map_t
));
758 set_da_freemap(mp
, dir_freemap
, 0, 50);
759 set_da_freemap(mp
, dir_freemap
, 100, 126);
760 set_da_freemap(mp
, dir_freemap
, 126, 129);
761 set_da_freemap(mp
, dir_freemap
, 130, 131);
762 set_da_freemap(mp
, dir_freemap
, 150, 160);
763 process_da_freemap(mp
, dir_freemap
, &holemap
);
771 * walk tree from root to the left-most leaf block reading in
772 * blocks and setting up cursor. passes back file block number of the
773 * left-most leaf block if successful (bno). returns 1 if successful,
777 traverse_int_dablock(xfs_mount_t
*mp
,
778 da_bt_cursor_t
*da_cursor
,
784 xfs_da_intnode_t
*node
;
789 * traverse down left-side of tree until we hit the
790 * left-most leaf block setting up the btree cursor along
796 da_cursor
->active
= 0;
800 * read in each block along the way and set up cursor
802 fsbno
= blkmap_get(da_cursor
->blkmap
, bno
);
804 if (fsbno
== NULLDFSBNO
)
807 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, fsbno
),
808 XFS_FSB_TO_BB(mp
, 1), 0);
810 if (whichfork
== XFS_DATA_FORK
)
811 do_warn(_("can't read block %u (fsbno %llu) "
812 "for directory inode %llu\n"),
813 bno
, fsbno
, da_cursor
->ino
);
815 do_warn(_("can't read block %u (fsbno %llu) "
816 "for attrbute fork of inode %llu\n"),
817 bno
, fsbno
, da_cursor
->ino
);
821 node
= (xfs_da_intnode_t
*)XFS_BUF_PTR(bp
);
823 if (INT_GET(node
->hdr
.info
.magic
, ARCH_CONVERT
) != XFS_DA_NODE_MAGIC
) {
824 do_warn(_("bad dir/attr magic number in inode %llu, "
825 "file bno = %u, fsbno = %llu\n"),
826 da_cursor
->ino
, bno
, fsbno
);
830 if (INT_GET(node
->hdr
.count
, ARCH_CONVERT
) >
831 mp
->m_dir_node_ents
) {
832 do_warn(_("bad record count in inode %llu, "
833 "count = %d, max = %d\n"),
835 INT_GET(node
->hdr
.count
, ARCH_CONVERT
),
836 mp
->m_dir_node_ents
);
842 * maintain level counter
845 i
= da_cursor
->active
= INT_GET(node
->hdr
.level
, ARCH_CONVERT
);
847 if (INT_GET(node
->hdr
.level
, ARCH_CONVERT
) == i
- 1) {
850 if (whichfork
== XFS_DATA_FORK
)
851 do_warn(_("bad directory btree for "
852 "directory inode %llu\n"),
855 do_warn(_("bad attribute fork btree "
863 da_cursor
->level
[i
].hashval
=
864 INT_GET(node
->btree
[0].hashval
, ARCH_CONVERT
);
865 da_cursor
->level
[i
].bp
= bp
;
866 da_cursor
->level
[i
].bno
= bno
;
867 da_cursor
->level
[i
].index
= 0;
869 da_cursor
->level
[i
].n
= XFS_BUF_TO_DA_INTNODE(bp
);
873 * set up new bno for next level down
875 bno
= INT_GET(node
->btree
[0].before
, ARCH_CONVERT
);
876 } while(node
!= NULL
&& i
> 1);
879 * now return block number and get out
881 *rbno
= da_cursor
->level
[0].bno
= bno
;
885 while (i
> 1 && i
<= da_cursor
->active
) {
886 libxfs_putbuf(da_cursor
->level
[i
].bp
);
894 * blow out buffer for this level and all the rest above as well
895 * if error == 0, we are not expecting to encounter any unreleased
896 * buffers (e.g. if we do, it's a mistake). if error == 1, we're
897 * in an error-handling case so unreleased buffers may exist.
900 release_da_cursor_int(xfs_mount_t
*mp
,
901 da_bt_cursor_t
*cursor
,
905 int level
= prev_level
+ 1;
907 if (cursor
->level
[level
].bp
!= NULL
) {
909 do_warn(_("release_da_cursor_int got unexpected "
910 "non-null bp, dabno = %u\n"),
911 cursor
->level
[level
].bno
);
915 libxfs_putbuf(cursor
->level
[level
].bp
);
916 cursor
->level
[level
].bp
= NULL
;
919 if (level
< cursor
->active
)
920 release_da_cursor_int(mp
, cursor
, level
, error
);
926 release_da_cursor(xfs_mount_t
*mp
,
927 da_bt_cursor_t
*cursor
,
930 release_da_cursor_int(mp
, cursor
, prev_level
, 0);
934 err_release_da_cursor(xfs_mount_t
*mp
,
935 da_bt_cursor_t
*cursor
,
938 release_da_cursor_int(mp
, cursor
, prev_level
, 1);
942 * like traverse_int_dablock only it does far less checking
943 * and doesn't maintain the cursor. Just gets you to the
944 * leftmost block in the directory. returns the fsbno
945 * of that block if successful, NULLDFSBNO if not.
948 get_first_dblock_fsbno(xfs_mount_t
*mp
,
954 xfs_da_intnode_t
*node
;
959 * traverse down left-side of tree until we hit the
960 * left-most leaf block setting up the btree cursor along
967 fsbno
= get_bmapi(mp
, dino
, ino
, bno
, XFS_DATA_FORK
);
969 if (fsbno
== NULLDFSBNO
) {
970 do_warn(_("bmap of block #%u of inode %llu failed\n"),
975 if (INT_GET(dino
->di_core
.di_size
, ARCH_CONVERT
) <= XFS_LBSIZE(mp
))
980 * walk down left side of btree, release buffers as you
981 * go. if the root block is a leaf (single-level btree),
986 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, fsbno
),
987 XFS_FSB_TO_BB(mp
, 1), 0);
989 do_warn(_("can't read block %u (fsbno %llu) "
990 "for directory inode %llu\n"),
995 node
= (xfs_da_intnode_t
*)XFS_BUF_PTR(bp
);
997 if (XFS_DA_NODE_MAGIC
!=
998 INT_GET(node
->hdr
.info
.magic
, ARCH_CONVERT
)) {
999 do_warn(_("bad dir/attr magic number in inode %llu, "
1000 "file bno = %u, fsbno = %llu\n"),
1007 i
= INT_GET(node
->hdr
.level
, ARCH_CONVERT
);
1008 bno
= INT_GET(node
->btree
[0].before
, ARCH_CONVERT
);
1012 fsbno
= get_bmapi(mp
, dino
, ino
, bno
, XFS_DATA_FORK
);
1014 if (fsbno
== NULLDFSBNO
) {
1015 do_warn(_("bmap of block #%u of inode %llu failed\n"),
1027 * make sure that all entries in all blocks along the right side of
1028 * of the tree are used and hashval's are consistent. level is the
1029 * level of the descendent block. returns 0 if good (even if it had
1030 * to be fixed up), and 1 if bad. The right edge of the tree is
1031 * technically a block boundary. this routine should be used then
1032 * instead of verify_da_path().
1035 verify_final_da_path(xfs_mount_t
*mp
,
1036 da_bt_cursor_t
*cursor
,
1039 xfs_da_intnode_t
*node
;
1040 xfs_dahash_t hashval
;
1043 int this_level
= p_level
+ 1;
1046 fprintf(stderr
, "in verify_final_da_path, this_level = %d\n",
1050 * the index should point to the next "unprocessed" entry
1051 * in the block which should be the final (rightmost) entry
1053 entry
= cursor
->level
[this_level
].index
;
1054 node
= (xfs_da_intnode_t
*)XFS_BUF_PTR(cursor
->level
[this_level
].bp
);
1056 * check internal block consistency on this level -- ensure
1057 * that all entries are used, encountered and expected hashvals
1060 if (entry
!= INT_GET(node
->hdr
.count
, ARCH_CONVERT
) - 1) {
1061 do_warn(_("directory/attribute block used/count "
1062 "inconsistency - %d/%hu\n"),
1063 entry
, INT_GET(node
->hdr
.count
, ARCH_CONVERT
));
1067 * hash values monotonically increasing ???
1069 if (cursor
->level
[this_level
].hashval
>=
1070 INT_GET(node
->btree
[entry
].hashval
, ARCH_CONVERT
)) {
1071 do_warn(_("directory/attribute block hashvalue inconsistency, "
1072 "expected > %u / saw %u\n"),
1073 cursor
->level
[this_level
].hashval
,
1074 INT_GET(node
->btree
[entry
].hashval
, ARCH_CONVERT
));
1077 if (INT_GET(node
->hdr
.info
.forw
, ARCH_CONVERT
) != 0) {
1078 do_warn(_("bad directory/attribute forward block pointer, "
1079 "expected 0, saw %u\n"),
1080 INT_GET(node
->hdr
.info
.forw
, ARCH_CONVERT
));
1084 do_warn(_("bad directory block in dir ino %llu\n"),
1089 * keep track of greatest block # -- that gets
1090 * us the length of the directory
1092 if (cursor
->level
[this_level
].bno
> cursor
->greatest_bno
)
1093 cursor
->greatest_bno
= cursor
->level
[this_level
].bno
;
1096 * ok, now check descendant block number against this level
1098 if (cursor
->level
[p_level
].bno
!=
1099 INT_GET(node
->btree
[entry
].before
, ARCH_CONVERT
)) {
1101 fprintf(stderr
, "bad directory btree pointer, child bno should "
1102 "be %d, block bno is %d, hashval is %u\n",
1103 INT_GET(node
->btree
[entry
].before
, ARCH_CONVERT
),
1104 cursor
->level
[p_level
].bno
,
1105 cursor
->level
[p_level
].hashval
);
1106 fprintf(stderr
, "verify_final_da_path returns 1 (bad) #1a\n");
1111 if (cursor
->level
[p_level
].hashval
!=
1112 INT_GET(node
->btree
[entry
].hashval
, ARCH_CONVERT
)) {
1114 do_warn(_("correcting bad hashval in non-leaf "
1115 "dir/attr block\n\tin (level %d) in "
1117 this_level
, cursor
->ino
);
1118 INT_SET(node
->btree
[entry
].hashval
, ARCH_CONVERT
,
1119 cursor
->level
[p_level
].hashval
);
1120 cursor
->level
[this_level
].dirty
++;
1122 do_warn(_("would correct bad hashval in non-leaf "
1123 "dir/attr block\n\tin (level %d) in "
1125 this_level
, cursor
->ino
);
1130 * Note: squirrel hashval away _before_ releasing the
1131 * buffer, preventing a use-after-free problem.
1133 hashval
= INT_GET(node
->btree
[entry
].hashval
, ARCH_CONVERT
);
1136 * release/write buffer
1138 ASSERT(cursor
->level
[this_level
].dirty
== 0 ||
1139 (cursor
->level
[this_level
].dirty
&& !no_modify
));
1141 if (cursor
->level
[this_level
].dirty
&& !no_modify
)
1142 libxfs_writebuf(cursor
->level
[this_level
].bp
, 0);
1144 libxfs_putbuf(cursor
->level
[this_level
].bp
);
1146 cursor
->level
[this_level
].bp
= NULL
;
1149 * bail out if this is the root block (top of tree)
1151 if (this_level
>= cursor
->active
) {
1153 fprintf(stderr
, "verify_final_da_path returns 0 (ok)\n");
1158 * set hashvalue to correctly reflect the now-validated
1159 * last entry in this block and continue upwards validation
1161 cursor
->level
[this_level
].hashval
= hashval
;
1162 return(verify_final_da_path(mp
, cursor
, this_level
));
1166 * Verifies the path from a descendant block up to the root.
1167 * Should be called when the descendant level traversal hits
1168 * a block boundary before crossing the boundary (reading in a new
1171 * the directory/attr btrees work differently to the other fs btrees.
1172 * each interior block contains records that are <hashval, bno>
1173 * pairs. The bno is a file bno, not a filesystem bno. The last
1174 * hashvalue in the block <bno> will be <hashval>. BUT unlike
1175 * the freespace btrees, the *last* value in each block gets
1176 * propagated up the tree instead of the first value in each block.
1177 * that is, the interior records point to child blocks and the *greatest*
1178 * hash value contained by the child block is the one the block above
1179 * uses as the key for the child block.
1181 * level is the level of the descendent block. returns 0 if good,
1182 * and 1 if bad. The descendant block may be a leaf block.
1184 * the invariant here is that the values in the cursor for the
1185 * levels beneath this level (this_level) and the cursor index
1186 * for this level *must* be valid.
1188 * that is, the hashval/bno info is accurate for all
1189 * DESCENDANTS and match what the node[index] information
1190 * for the current index in the cursor for this level.
1192 * the index values in the cursor for the descendant level
1193 * are allowed to be off by one as they will reflect the
1194 * next entry at those levels to be processed.
1196 * the hashvalue for the current level can't be set until
1197 * we hit the last entry in the block so, it's garbage
1198 * until set by this routine.
1200 * bno and bp for the current block/level are always valid
1201 * since they have to be set so we can get a buffer for the
1205 verify_da_path(xfs_mount_t
*mp
,
1206 da_bt_cursor_t
*cursor
,
1209 xfs_da_intnode_t
*node
;
1210 xfs_da_intnode_t
*newnode
;
1216 int this_level
= p_level
+ 1;
1219 * index is currently set to point to the entry that
1220 * should be processed now in this level.
1222 entry
= cursor
->level
[this_level
].index
;
1223 node
= (xfs_da_intnode_t
*)XFS_BUF_PTR(cursor
->level
[this_level
].bp
);
1226 * if this block is out of entries, validate this
1227 * block and move on to the next block.
1228 * and update cursor value for said level
1230 if (entry
>= INT_GET(node
->hdr
.count
, ARCH_CONVERT
)) {
1232 * update the hash value for this level before
1233 * validating it. bno value should be ok since
1234 * it was set when the block was first read in.
1236 cursor
->level
[this_level
].hashval
=
1237 INT_GET(node
->btree
[entry
- 1].hashval
, ARCH_CONVERT
);
1240 * keep track of greatest block # -- that gets
1241 * us the length of the directory
1243 if (cursor
->level
[this_level
].bno
> cursor
->greatest_bno
)
1244 cursor
->greatest_bno
= cursor
->level
[this_level
].bno
;
1247 * validate the path for the current used-up block
1248 * before we trash it
1250 if (verify_da_path(mp
, cursor
, this_level
))
1253 * ok, now get the next buffer and check sibling pointers
1255 dabno
= INT_GET(node
->hdr
.info
.forw
, ARCH_CONVERT
);
1257 fsbno
= blkmap_get(cursor
->blkmap
, dabno
);
1259 if (fsbno
== NULLDFSBNO
) {
1260 do_warn(_("can't get map info for block %u "
1261 "of directory inode %llu\n"),
1262 dabno
, cursor
->ino
);
1266 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, fsbno
),
1267 XFS_FSB_TO_BB(mp
, 1), 0);
1269 do_warn(_("can't read block %u (%llu) "
1270 "for directory inode %llu\n"),
1271 dabno
, fsbno
, cursor
->ino
);
1275 newnode
= (xfs_da_intnode_t
*)XFS_BUF_PTR(bp
);
1277 * verify magic number and back pointer, sanity-check
1278 * entry count, verify level
1281 if (XFS_DA_NODE_MAGIC
!=
1282 INT_GET(newnode
->hdr
.info
.magic
, ARCH_CONVERT
)) {
1283 do_warn(_("bad magic number %x in block %u (%llu) "
1284 "for directory inode %llu\n"),
1285 INT_GET(newnode
->hdr
.info
.magic
, ARCH_CONVERT
),
1286 dabno
, fsbno
, cursor
->ino
);
1289 if (INT_GET(newnode
->hdr
.info
.back
, ARCH_CONVERT
) !=
1290 cursor
->level
[this_level
].bno
) {
1291 do_warn(_("bad back pointer in block %u (%llu) "
1292 "for directory inode %llu\n"),
1293 dabno
, fsbno
, cursor
->ino
);
1296 if (INT_GET(newnode
->hdr
.count
, ARCH_CONVERT
) >
1297 mp
->m_dir_node_ents
) {
1298 do_warn(_("entry count %d too large in block %u (%llu) "
1299 "for directory inode %llu\n"),
1300 INT_GET(newnode
->hdr
.count
, ARCH_CONVERT
),
1301 dabno
, fsbno
, cursor
->ino
);
1304 if (INT_GET(newnode
->hdr
.level
, ARCH_CONVERT
) != this_level
) {
1305 do_warn(_("bad level %d in block %u (%llu) "
1306 "for directory inode %llu\n"),
1307 INT_GET(newnode
->hdr
.level
, ARCH_CONVERT
),
1308 dabno
, fsbno
, cursor
->ino
);
1313 fprintf(stderr
, "verify_da_path returns 1 (bad) #4\n");
1319 * update cursor, write out the *current* level if
1320 * required. don't write out the descendant level
1322 ASSERT(cursor
->level
[this_level
].dirty
== 0 ||
1323 (cursor
->level
[this_level
].dirty
&& !no_modify
));
1325 if (cursor
->level
[this_level
].dirty
&& !no_modify
)
1326 libxfs_writebuf(cursor
->level
[this_level
].bp
, 0);
1328 libxfs_putbuf(cursor
->level
[this_level
].bp
);
1329 cursor
->level
[this_level
].bp
= bp
;
1330 cursor
->level
[this_level
].dirty
= 0;
1331 cursor
->level
[this_level
].bno
= dabno
;
1332 cursor
->level
[this_level
].hashval
=
1333 INT_GET(newnode
->btree
[0].hashval
, ARCH_CONVERT
);
1335 cursor
->level
[this_level
].n
= newnode
;
1339 entry
= cursor
->level
[this_level
].index
= 0;
1342 * ditto for block numbers
1344 if (cursor
->level
[p_level
].bno
!=
1345 INT_GET(node
->btree
[entry
].before
, ARCH_CONVERT
)) {
1347 fprintf(stderr
, "bad directory btree pointer, child bno "
1348 "should be %d, block bno is %d, hashval is %u\n",
1349 INT_GET(node
->btree
[entry
].before
, ARCH_CONVERT
),
1350 cursor
->level
[p_level
].bno
,
1351 cursor
->level
[p_level
].hashval
);
1352 fprintf(stderr
, "verify_da_path returns 1 (bad) #1a\n");
1357 * ok, now validate last hashvalue in the descendant
1358 * block against the hashval in the current entry
1360 if (cursor
->level
[p_level
].hashval
!=
1361 INT_GET(node
->btree
[entry
].hashval
, ARCH_CONVERT
)) {
1363 do_warn(_("correcting bad hashval in interior "
1364 "dir/attr block\n\tin (level %d) in "
1366 this_level
, cursor
->ino
);
1367 INT_SET(node
->btree
[entry
].hashval
, ARCH_CONVERT
,
1368 cursor
->level
[p_level
].hashval
);
1369 cursor
->level
[this_level
].dirty
++;
1371 do_warn(_("would correct bad hashval in interior "
1372 "dir/attr block\n\tin (level %d) in "
1374 this_level
, cursor
->ino
);
1378 * increment index for this level to point to next entry
1379 * (which should point to the next descendant block)
1381 cursor
->level
[this_level
].index
++;
1383 fprintf(stderr
, "verify_da_path returns 0 (ok)\n");
1390 * handles junking directory leaf block entries that have zero lengths
1391 * buf_dirty is an in/out, set to 1 if the leaf was modified.
1392 * we do NOT initialize it to zero if nothing happened because it
1393 * may be already set by the caller. Assumes that the block
1394 * has been compacted before calling this routine.
1397 junk_zerolen_dir_leaf_entries(
1399 xfs_dir_leafblock_t
*leaf
,
1403 xfs_dir_leaf_entry_t
*entry
;
1404 xfs_dir_leaf_name_t
*namest
;
1405 xfs_dir_leaf_hdr_t
*hdr
;
1406 xfs_dir_leaf_map_t
*map
;
1410 int current_hole
= 0;
1420 entry
= &leaf
->entries
[0];
1424 * we can convert the entries to one character entries
1425 * as long as we have space. Once we run out, then
1426 * we have to delete really delete (copy over) an entry.
1427 * however, that frees up some space that we could use ...
1429 * so the idea is, we'll use up space from all the holes,
1430 * potentially leaving each hole too small to do any good.
1431 * then if need to, we'll delete entries and use that space
1432 * up from the top-most byte down. that may leave a 4th hole
1433 * but we can represent that by correctly setting the value
1434 * of firstused. that leaves any hole between the end of
1435 * the entry list and firstused so it doesn't have to be
1436 * recorded in the hole map.
1439 for (bytes
= i
= 0; i
< INT_GET(hdr
->count
, ARCH_CONVERT
); entry
++, i
++) {
1441 * skip over entries that are good or already converted
1443 if (entry
->namelen
!= 0)
1449 * try and use up existing holes first until they get
1450 * too small, then set bytes to the # of bytes between
1451 * the current heap beginning and the last used byte
1452 * in the entry table.
1454 if (bytes
< sizeof(xfs_dir_leaf_name_t
) &&
1455 current_hole
< XFS_DIR_LEAF_MAPSIZE
) {
1457 * skip over holes that are too small
1459 while (current_hole
< XFS_DIR_LEAF_MAPSIZE
&&
1460 INT_GET(hdr
->freemap
[current_hole
].size
, ARCH_CONVERT
) <
1461 sizeof(xfs_dir_leaf_name_t
)) {
1465 if (current_hole
< XFS_DIR_LEAF_MAPSIZE
)
1466 bytes
= INT_GET(hdr
->freemap
[current_hole
].size
, ARCH_CONVERT
);
1468 bytes
= (int) INT_GET(hdr
->firstused
, ARCH_CONVERT
) -
1469 ((__psint_t
) &leaf
->entries
[INT_GET(hdr
->count
, ARCH_CONVERT
)] -
1475 for (map
= &hdr
->freemap
[0];
1476 current_hole
< XFS_DIR_LEAF_MAPSIZE
&&
1477 INT_GET(map
->size
, ARCH_CONVERT
) < sizeof(xfs_dir_leaf_name_t
);
1483 * if we can use an existing hole, do it. otherwise,
1484 * delete entries until the deletions create a big enough
1485 * hole to convert another entry. then use up those bytes
1486 * bytes until you run low. then delete entries again ...
1488 if (current_hole
< XFS_DIR_LEAF_MAPSIZE
) {
1489 ASSERT(sizeof(xfs_dir_leaf_name_t
) <= bytes
);
1491 do_warn(_("marking bad entry in directory inode %llu\n"),
1495 INT_SET(entry
->nameidx
, ARCH_CONVERT
, INT_GET(hdr
->freemap
[current_hole
].base
, ARCH_CONVERT
) +
1496 bytes
- sizeof(xfs_dir_leaf_name_t
));
1498 namest
= XFS_DIR_LEAF_NAMESTRUCT(leaf
, INT_GET(entry
->nameidx
, ARCH_CONVERT
));
1499 tmp_ino
= NULLFSINO
;
1500 XFS_DIR_SF_PUT_DIRINO(&tmp_ino
, &namest
->inumber
);
1501 namest
->name
[0] = '/';
1503 if (INT_GET(entry
->nameidx
, ARCH_CONVERT
) < INT_GET(hdr
->firstused
, ARCH_CONVERT
))
1504 INT_SET(hdr
->firstused
, ARCH_CONVERT
, INT_GET(entry
->nameidx
, ARCH_CONVERT
));
1505 INT_MOD(hdr
->freemap
[current_hole
].size
, ARCH_CONVERT
, -(sizeof(xfs_dir_leaf_name_t
)));
1506 INT_MOD(hdr
->namebytes
, ARCH_CONVERT
, +1);
1509 * delete the table entry and try and account for the
1510 * space in the holemap. don't have to update namebytes
1511 * or firstused since we're not actually deleting any
1512 * bytes from the heap. following code swiped from
1513 * xfs_dir_leaf_remove() in xfs_dir_leaf.c
1515 INT_MOD(hdr
->count
, ARCH_CONVERT
, -1);
1517 _("deleting zero length entry in directory inode %llu\n"),
1520 * overwrite the bad entry unless it's the
1521 * last entry in the list (highly unlikely).
1522 * zero out the free'd bytes.
1524 if (INT_GET(hdr
->count
, ARCH_CONVERT
) - i
> 0) {
1525 memmove(entry
, entry
+ 1, (INT_GET(hdr
->count
, ARCH_CONVERT
) - i
) *
1526 sizeof(xfs_dir_leaf_entry_t
));
1528 bzero((void *) ((__psint_t
) entry
+
1529 (INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) - i
- 1) *
1530 sizeof(xfs_dir_leaf_entry_t
)),
1531 sizeof(xfs_dir_leaf_entry_t
));
1533 start
= (__psint_t
) &leaf
->entries
[INT_GET(hdr
->count
, ARCH_CONVERT
)] -
1535 tablesize
= sizeof(xfs_dir_leaf_entry_t
) *
1536 (INT_GET(hdr
->count
, ARCH_CONVERT
) + 1) + sizeof(xfs_dir_leaf_hdr_t
);
1537 map
= &hdr
->freemap
[0];
1538 tmp
= INT_GET(map
->size
, ARCH_CONVERT
);
1539 before
= after
= -1;
1540 smallest
= XFS_DIR_LEAF_MAPSIZE
- 1;
1541 for (j
= 0; j
< XFS_DIR_LEAF_MAPSIZE
; map
++, j
++) {
1542 ASSERT(INT_GET(map
->base
, ARCH_CONVERT
) < XFS_LBSIZE(mp
));
1543 ASSERT(INT_GET(map
->size
, ARCH_CONVERT
) < XFS_LBSIZE(mp
));
1544 if (INT_GET(map
->base
, ARCH_CONVERT
) == tablesize
) {
1545 INT_MOD(map
->base
, ARCH_CONVERT
, -(sizeof(xfs_dir_leaf_entry_t
)));
1546 INT_MOD(map
->size
, ARCH_CONVERT
, sizeof(xfs_dir_leaf_entry_t
));
1549 if ((INT_GET(map
->base
, ARCH_CONVERT
) + INT_GET(map
->size
, ARCH_CONVERT
)) == start
) {
1551 } else if (INT_GET(map
->base
, ARCH_CONVERT
) == start
+
1552 sizeof(xfs_dir_leaf_entry_t
)) {
1554 } else if (INT_GET(map
->size
, ARCH_CONVERT
) < tmp
) {
1555 tmp
= INT_GET(map
->size
, ARCH_CONVERT
);
1561 * Coalesce adjacent freemap regions,
1562 * or replace the smallest region.
1564 if ((before
>= 0) || (after
>= 0)) {
1565 if ((before
>= 0) && (after
>= 0)) {
1566 map
= &hdr
->freemap
[before
];
1567 INT_MOD(map
->size
, ARCH_CONVERT
, sizeof(xfs_dir_leaf_entry_t
));
1568 INT_MOD(map
->size
, ARCH_CONVERT
, INT_GET(hdr
->freemap
[after
].size
, ARCH_CONVERT
));
1569 hdr
->freemap
[after
].base
= 0;
1570 hdr
->freemap
[after
].size
= 0;
1571 } else if (before
>= 0) {
1572 map
= &hdr
->freemap
[before
];
1573 INT_MOD(map
->size
, ARCH_CONVERT
, sizeof(xfs_dir_leaf_entry_t
));
1575 map
= &hdr
->freemap
[after
];
1576 INT_SET(map
->base
, ARCH_CONVERT
, start
);
1577 INT_MOD(map
->size
, ARCH_CONVERT
, sizeof(xfs_dir_leaf_entry_t
));
1581 * Replace smallest region
1582 * (if it is smaller than free'd entry)
1584 map
= &hdr
->freemap
[smallest
];
1585 if (INT_GET(map
->size
, ARCH_CONVERT
) < sizeof(xfs_dir_leaf_entry_t
)) {
1586 INT_SET(map
->base
, ARCH_CONVERT
, start
);
1587 INT_SET(map
->size
, ARCH_CONVERT
, sizeof(xfs_dir_leaf_entry_t
));
1590 * mark as needing compaction
1596 * do we have to delete stuff or is there
1597 * room for deletions?
1599 ASSERT(current_hole
== XFS_DIR_LEAF_MAPSIZE
);
1602 * here, bytes == number of unused bytes from
1603 * end of list to top (beginning) of heap
1604 * (firstused). It's ok to leave extra
1605 * unused bytes in that region because they
1606 * wind up before firstused (which we reset
1609 if (bytes
< sizeof(xfs_dir_leaf_name_t
)) {
1611 * have to delete an entry because
1612 * we have no room to convert it to
1616 _("deleting entry in directory inode %llu\n"),
1619 * overwrite the bad entry unless it's the
1620 * last entry in the list (highly unlikely).
1622 if (INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) - i
- 1> 0) {
1623 memmove(entry
, entry
+ 1,
1624 (INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) - i
- 1) *
1625 sizeof(xfs_dir_leaf_entry_t
));
1627 bzero((void *) ((__psint_t
) entry
+
1628 (INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) - i
- 1) *
1629 sizeof(xfs_dir_leaf_entry_t
)),
1630 sizeof(xfs_dir_leaf_entry_t
));
1633 * bump up free byte count, drop other
1634 * index vars since the table just
1635 * shrank by one entry and we don't
1636 * want to miss any as we walk the table
1638 bytes
+= sizeof(xfs_dir_leaf_entry_t
);
1639 INT_MOD(leaf
->hdr
.count
, ARCH_CONVERT
, -1);
1644 * convert entry using the bytes in between
1645 * the end of the entry table and the heap
1648 INT_MOD(leaf
->hdr
.firstused
, ARCH_CONVERT
, -(sizeof(xfs_dir_leaf_name_t
)));
1649 INT_SET(entry
->nameidx
, ARCH_CONVERT
, INT_GET(leaf
->hdr
.firstused
, ARCH_CONVERT
));
1651 namest
= XFS_DIR_LEAF_NAMESTRUCT(leaf
,
1652 INT_GET(entry
->nameidx
, ARCH_CONVERT
));
1653 tmp_ino
= NULLFSINO
;
1654 XFS_DIR_SF_PUT_DIRINO(&tmp_ino
,
1656 namest
->name
[0] = '/';
1658 bytes
-= sizeof(xfs_dir_leaf_entry_t
);
1668 static char dirbuf
[64 * 1024];
1671 * called by both node dir and leaf dir processing routines
1672 * validates all contents *but* the sibling pointers (forw/back)
1673 * and the magic number.
1675 * returns 0 if the directory is ok or has been brought to the
1676 * stage that it can be fixed up later (in phase 6),
1677 * 1 if it has to be junked.
1679 * Right now we fix a lot of things (TBD == to be deleted).
1681 * incorrect . entries - inode # is corrected
1682 * entries with mismatched hashvalue/name strings - hashvalue reset
1683 * entries whose hashvalues are out-of-order - entry marked TBD
1684 * .. entries with invalid inode numbers - entry marked TBD
1685 * entries with invalid inode numbers - entry marked TBD
1686 * multiple . entries - all but the first entry are marked TBD
1687 * zero-length entries - entry is deleted
1688 * entries with an out-of-bounds name index ptr - entry is deleted
1690 * entries marked TBD have the first character of the name (which
1691 * lives in the heap) have the first character in the name set
1692 * to '/' -- an illegal value.
1694 * entries deleted right here are deleted by blowing away the entry
1695 * (but leaving the heap untouched). any space that was used
1696 * by the deleted entry will be reclaimed by the block freespace
1697 * (da_freemap) processing code.
1699 * if two entries claim the same space in the heap (say, due to
1700 * bad entry name index pointers), we lose the directory. We could
1701 * try harder to fix this but it'll do for now.
1705 process_leaf_dir_block(
1707 xfs_dir_leafblock_t
*leaf
,
1710 xfs_dahash_t last_hashval
, /* last hashval encountered */
1716 int *buf_dirty
, /* is buffer dirty? */
1717 xfs_dahash_t
*next_hashval
) /* greatest hashval in block */
1720 xfs_dir_leaf_entry_t
*entry
;
1721 xfs_dir_leaf_entry_t
*s_entry
;
1722 xfs_dir_leaf_entry_t
*d_entry
;
1723 xfs_dir_leafblock_t
*new_leaf
;
1725 xfs_dir_leaf_name_t
*namest
;
1726 ino_tree_node_t
*irec_p
;
1728 xfs_dahash_t hashval
;
1739 int zero_len_entries
;
1740 char fname
[MAXNAMELEN
+ 1];
1741 da_hole_map_t holemap
;
1742 da_hole_map_t bholemap
;
1744 unsigned char *dir_freemap
;
1748 fprintf(stderr
, "\tprocess_leaf_dir_block - ino %llu\n", ino
);
1752 * clear static dir block freespace bitmap
1754 init_da_freemap(dir_freemap
);
1758 * XXX - alternatively, do this for parallel usage.
1759 * set up block freespace map. head part of dir leaf block
1760 * including all entries are packed so we can use sizeof
1761 * and not worry about alignment.
1764 if ((dir_freemap
= alloc_da_freemap(mp
)) == NULL
) {
1765 do_error(_("couldn't allocate directory block freemap\n"));
1771 first_used
= mp
->m_sb
.sb_blocksize
;
1772 zero_len_entries
= 0;
1775 i
= stop
= sizeof(xfs_dir_leaf_hdr_t
);
1776 if (set_da_freemap(mp
, dir_freemap
, 0, stop
)) {
1778 _("directory block header conflicts with used space in directory inode %llu\n"),
1784 * verify structure: monotonically increasing hash value for
1785 * all leaf entries, indexes for all entries must be within
1786 * this fs block (trivially true for 64K blocks). also track
1787 * used space so we can check the freespace map. check for
1788 * zero-length entries. for now, if anything's wrong, we
1789 * junk the directory and we'll pick up no-longer referenced
1790 * inodes on a later pass.
1792 for (i
= 0, entry
= &leaf
->entries
[0];
1793 i
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
);
1796 * check that the name index isn't out of bounds
1797 * if it is, delete the entry since we can't
1800 if (INT_GET(entry
->nameidx
, ARCH_CONVERT
) >=
1801 mp
->m_sb
.sb_blocksize
) {
1805 if (INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) > 1) {
1807 _("nameidx %d for entry #%d, bno %d, ino %llu > fs blocksize, deleting entry\n"),
1808 INT_GET(entry
->nameidx
,
1811 ASSERT(INT_GET(leaf
->hdr
.count
,
1814 bytes
= (INT_GET(leaf
->hdr
.count
,
1815 ARCH_CONVERT
) - i
) *
1816 sizeof(xfs_dir_leaf_entry_t
);
1819 * compress table unless we're
1820 * only dealing with 1 entry
1821 * (the last one) in which case
1825 sizeof(xfs_dir_leaf_entry_t
)) {
1826 memmove(entry
, entry
+ 1,
1829 ((__psint_t
) entry
+ bytes
),
1830 sizeof(xfs_dir_leaf_entry_t
));
1833 sizeof(xfs_dir_leaf_entry_t
));
1837 * sync vars to match smaller table.
1838 * don't have to worry about freespace
1839 * map since we haven't set it for
1842 INT_MOD(leaf
->hdr
.count
, ARCH_CONVERT
, -1);
1847 _("nameidx %d, entry #%d, bno %d, ino %llu > fs blocksize, marking entry bad\n"),
1848 INT_GET(entry
->nameidx
,
1851 INT_SET(entry
->nameidx
, ARCH_CONVERT
,
1852 mp
->m_sb
.sb_blocksize
-
1853 sizeof(xfs_dir_leaf_name_t
));
1854 namest
= XFS_DIR_LEAF_NAMESTRUCT(leaf
,
1855 INT_GET(entry
->nameidx
,
1858 XFS_DIR_SF_PUT_DIRINO(&lino
,
1860 namest
->name
[0] = '/';
1864 _("nameidx %d, entry #%d, bno %d, ino %llu > fs blocksize, would delete entry\n"),
1865 INT_GET(entry
->nameidx
, ARCH_CONVERT
),
1871 * inode processing -- make sure the inode
1872 * is in our tree or we add it to the uncertain
1873 * list if the inode # is valid. if namelen is 0,
1874 * we can still try for the inode as long as nameidx
1877 namest
= XFS_DIR_LEAF_NAMESTRUCT(leaf
,
1878 INT_GET(entry
->nameidx
, ARCH_CONVERT
));
1879 XFS_DIR_SF_GET_DIRINO(&namest
->inumber
, &lino
);
1882 * we may have to blow out an entry because of bad
1883 * inode numbers. do NOT touch the name until after
1884 * we've computed the hashvalue and done a namecheck()
1887 if (!ino_discovery
&& lino
== NULLFSINO
) {
1889 * don't do a damned thing. We already
1890 * found this (or did it ourselves) during
1893 } else if (verify_inum(mp
, lino
)) {
1895 * bad inode number. clear the inode
1896 * number and the entry will get removed
1897 * later. We don't trash the directory
1898 * since it's still structurally intact.
1901 _("invalid ino number %llu in dir ino %llu, entry #%d, bno %d\n"),
1902 lino
, ino
, i
, da_bno
);
1905 _("\tclearing ino number in entry %d...\n"),
1908 XFS_DIR_SF_PUT_DIRINO(&lino
, &namest
->inumber
);
1912 _("\twould clear ino number in entry %d...\n"),
1915 } else if (lino
== mp
->m_sb
.sb_rbmino
) {
1917 _("entry #%d, bno %d in directory %llu references realtime bitmap inode %llu\n"),
1918 i
, da_bno
, ino
, lino
);
1921 _("\tclearing ino number in entry %d...\n"),
1925 XFS_DIR_SF_PUT_DIRINO(&lino
, &namest
->inumber
);
1929 _("\twould clear ino number in entry %d...\n"),
1932 } else if (lino
== mp
->m_sb
.sb_rsumino
) {
1934 _("entry #%d, bno %d in directory %llu references realtime summary inode %llu\n"),
1935 i
, da_bno
, ino
, lino
);
1938 _("\tclearing ino number in entry %d...\n"), i
);
1941 XFS_DIR_SF_PUT_DIRINO(&lino
, &namest
->inumber
);
1945 _("\twould clear ino number in entry %d...\n"),
1948 } else if (lino
== mp
->m_sb
.sb_uquotino
) {
1950 _("entry #%d, bno %d in directory %llu references user quota inode %llu\n"),
1951 i
, da_bno
, ino
, lino
);
1954 _("\tclearing ino number in entry %d...\n"),
1958 XFS_DIR_SF_PUT_DIRINO(&lino
, &namest
->inumber
);
1962 _("\twould clear ino number in entry %d...\n"),
1965 } else if (lino
== mp
->m_sb
.sb_gquotino
) {
1967 _("entry #%d, bno %d in directory %llu references group quota inode %llu\n"),
1968 i
, da_bno
, ino
, lino
);
1971 _("\tclearing ino number in entry %d...\n"),
1975 XFS_DIR_SF_PUT_DIRINO(&lino
, &namest
->inumber
);
1979 _("\twould clear ino number in entry %d...\n"),
1982 } else if (lino
== old_orphanage_ino
) {
1984 * do nothing, silently ignore it, entry has
1985 * already been marked TBD since old_orphanage_ino
1988 } else if ((irec_p
= find_inode_rec(
1989 XFS_INO_TO_AGNO(mp
, lino
),
1990 XFS_INO_TO_AGINO(mp
, lino
))) != NULL
) {
1992 * inode recs should have only confirmed
1995 ino_off
= XFS_INO_TO_AGINO(mp
, lino
) -
1996 irec_p
->ino_startnum
;
1997 ASSERT(is_inode_confirmed(irec_p
, ino_off
));
1999 * if inode is marked free and we're in inode
2000 * discovery mode, leave the entry alone for now.
2001 * if the inode turns out to be used, we'll figure
2002 * that out when we scan it. If the inode really
2003 * is free, we'll hit this code again in phase 4
2004 * after we've finished inode discovery and blow
2005 * out the entry then.
2007 if (!ino_discovery
&& is_inode_free(irec_p
, ino_off
)) {
2010 _("entry references free inode %llu in directory %llu, will clear entry\n"),
2013 XFS_DIR_SF_PUT_DIRINO(&lino
,
2018 _("entry references free inode %llu in directory %llu, would clear entry\n"),
2022 } else if (ino_discovery
) {
2023 add_inode_uncertain(mp
, lino
, 0);
2026 _("bad ino number %llu in dir ino %llu, entry #%d, bno %d\n"),
2027 lino
, ino
, i
, da_bno
);
2029 do_warn(_("clearing inode number...\n"));
2031 XFS_DIR_SF_PUT_DIRINO(&lino
, &namest
->inumber
);
2034 do_warn(_("would clear inode number...\n"));
2038 * if we have a zero-length entry, trash it.
2039 * we may lose the inode (chunk) if we don't
2040 * finish the repair successfully and the inode
2041 * isn't mentioned anywhere else (like in the inode
2042 * tree) but the alternative is to risk losing the
2043 * entire directory by trying to use the next byte
2044 * to turn the entry into a 1-char entry. That's
2045 * probably a safe bet but if it didn't work, we'd
2046 * lose the entire directory the way we currently do
2047 * things. (Maybe we should change that later :-).
2049 if (entry
->namelen
== 0) {
2052 if (INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) > 1) {
2054 _("entry #%d, dir inode %llu, has zero-len name, deleting entry\n"),
2056 ASSERT(INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
) > i
);
2058 bytes
= (INT_GET(leaf
->hdr
.count
,
2059 ARCH_CONVERT
) - i
) *
2060 sizeof(xfs_dir_leaf_entry_t
);
2063 * compress table unless we're
2064 * only dealing with 1 entry
2065 * (the last one) in which case
2068 if (bytes
> sizeof(xfs_dir_leaf_entry_t
)) {
2069 memmove(entry
, entry
+ 1, bytes
);
2071 ((__psint_t
) entry
+ bytes
),
2072 sizeof(xfs_dir_leaf_entry_t
));
2075 sizeof(xfs_dir_leaf_entry_t
));
2079 * sync vars to match smaller table.
2080 * don't have to worry about freespace
2081 * map since we haven't set it for
2084 INT_MOD(leaf
->hdr
.count
, ARCH_CONVERT
, -1);
2089 * if it's the only entry, preserve the
2090 * inode number for now
2093 _("entry #%d, dir inode %llu, has zero-len name, marking entry bad\n"),
2095 INT_SET(entry
->nameidx
, ARCH_CONVERT
,
2096 mp
->m_sb
.sb_blocksize
-
2097 sizeof(xfs_dir_leaf_name_t
));
2098 namest
= XFS_DIR_LEAF_NAMESTRUCT(leaf
,
2099 INT_GET(entry
->nameidx
,
2101 XFS_DIR_SF_PUT_DIRINO(&lino
, &namest
->inumber
);
2102 namest
->name
[0] = '/';
2104 } else if (INT_GET(entry
->nameidx
, ARCH_CONVERT
) +
2105 entry
->namelen
> XFS_LBSIZE(mp
)) {
2107 _("bad size, entry #%d in dir inode %llu, block %u -- entry overflows block\n"),
2113 start
= (__psint_t
)&leaf
->entries
[i
] - (__psint_t
)leaf
;;
2114 stop
= start
+ sizeof(xfs_dir_leaf_entry_t
);
2116 if (set_da_freemap(mp
, dir_freemap
, start
, stop
)) {
2118 _("dir entry slot %d in block %u conflicts with used space in dir inode %llu\n"),
2124 * check if the name is legal. if so, then
2125 * check that the name and hashvalues match.
2127 * if the name is illegal, we don't check the
2128 * hashvalue computed from it. we just make
2129 * sure that the hashvalue in the entry is
2130 * monotonically increasing wrt to the previous
2133 * Note that we do NOT have to check the length
2134 * because the length is stored in a one-byte
2135 * unsigned int which max's out at MAXNAMELEN
2136 * making it impossible for the stored length
2137 * value to be out of range.
2139 bcopy(namest
->name
, fname
, entry
->namelen
);
2140 fname
[entry
->namelen
] = '\0';
2141 hashval
= libxfs_da_hashname(fname
, entry
->namelen
);
2144 * only complain about illegal names in phase 3 (when
2145 * inode discovery is turned on). Otherwise, we'd complain
2146 * a lot during phase 4. If the name is illegal, leave
2147 * the hash value in that entry alone.
2149 nm_illegal
= namecheck(fname
, entry
->namelen
);
2151 if (ino_discovery
&& nm_illegal
) {
2153 * junk the entry, illegal name
2157 _("illegal name \"%s\" in directory inode %llu, entry will be cleared\n"),
2159 namest
->name
[0] = '/';
2163 _("illegal name \"%s\" in directory inode %llu, entry would be cleared\n"),
2166 } else if (!nm_illegal
&&
2167 INT_GET(entry
->hashval
, ARCH_CONVERT
) != hashval
) {
2169 * try resetting the hashvalue to the correct
2170 * value for the string, if the string has been
2171 * corrupted, too, that will get picked up next
2173 do_warn(_("\tmismatched hash value for entry \"%s\"\n"),
2177 _("\t\tin directory inode %llu. resetting hash value.\n"),
2179 INT_SET(entry
->hashval
, ARCH_CONVERT
, hashval
);
2183 _("\t\tin directory inode %llu. would reset hash value.\n"),
2189 * now we can mark entries with NULLFSINO's bad
2191 if (!no_modify
&& lino
== NULLFSINO
) {
2192 namest
->name
[0] = '/';
2197 * regardless of whether the entry has or hasn't been
2198 * marked for deletion, the hash value ordering must
2201 if (INT_GET(entry
->hashval
, ARCH_CONVERT
) < last_hashval
) {
2203 * blow out the entry -- set hashval to sane value
2204 * and set the first character in the string to
2205 * the illegal value '/'. Reset the hash value
2206 * to the last hashvalue so that verify_da_path
2207 * will fix up the interior pointers correctly.
2208 * the entry will be deleted later (by routines
2209 * that need only the entry #). We keep the
2210 * inode number in the entry so we can attach
2211 * the inode to the orphanage later.
2213 do_warn(_("\tbad hash ordering for entry \"%s\"\n"),
2217 _("\t\tin directory inode %llu. will clear entry\n"),
2219 INT_SET(entry
->hashval
, ARCH_CONVERT
,
2221 namest
->name
[0] = '/';
2225 _("\t\tin directory inode %llu. would clear entry\n"),
2230 *next_hashval
= last_hashval
= INT_GET(entry
->hashval
, ARCH_CONVERT
);
2233 * if heap data conflicts with something,
2234 * blow it out and skip the rest of the loop
2236 if (set_da_freemap(mp
, dir_freemap
,
2237 INT_GET(entry
->nameidx
, ARCH_CONVERT
),
2238 INT_GET(entry
->nameidx
, ARCH_CONVERT
)
2239 + sizeof(xfs_dir_leaf_name_t
)
2240 + entry
->namelen
- 1)) {
2242 _("name \"%s\" (block %u, slot %d) conflicts with used space in dir inode %llu\n"),
2243 fname
, da_bno
, i
, ino
);
2249 _("will clear entry \"%s\" (#%d) in directory inode %llu\n"),
2253 _("would clear entry \"%s\" (#%d)in directory inode %llu\n"),
2260 * keep track of heap stats (first byte used, total bytes used)
2262 if (INT_GET(entry
->nameidx
, ARCH_CONVERT
) < first_used
)
2263 first_used
= INT_GET(entry
->nameidx
, ARCH_CONVERT
);
2264 bytes_used
+= entry
->namelen
;
2267 * special . or .. entry processing
2269 if (entry
->namelen
== 2 && namest
->name
[0] == '.' &&
2270 namest
->name
[1] == '.') {
2278 fprintf(stderr
, "process_leaf_dir_block found .. entry (parent) = %llu\n", lino
);
2281 * what if .. == .? legal only in
2282 * the root inode. blow out entry
2283 * and set parent to NULLFSINO otherwise.
2286 ino
!= mp
->m_sb
.sb_rootino
) {
2287 *parent
= NULLFSINO
;
2289 _("bad .. entry in dir ino %llu, points to self"),
2293 _("will clear entry\n"));
2294 namest
->name
[0] = '/';
2298 _("would clear entry\n"));
2300 } else if (ino
!= lino
&&
2301 ino
== mp
->m_sb
.sb_rootino
) {
2303 * we have to make sure that . == ..
2308 _("correcting .. entry in root inode %llu, was %llu\n"),
2310 XFS_DIR_SF_PUT_DIRINO(
2311 &ino
, &namest
->inumber
);
2315 _("bad .. entry (%llu) in root inode %llu should be %llu\n"),
2322 * can't fix the directory unless we know
2323 * which .. entry is the right one. Both
2324 * have valid inode numbers, match the hash
2325 * value and the hash values are ordered
2326 * properly or we wouldn't be here. So
2327 * since both seem equally valid, trash
2332 _("multiple .. entries in directory inode %llu, will clear second entry\n"),
2334 namest
->name
[0] = '/';
2338 _("multiple .. entries in directory inode %llu, would clear second entry\n"),
2342 } else if (entry
->namelen
== 1 && namest
->name
[0] == '.') {
2351 _(". in directory inode %llu has wrong value (%llu), fixing entry...\n"),
2353 XFS_DIR_SF_PUT_DIRINO(&ino
,
2358 _(". in directory inode %llu has wrong value (%llu)\n"),
2364 _("multiple . entries in directory inode %llu\n"),
2367 * mark entry as to be junked.
2371 _("will clear one . entry in directory inode %llu\n"),
2373 namest
->name
[0] = '/';
2377 _("would clear one . entry in directory inode %llu\n"),
2383 * all the rest -- make sure only . references self
2387 _("entry \"%s\" in directory inode %llu points to self, "),
2390 do_warn(_("will clear entry\n"));
2391 namest
->name
[0] = '/';
2394 do_warn(_("would clear entry\n"));
2401 * compare top of heap values and reset as required. if the
2402 * holes flag is set, don't reset first_used unless it's
2403 * pointing to used bytes. we're being conservative here
2404 * since the block will get compacted anyhow by the kernel.
2406 if ((leaf
->hdr
.holes
== 0 &&
2407 first_used
!= INT_GET(leaf
->hdr
.firstused
, ARCH_CONVERT
)) ||
2408 INT_GET(leaf
->hdr
.firstused
, ARCH_CONVERT
) > first_used
) {
2412 _("- resetting first used heap value from %d to %d in block %u of dir ino %llu\n"),
2413 (int) INT_GET(leaf
->hdr
.firstused
,
2415 first_used
, da_bno
, ino
);
2416 INT_SET(leaf
->hdr
.firstused
, ARCH_CONVERT
, first_used
);
2421 _("- would reset first used value from %d to %d in block %u of dir ino %llu\n"),
2422 (int) INT_GET(leaf
->hdr
.firstused
,
2424 first_used
, da_bno
, ino
);
2428 if (bytes_used
!= INT_GET(leaf
->hdr
.namebytes
, ARCH_CONVERT
)) {
2432 _("- resetting namebytes cnt from %d to %d in block %u of dir inode %llu\n"),
2433 (int) INT_GET(leaf
->hdr
.namebytes
,
2435 bytes_used
, da_bno
, ino
);
2436 INT_SET(leaf
->hdr
.namebytes
, ARCH_CONVERT
, bytes_used
);
2441 _("- would reset namebytes cnt from %d to %d in block %u of dir inode %llu\n"),
2442 (int) INT_GET(leaf
->hdr
.namebytes
,
2444 bytes_used
, da_bno
, ino
);
2449 * If the hole flag is not set, then we know that there can
2450 * be no lost holes. If the hole flag is set, then it's ok
2451 * if the on-disk holemap doesn't describe everything as long
2452 * as what it does describe doesn't conflict with reality.
2457 bholemap
.lost_holes
= leaf
->hdr
.holes
;
2458 for (i
= 0; i
< XFS_DIR_LEAF_MAPSIZE
; i
++) {
2459 bholemap
.hentries
[i
].base
= INT_GET(leaf
->hdr
.freemap
[i
].base
, ARCH_CONVERT
);
2460 bholemap
.hentries
[i
].size
= INT_GET(leaf
->hdr
.freemap
[i
].size
, ARCH_CONVERT
);
2464 * Ok, now set up our own freespace list
2465 * (XFS_DIR_LEAF_MAPSIZE (3) * biggest regions)
2466 * and see if they match what's in the block
2468 bzero(&holemap
, sizeof(da_hole_map_t
));
2469 process_da_freemap(mp
, dir_freemap
, &holemap
);
2471 if (zero_len_entries
) {
2473 } else if (leaf
->hdr
.holes
== 0) {
2474 if (holemap
.lost_holes
> 0) {
2477 _("- found unexpected lost holes in block %u, dir inode %llu\n"),
2481 } else if (compare_da_freemaps(mp
, &holemap
, &bholemap
,
2482 XFS_DIR_LEAF_MAPSIZE
, ino
, da_bno
)) {
2485 _("- hole info non-optimal in block %u, dir inode %llu\n"),
2489 } else if (verify_da_freemap(mp
, dir_freemap
, &holemap
, ino
, da_bno
)) {
2492 _("- hole info incorrect in block %u, dir inode %llu\n"),
2499 * have to reset block hole info
2503 _("- existing hole info for block %d, dir inode %llu (base, size) - \n"),
2506 for (i
= 0; i
< XFS_DIR_LEAF_MAPSIZE
; i
++) {
2508 "- (%d, %d) ", bholemap
.hentries
[i
].base
,
2509 bholemap
.hentries
[i
].size
);
2511 do_warn(_("- holes flag = %d\n"), bholemap
.lost_holes
);
2517 _("- compacting block %u in dir inode %llu\n"),
2520 new_leaf
= (xfs_dir_leafblock_t
*) &dirbuf
[0];
2523 * copy leaf block header
2525 bcopy(&leaf
->hdr
, &new_leaf
->hdr
,
2526 sizeof(xfs_dir_leaf_hdr_t
));
2529 * reset count in case we have some zero length entries
2530 * that are being junked
2533 first_used
= XFS_LBSIZE(mp
);
2534 first_byte
= (char *) new_leaf
2535 + (__psint_t
) XFS_LBSIZE(mp
);
2538 * copy entry table and pack names starting from the end
2541 for (i
= 0, s_entry
= &leaf
->entries
[0],
2542 d_entry
= &new_leaf
->entries
[0];
2543 i
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
);
2546 * skip zero-length entries
2548 if (s_entry
->namelen
== 0)
2551 bytes
= sizeof(xfs_dir_leaf_name_t
)
2552 + s_entry
->namelen
- 1;
2554 if ((__psint_t
) first_byte
- bytes
<
2555 sizeof(xfs_dir_leaf_entry_t
)
2556 + (__psint_t
) d_entry
) {
2558 _("not enough space in block %u of dir inode %llu for all entries\n"),
2563 first_used
-= bytes
;
2564 first_byte
-= bytes
;
2566 INT_SET(d_entry
->nameidx
, ARCH_CONVERT
, first_used
);
2567 INT_SET(d_entry
->hashval
, ARCH_CONVERT
, INT_GET(s_entry
->hashval
, ARCH_CONVERT
));
2568 d_entry
->namelen
= s_entry
->namelen
;
2571 bcopy((char *) leaf
+ INT_GET(s_entry
->nameidx
, ARCH_CONVERT
),
2578 ASSERT((char *) first_byte
>= (char *) d_entry
);
2579 ASSERT(first_used
<= XFS_LBSIZE(mp
));
2582 * zero space between end of table and top of heap
2584 bzero(d_entry
, (__psint_t
) first_byte
2585 - (__psint_t
) d_entry
);
2590 if (num_entries
!= INT_GET(new_leaf
->hdr
.count
, ARCH_CONVERT
))
2591 INT_SET(new_leaf
->hdr
.count
, ARCH_CONVERT
, num_entries
);
2593 INT_SET(new_leaf
->hdr
.firstused
, ARCH_CONVERT
, first_used
);
2594 new_leaf
->hdr
.holes
= 0;
2595 new_leaf
->hdr
.pad1
= 0;
2597 INT_SET(new_leaf
->hdr
.freemap
[0].base
, ARCH_CONVERT
, (__psint_t
) d_entry
2598 - (__psint_t
) new_leaf
);
2599 INT_SET(new_leaf
->hdr
.freemap
[0].size
, ARCH_CONVERT
, (__psint_t
) first_byte
2600 - (__psint_t
) d_entry
);
2602 ASSERT(INT_GET(new_leaf
->hdr
.freemap
[0].base
, ARCH_CONVERT
) < first_used
);
2603 ASSERT(INT_GET(new_leaf
->hdr
.freemap
[0].base
, ARCH_CONVERT
) ==
2604 (__psint_t
) (&new_leaf
->entries
[0])
2605 - (__psint_t
) new_leaf
2606 + i
* sizeof(xfs_dir_leaf_entry_t
));
2607 ASSERT(INT_GET(new_leaf
->hdr
.freemap
[0].base
, ARCH_CONVERT
) < XFS_LBSIZE(mp
));
2608 ASSERT(INT_GET(new_leaf
->hdr
.freemap
[0].size
, ARCH_CONVERT
) < XFS_LBSIZE(mp
));
2609 ASSERT(INT_GET(new_leaf
->hdr
.freemap
[0].base
, ARCH_CONVERT
) +
2610 INT_GET(new_leaf
->hdr
.freemap
[0].size
, ARCH_CONVERT
) == first_used
);
2612 new_leaf
->hdr
.freemap
[1].base
= 0;
2613 new_leaf
->hdr
.freemap
[1].size
= 0;
2614 new_leaf
->hdr
.freemap
[2].base
= 0;
2615 new_leaf
->hdr
.freemap
[2].size
= 0;
2618 * final step, copy block back
2620 bcopy(new_leaf
, leaf
, mp
->m_sb
.sb_blocksize
);
2626 _("- would compact block %u in dir inode %llu\n"),
2633 * now take care of deleting or marking the entries with
2634 * zero-length namelen's
2636 junk_zerolen_dir_leaf_entries(mp
, leaf
, ino
, buf_dirty
);
2640 fprintf(stderr
, "process_leaf_dir_block returns %d\n", res
);
2642 return((res
> 0) ? 1 : 0);
2646 * returns 0 if the directory is ok, 1 if it has to be junked.
2649 process_leaf_dir_level(xfs_mount_t
*mp
,
2650 da_bt_cursor_t
*da_cursor
,
2657 xfs_dir_leafblock_t
*leaf
;
2660 xfs_dfsbno_t dev_bno
;
2662 xfs_dablk_t prev_bno
;
2665 xfs_daddr_t bd_addr
;
2666 xfs_dahash_t current_hashval
= 0;
2667 xfs_dahash_t greatest_hashval
;
2670 fprintf(stderr
, "process_leaf_dir_level - ino %llu\n", da_cursor
->ino
);
2673 da_bno
= da_cursor
->level
[0].bno
;
2674 ino
= da_cursor
->ino
;
2678 dev_bno
= blkmap_get(da_cursor
->blkmap
, da_bno
);
2680 * directory code uses 0 as the NULL block pointer
2681 * since 0 is the root block and no directory block
2682 * pointer can point to the root block of the btree
2684 ASSERT(da_bno
!= 0);
2686 if (dev_bno
== NULLDFSBNO
) {
2688 _("can't map block %u for directory inode %llu\n"),
2693 bd_addr
= (xfs_daddr_t
)XFS_FSB_TO_DADDR(mp
, dev_bno
);
2695 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, dev_bno
),
2696 XFS_FSB_TO_BB(mp
, 1), 0);
2699 _("can't read file block %u (fsbno %llu, daddr %lld) "
2700 "for directory inode %llu\n"),
2701 da_bno
, dev_bno
, (__int64_t
) bd_addr
, ino
);
2705 leaf
= (xfs_dir_leafblock_t
*)XFS_BUF_PTR(bp
);
2708 * check magic number for leaf directory btree block
2710 if (XFS_DIR_LEAF_MAGIC
!=
2711 INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
)) {
2713 _("bad directory leaf magic # %#x for dir ino %llu\n"),
2714 INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
),
2720 * keep track of greatest block # -- that gets
2721 * us the length of the directory
2723 if (da_bno
> da_cursor
->greatest_bno
)
2724 da_cursor
->greatest_bno
= da_bno
;
2728 * for each block, process the block, verify it's path,
2729 * then get next block. update cursor values along the way
2731 if (process_leaf_dir_block(mp
, leaf
, da_bno
, ino
,
2732 current_hashval
, ino_discovery
,
2733 da_cursor
->blkmap
, dot
, dotdot
, parent
,
2734 &buf_dirty
, &greatest_hashval
)) {
2740 * index can be set to hdr.count so match the
2741 * indexes of the interior blocks -- which at the
2742 * end of the block will point to 1 after the final
2743 * real entry in the block
2745 da_cursor
->level
[0].hashval
= greatest_hashval
;
2746 da_cursor
->level
[0].bp
= bp
;
2747 da_cursor
->level
[0].bno
= da_bno
;
2748 da_cursor
->level
[0].index
= INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
);
2749 da_cursor
->level
[0].dirty
= buf_dirty
;
2751 if (INT_GET(leaf
->hdr
.info
.back
, ARCH_CONVERT
) != prev_bno
) {
2752 do_warn(_("bad sibling back pointer for directory "
2753 "block %u in directory inode %llu\n"),
2760 da_bno
= INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
);
2763 if (verify_da_path(mp
, da_cursor
, 0)) {
2768 current_hashval
= greatest_hashval
;
2770 ASSERT(buf_dirty
== 0 || (buf_dirty
&& !no_modify
));
2772 if (buf_dirty
&& !no_modify
) {
2774 libxfs_writebuf(bp
, 0);
2778 } while (da_bno
!= 0 && res
== 0);
2780 if (verify_final_da_path(mp
, da_cursor
, 0)) {
2782 * verify the final path up (right-hand-side) if still ok
2784 do_warn(_("bad hash path in directory %llu\n"), da_cursor
->ino
);
2789 fprintf(stderr
, "process_leaf_dir_level returns %d (%s)\n",
2790 res
, ((res
) ? "bad" : "ok"));
2793 * redundant but just for testing
2795 release_da_cursor(mp
, da_cursor
, 0);
2801 * release all buffers holding interior btree blocks
2803 err_release_da_cursor(mp
, da_cursor
, 0);
2809 * a node directory is a true btree directory -- where the directory
2810 * has gotten big enough that it is represented as a non-trivial (e.g.
2811 * has more than just a root block) btree.
2813 * Note that if we run into any problems, we trash the
2814 * directory. Even if it's the root directory,
2815 * we'll be able to traverse all the disconnected
2816 * subtrees later (phase 6).
2818 * one day, if we actually fix things, we'll set repair to 1 to
2819 * indicate that we have or that we should.
2821 * dirname can be set to NULL if the name is unknown (or to
2822 * the string representation of the inode)
2824 * returns 0 if things are ok, 1 if bad (directory needs to be junked)
2836 xfs_ino_t
*parent
, /* out - parent ino # or NULLFSINO */
2842 da_bt_cursor_t da_cursor
;
2845 fprintf(stderr
, "process_node_dir - ino %llu\n", ino
);
2847 *repair
= *dot
= *dotdot
= 0;
2848 *parent
= NULLFSINO
;
2851 * try again -- traverse down left-side of tree until we hit
2852 * the left-most leaf block setting up the btree cursor along
2853 * the way. Then walk the leaf blocks left-to-right, calling
2854 * a parent-verification routine each time we traverse a block.
2856 bzero(&da_cursor
, sizeof(da_bt_cursor_t
));
2858 da_cursor
.active
= 0;
2860 da_cursor
.ino
= ino
;
2861 da_cursor
.dip
= dip
;
2862 da_cursor
.greatest_bno
= 0;
2863 da_cursor
.blkmap
= blkmap
;
2866 * now process interior node
2869 error
= traverse_int_dablock(mp
, &da_cursor
, &bno
, XFS_DATA_FORK
);
2875 * now pass cursor and bno into leaf-block processing routine
2876 * the leaf dir level routine checks the interior paths
2877 * up to the root including the final right-most path.
2880 error
= process_leaf_dir_level(mp
, &da_cursor
, ino_discovery
,
2881 repair
, dot
, dotdot
, parent
);
2887 * sanity check inode size
2889 if (INT_GET(dip
->di_core
.di_size
, ARCH_CONVERT
) <
2890 (da_cursor
.greatest_bno
+ 1) * mp
->m_sb
.sb_blocksize
) {
2891 if ((xfs_fsize_t
) da_cursor
.greatest_bno
2892 * mp
->m_sb
.sb_blocksize
> UINT_MAX
) {
2894 _("out of range internal directory block numbers (inode %llu)\n"),
2900 _("setting directory inode (%llu) size to %llu bytes, was %lld bytes\n"),
2902 (xfs_dfiloff_t
) (da_cursor
.greatest_bno
+ 1)
2903 * mp
->m_sb
.sb_blocksize
,
2904 INT_GET(dip
->di_core
.di_size
, ARCH_CONVERT
));
2906 INT_SET(dip
->di_core
.di_size
, ARCH_CONVERT
, (xfs_fsize_t
)
2907 (da_cursor
.greatest_bno
+ 1) * mp
->m_sb
.sb_blocksize
);
2913 * a leaf directory is one where the directory is too big for
2914 * the inode data fork but is small enough to fit into one
2915 * directory btree block (filesystem block) outside the inode
2917 * returns NULLFSINO if the directory is cannot be salvaged
2918 * and the .. ino if things are ok (even if the directory had
2919 * to be altered to make it ok).
2921 * dirname can be set to NULL if the name is unknown (or to
2922 * the string representation of the inode)
2924 * returns 0 if things are ok, 1 if bad (directory needs to be junked)
2935 int *dot
, /* out - 1 if there is a dot, else 0 */
2936 int *dotdot
, /* out - 1 if there's a dotdot, else 0 */
2937 xfs_ino_t
*parent
, /* out - parent ino # or NULLFSINO */
2938 char *dirname
, /* in - directory pathname */
2939 int *repair
) /* out - 1 if something was fixed */
2941 xfs_dir_leafblock_t
*leaf
;
2942 xfs_dahash_t next_hashval
;
2948 fprintf(stderr
, "process_leaf_dir - ino %llu\n", ino
);
2950 *repair
= *dot
= *dotdot
= 0;
2951 *parent
= NULLFSINO
;
2953 bno
= blkmap_get(blkmap
, 0);
2954 if (bno
== NULLDFSBNO
) {
2955 do_warn(_("block 0 for directory inode %llu is missing\n"),
2959 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, bno
),
2960 XFS_FSB_TO_BB(mp
, 1), 0);
2962 do_warn(_("can't read block 0 for directory inode %llu\n"),
2969 leaf
= (xfs_dir_leafblock_t
*)XFS_BUF_PTR(bp
);
2972 * check magic number for leaf directory btree block
2974 if (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) != XFS_DIR_LEAF_MAGIC
) {
2975 do_warn(_("bad directory leaf magic # %#x for dir ino %llu\n"),
2976 INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
), ino
);
2981 if (process_leaf_dir_block(mp
, leaf
, 0, ino
, 0, ino_discovery
, blkmap
,
2982 dot
, dotdot
, parent
, &buf_dirty
, &next_hashval
)) {
2984 * the block is bad. lose the directory.
2985 * XXX - later, we should try and just lose
2986 * the block without losing the entire directory
2988 ASSERT(*dotdot
== 0 || (*dotdot
== 1 && *parent
!= NULLFSINO
));
2994 * check sibling pointers in leaf block (above doesn't do it)
2996 if (INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
) != 0 ||
2997 INT_GET(leaf
->hdr
.info
.back
, ARCH_CONVERT
) != 0) {
2999 do_warn(_("clearing forw/back pointers for "
3000 "directory inode %llu\n"), ino
);
3002 leaf
->hdr
.info
.forw
= 0;
3003 leaf
->hdr
.info
.back
= 0;
3005 do_warn(_("would clear forw/back pointers for "
3006 "directory inode %llu\n"), ino
);
3010 ASSERT(buf_dirty
== 0 || (buf_dirty
&& !no_modify
));
3012 if (buf_dirty
&& !no_modify
)
3013 libxfs_writebuf(bp
, 0);
3021 * returns 1 if things are bad (directory needs to be junked)
3022 * and 0 if things are ok. If ino_discovery is 1, add unknown
3023 * inodes to uncertain inode list.
3041 *parent
= NULLFSINO
;
3045 * branch off depending on the type of inode. This routine
3046 * is only called ONCE so all the subordinate routines will
3047 * fix '.' and junk '..' if they're bogus.
3049 if (INT_GET(dip
->di_core
.di_size
, ARCH_CONVERT
) <=
3050 XFS_DFORK_DSIZE(dip
, mp
)) {
3053 if (process_shortform_dir(mp
, ino
, dip
, ino_discovery
,
3054 dino_dirty
, parent
, dirname
, &repair
)) {
3057 } else if (INT_GET(dip
->di_core
.di_size
, ARCH_CONVERT
) <=
3059 if (process_leaf_dir(mp
, ino
, dip
, ino_discovery
,
3060 dino_dirty
, blkmap
, &dot
, &dotdot
,
3061 parent
, dirname
, &repair
)) {
3065 if (process_node_dir(mp
, ino
, dip
, ino_discovery
,
3066 blkmap
, &dot
, &dotdot
,
3067 parent
, dirname
, &repair
)) {
3072 * bad . entries in all directories will be fixed up in phase 6
3075 do_warn(_("no . entry for directory %llu\n"), ino
);
3079 * shortform dirs always have a .. entry. .. for all longform
3080 * directories will get fixed in phase 6. .. for other shortform
3081 * dirs also get fixed there. .. for a shortform root was
3082 * fixed in place since we know what it should be
3084 if (dotdot
== 0 && ino
!= mp
->m_sb
.sb_rootino
) {
3085 do_warn(_("no .. entry for directory %llu\n"), ino
);
3086 } else if (dotdot
== 0 && ino
== mp
->m_sb
.sb_rootino
) {
3087 do_warn(_("no .. entry for root directory %llu\n"), ino
);
3088 need_root_dotdot
= 1;
3092 fprintf(stderr
, "(process_dir), parent of %llu is %llu\n", ino
, parent
);