2
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of version 2 of the GNU General Public License as
6
* published by the Free Software Foundation.
8
* This program is distributed in the hope that it would be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
* Further, this software is distributed without any warranty that it is
13
* free of the rightful claim of any third person regarding infringement
14
* or the like. Any license provided herein, whether implied or
15
* otherwise, applies only to this software file. Patent licenses, if
16
* any, provided herein do not apply to combinations of this program with
17
* other software, or any other product whatsoever.
19
* You should have received a copy of the GNU General Public License along
20
* with this program; if not, write the Free Software Foundation, Inc., 59
21
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
23
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24
* Mountain View, CA 94043, or:
28
* For further information regarding this notice, see:
30
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
39
#include "err_protos.h"
44
#if XFS_DIR_LEAF_MAPSIZE >= XFS_ATTR_LEAF_MAPSIZE
45
#define XR_DA_LEAF_MAPSIZE XFS_DIR_LEAF_MAPSIZE
47
#define XR_DA_LEAF_MAPSIZE XFS_ATTR_LEAF_MAPSIZE
52
typedef struct da_hole_map {
58
} hentries[XR_DA_LEAF_MAPSIZE];
62
* takes a name and length (name need not be null-terminated)
63
* and returns 1 if the name contains a '/' or a \0, returns 0
67
namecheck(char *name, int length)
72
ASSERT(length < MAXNAMELEN);
74
for (c = name, i = 0; i < length; i++, c++) {
75
if (*c == '/' || *c == '\0')
83
* this routine performs inode discovery and tries to fix things
84
* in place. available redundancy -- inode data size should match
85
* used directory space in inode. returns number of valid directory
86
* entries. a non-zero return value means the directory is bogus
87
* and should be blasted.
91
process_shortform_dir(
96
int *dino_dirty, /* out - 1 if dinode buffer dirty? */
97
xfs_ino_t *parent, /* out - NULLFSINO if entry doesn't exist */
98
char *dirname, /* directory pathname */
99
int *repair) /* out - 1 if dir was fixed up */
101
xfs_dir_shortform_t *sf;
102
xfs_dir_sf_entry_t *sf_entry, *next_sfe, *tmp_sfe;
105
__int64_t ino_dir_size;
114
ino_tree_node_t *irec_p;
115
char name[MAXNAMELEN + 1];
118
fprintf(stderr, "process_shortform_dir - inode %llu\n", ino);
121
sf = &dip->di_u.di_dirsf;
123
max_size = XFS_DFORK_DSIZE_ARCH(dip, mp, ARCH_CONVERT);
124
num_entries = INT_GET(sf->hdr.count, ARCH_CONVERT);
125
ino_dir_size = INT_GET(dip->di_core.di_size, ARCH_CONVERT);
128
ASSERT(ino_dir_size <= max_size);
131
* check for bad entry count
133
if (num_entries * sizeof(xfs_dir_sf_entry_t) + sizeof(xfs_dir_sf_hdr_t)
134
> max_size || num_entries == 0)
138
* run through entries, stop at first bad entry, don't need
139
* to check for .. since that's encoded in its own field
141
sf_entry = next_sfe = &sf->list[0];
142
for (i = 0; i < num_entries && ino_dir_size >
143
(__psint_t)next_sfe - (__psint_t)sf; i++) {
148
XFS_DIR_SF_GET_DIRINO_ARCH(&sf_entry->inumber, &lino, ARCH_CONVERT);
151
* if entry points to self, junk it since only '.' or '..'
152
* should do that and shortform dirs don't contain either
153
* entry. if inode number is invalid, trash entry.
154
* if entry points to special inodes, trash it.
155
* if inode is unknown but number is valid,
156
* add it to the list of uncertain inodes. don't
157
* have to worry about an entry pointing to a
158
* deleted lost+found inode because the entry was
159
* deleted at the same time that the inode was cleared.
163
} else if (verify_inum(mp, lino)) {
165
* junk the entry, mark lino as NULL since it's bad
167
do_warn("invalid inode number %llu in directory %llu\n",
171
} else if (lino == mp->m_sb.sb_rbmino) {
173
"entry in shorform dir %llu references realtime bitmap inode %llu\n",
176
} else if (lino == mp->m_sb.sb_rsumino) {
178
"entry in shorform dir %llu references realtime summary inode %llu\n",
181
} else if (lino == mp->m_sb.sb_uquotino) {
183
"entry in shorform dir %llu references user quota inode %llu\n",
186
} else if (lino == mp->m_sb.sb_gquotino) {
188
"entry in shorform dir %llu references group quota inode %llu\n",
191
} else if ((irec_p = find_inode_rec(XFS_INO_TO_AGNO(mp, lino),
192
XFS_INO_TO_AGINO(mp, lino))) != NULL) {
194
* if inode is marked free and we're in inode
195
* discovery mode, leave the entry alone for now.
196
* if the inode turns out to be used, we'll figure
197
* that out when we scan it. If the inode really
198
* is free, we'll hit this code again in phase 4
199
* after we've finished inode discovery and blow
200
* out the entry then.
202
ino_off = XFS_INO_TO_AGINO(mp, lino) -
203
irec_p->ino_startnum;
204
ASSERT(is_inode_confirmed(irec_p, ino_off));
206
if (!ino_discovery && is_inode_free(irec_p, ino_off)) {
208
"entry references free inode %llu in shortform directory %llu\n",
212
} else if (ino_discovery) {
214
* put the inode on the uncertain list. we'll
215
* pull the inode off the list and check it later.
216
* if the inode turns out be bogus, we'll delete
217
* this entry in phase 6.
219
add_inode_uncertain(mp, lino, 0);
222
* blow the entry out. we know about all
223
* undiscovered entries now (past inode discovery
224
* phase) so this is clearly a bogus entry.
227
"entry references non-existent inode %llu in shortform dir %llu\n",
232
namelen = sf_entry->namelen;
236
* if we're really lucky, this is
237
* the last entry in which case we
238
* can use the dir size to set the
239
* namelen value. otherwise, forget
240
* it because we're not going to be
241
* able to find the next entry.
245
if (i == num_entries - 1) {
246
namelen = ino_dir_size -
247
((__psint_t) &sf_entry->name[0] -
251
"zero length entry in shortform dir %llu, resetting to %d\n",
253
sf_entry->namelen = namelen;
256
"zero length entry in shortform dir %llu, would set to %d\n",
261
"zero length entry in shortform dir %llu",
264
do_warn(", junking %d entries\n",
267
do_warn(", would junk %d entries\n",
270
* don't process the rest of the directory,
271
* break out of processing looop
275
} else if ((__psint_t) sf_entry - (__psint_t) sf +
276
+ XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry)
280
if (i == num_entries - 1) {
281
namelen = ino_dir_size -
282
((__psint_t) &sf_entry->name[0] -
285
"size of last entry overflows space left in in shortform dir %llu, ",
288
do_warn("resetting to %d\n",
290
sf_entry->namelen = namelen;
293
do_warn("would reset to %d\n",
298
"size of entry #%d overflows space left in in shortform dir %llu\n",
301
if (i == num_entries - 1)
302
do_warn("junking entry #%d\n",
306
"junking %d entries\n",
309
if (i == num_entries - 1)
311
"would junk entry #%d\n",
315
"would junk %d entries\n",
324
* check for illegal chars in name.
325
* no need to check for bad length because
326
* the length value is stored in a byte
327
* so it can't be too big, it can only wrap
329
if (namecheck((char *)&sf_entry->name[0], namelen)) {
334
"entry contains illegal character in shortform dir %llu\n",
340
* junk the entry by copying up the rest of the
341
* fork over the current entry and decrementing
342
* the entry count. if we're in no_modify mode,
343
* just issue the warning instead. then continue
344
* the loop with the next_sfe pointer set to the
345
* correct place in the fork and other counters
346
* properly set to reflect the deletion if it
350
bcopy(sf_entry->name, name, namelen);
351
name[namelen] = '\0';
354
tmp_elen = XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry);
355
INT_MOD(dip->di_core.di_size, ARCH_CONVERT, -(tmp_elen));
356
ino_dir_size -= tmp_elen;
358
tmp_sfe = (xfs_dir_sf_entry_t *)
359
((__psint_t) sf_entry + tmp_elen);
360
tmp_len = max_size - ((__psint_t) tmp_sfe
363
memmove(sf_entry, tmp_sfe, tmp_len);
365
INT_MOD(sf->hdr.count, ARCH_CONVERT, -1);
367
bzero((void *) ((__psint_t) sf_entry + tmp_len),
371
* reset the tmp value to the current
372
* pointer so we'll process the entry
378
* WARNING: drop the index i by one
379
* so it matches the decremented count
380
* for accurate comparisons later
388
"junking entry \"%s\" in directory inode %llu\n",
392
"would have junked entry \"%s\" in directory inode %llu\n",
398
* go onto next entry unless we've just junked an
399
* entry in which the current entry pointer points
400
* to an unprocessed entry. have to take into zero-len
401
* entries into account in no modify mode since we
402
* calculate size based on next_sfe.
404
next_sfe = (tmp_sfe == NULL)
405
? (xfs_dir_sf_entry_t *) ((__psint_t) sf_entry
407
? XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry)
408
: sizeof(xfs_dir_sf_entry_t) - 1
413
/* sync up sizes and entry counts */
415
if (INT_GET(sf->hdr.count, ARCH_CONVERT) != i) {
417
do_warn("would have corrected entry count in directory %llu from %d to %d\n",
418
ino, INT_GET(sf->hdr.count, ARCH_CONVERT), i);
420
do_warn("corrected entry count in directory %llu, was %d, now %d\n",
421
ino, INT_GET(sf->hdr.count, ARCH_CONVERT), i);
422
INT_SET(sf->hdr.count, ARCH_CONVERT, i);
428
if ((__psint_t) next_sfe - (__psint_t) sf != ino_dir_size) {
431
"would have corrected directory %llu size from %lld to %lld\n",
432
ino, (__int64_t) ino_dir_size,
433
(__int64_t)((__psint_t) next_sfe - (__psint_t) sf));
436
"corrected directory %llu size, was %lld, now %lld\n",
437
ino, (__int64_t) ino_dir_size,
438
(__int64_t)((__psint_t) next_sfe - (__psint_t) sf));
440
INT_SET(dip->di_core.di_size, ARCH_CONVERT, (xfs_fsize_t)
441
((__psint_t) next_sfe - (__psint_t) sf));
447
* check parent (..) entry
449
XFS_DIR_SF_GET_DIRINO_ARCH(&sf->hdr.parent, parent, ARCH_CONVERT);
452
* if parent entry is bogus, null it out. we'll fix it later .
454
if (verify_inum(mp, *parent)) {
458
"bogus .. inode number (%llu) in directory inode %llu,",
461
do_warn("clearing inode number\n");
463
XFS_DIR_SF_PUT_DIRINO_ARCH(parent, &sf->hdr.parent, ARCH_CONVERT);
467
do_warn("would clear inode number\n");
469
} else if (ino == mp->m_sb.sb_rootino && ino != *parent) {
471
* root directories must have .. == .
475
"corrected root directory %llu .. entry, was %llu, now %llu\n",
478
XFS_DIR_SF_PUT_DIRINO_ARCH(parent, &sf->hdr.parent, ARCH_CONVERT);
483
"would have corrected root directory %llu .. entry from %llu to %llu\n",
486
} else if (ino == *parent && ino != mp->m_sb.sb_rootino) {
488
* likewise, non-root directories can't have .. pointing
492
do_warn("bad .. entry in dir ino %llu, points to self,",
495
do_warn(" clearing inode number\n");
497
XFS_DIR_SF_PUT_DIRINO_ARCH(parent, &sf->hdr.parent, ARCH_CONVERT);
501
do_warn(" would clear inode number\n");
509
* freespace map for directory leaf blocks (1 bit per byte)
510
* 1 == used, 0 == free
512
static da_freemap_t dir_freemap[DA_BMAP_SIZE];
516
alloc_da_freemap(xfs_mount_t *mp)
518
unsigned char *freemap;
520
if ((freemap = malloc(mp->m_sb.sb_blocksize)) == NULL)
523
bzero(freemap, mp->m_sb.sb_blocksize/NBBY);
530
init_da_freemap(da_freemap_t *dir_freemap)
532
bzero(dir_freemap, sizeof(da_freemap_t) * DA_BMAP_SIZE);
536
* sets directory freemap, returns 1 if there is a conflict
537
* returns 0 if everything's good. the range [start, stop) is set.
538
* right now, we just use the static array since only one directory
539
* block will be processed at once even though the interface allows
540
* you to pass in arbitrary da_freemap_t array's.
542
* Within a char, the lowest bit of the char represents the byte with
543
* the smallest address
546
set_da_freemap(xfs_mount_t *mp, da_freemap_t *map, int start, int stop)
548
const da_freemap_t mask = 0x1;
553
* allow == relation since [x, x) claims 1 byte
555
do_warn("bad range claimed [%d, %d) in da block\n",
560
if (stop > mp->m_sb.sb_blocksize) {
562
"byte range end [%d %d) in da block larger than blocksize %d\n",
563
start, stop, mp->m_sb.sb_blocksize);
567
for (i = start; i < stop; i ++) {
568
if (map[i / NBBY] & (mask << i % NBBY)) {
569
do_warn("multiply claimed byte %d in da block\n", i);
572
map[i / NBBY] |= (mask << i % NBBY);
579
* returns 0 if holemap is consistent with reality (as expressed by
580
* the da_freemap_t). returns 1 if there's a conflict.
583
verify_da_freemap(xfs_mount_t *mp, da_freemap_t *map, da_hole_map_t *holes,
584
xfs_ino_t ino, xfs_dablk_t da_bno)
586
int i, j, start, len;
587
const da_freemap_t mask = 0x1;
589
for (i = 0; i < XFS_DIR_LEAF_MAPSIZE; i++) {
590
if (holes->hentries[i].size == 0)
593
start = holes->hentries[i].base;
594
len = holes->hentries[i].size;
596
if (start >= mp->m_sb.sb_blocksize ||
597
start + len > mp->m_sb.sb_blocksize) {
599
"hole (start %d, len %d) out of range, block %d, dir ino %llu\n",
600
start, len, da_bno, ino);
604
for (j = start; j < start + len; j++) {
605
if ((map[j / NBBY] & (mask << (j % NBBY))) != 0) {
607
* bad news -- hole claims a used byte is free
610
"hole claims used byte %d, block %d, dir ino %llu\n",
621
process_da_freemap(xfs_mount_t *mp, da_freemap_t *map, da_hole_map_t *holes)
623
int i, j, in_hole, start, length, smallest, num_holes;
624
const da_freemap_t mask = 0x1;
626
num_holes = in_hole = start = length = 0;
628
for (i = 0; i < mp->m_sb.sb_blocksize; i++) {
629
if ((map[i / NBBY] & (mask << (i % NBBY))) == 0) {
631
* byte is free (unused)
636
* start of a new hole
651
* if the hole disappears, throw it away
660
for (smallest = j = 0; j < XR_DA_LEAF_MAPSIZE; j++) {
661
if (holes->hentries[j].size <
662
holes->hentries[smallest].size)
666
if (length > holes->hentries[smallest].size) {
667
holes->hentries[smallest].base = start;
668
holes->hentries[smallest].size = length;
674
* see if we have a big hole at the end
678
* duplicate of hole placement code above
685
for (smallest = j = 0; j < XR_DA_LEAF_MAPSIZE; j++) {
686
if (holes->hentries[j].size <
687
holes->hentries[smallest].size)
691
if (length > holes->hentries[smallest].size) {
692
holes->hentries[smallest].base = start;
693
holes->hentries[smallest].size = length;
698
holes->lost_holes = MAX(num_holes - XR_DA_LEAF_MAPSIZE, 0);
699
holes->num_holes = num_holes;
705
* returns 1 if the hole info doesn't match, 0 if it does
709
compare_da_freemaps(xfs_mount_t *mp, da_hole_map_t *holemap,
710
da_hole_map_t *block_hmap, int entries,
711
xfs_ino_t ino, xfs_dablk_t da_bno)
713
int i, k, res, found;
718
* we chop holemap->lost_holes down to being two-valued
719
* value (1 or 0) for the test because the filesystem
720
* value is two-valued
722
if ((holemap->lost_holes > 0 ? 1 : 0) != block_hmap->lost_holes) {
725
"- derived hole value %d, saw %d, block %d, dir ino %llu\n",
726
holemap->lost_holes, block_hmap->lost_holes,
733
for (i = 0; i < entries; i++) {
734
for (found = k = 0; k < entries; k++) {
735
if (holemap->hentries[i].base ==
736
block_hmap->hentries[k].base
737
&& holemap->hentries[i].size ==
738
block_hmap->hentries[k].size)
744
"- derived hole (base %d, size %d) in block %d, dir inode %llu not found\n",
745
holemap->hentries[i].base,
746
holemap->hentries[i].size,
759
test(xfs_mount_t *mp)
762
da_hole_map_t holemap;
764
init_da_freemap(dir_freemap);
765
bzero(&holemap, sizeof(da_hole_map_t));
767
set_da_freemap(mp, dir_freemap, 0, 50);
768
set_da_freemap(mp, dir_freemap, 100, 126);
769
set_da_freemap(mp, dir_freemap, 126, 129);
770
set_da_freemap(mp, dir_freemap, 130, 131);
771
set_da_freemap(mp, dir_freemap, 150, 160);
772
process_da_freemap(mp, dir_freemap, &holemap);
780
* walk tree from root to the left-most leaf block reading in
781
* blocks and setting up cursor. passes back file block number of the
782
* left-most leaf block if successful (bno). returns 1 if successful,
786
traverse_int_dablock(xfs_mount_t *mp,
787
da_bt_cursor_t *da_cursor,
793
xfs_da_intnode_t *node;
798
* traverse down left-side of tree until we hit the
799
* left-most leaf block setting up the btree cursor along
805
da_cursor->active = 0;
809
* read in each block along the way and set up cursor
811
fsbno = blkmap_get(da_cursor->blkmap, bno);
813
if (fsbno == NULLDFSBNO)
816
bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, fsbno),
817
XFS_FSB_TO_BB(mp, 1), 0);
819
if (whichfork == XFS_DATA_FORK)
820
do_warn("can't read block %u (fsbno %llu) for "
821
"directory inode %llu\n",
822
bno, fsbno, da_cursor->ino);
824
do_warn("can't read block %u (fsbno %llu) for "
825
"attrbute fork of inode %llu\n",
826
bno, fsbno, da_cursor->ino);
830
node = (xfs_da_intnode_t *)XFS_BUF_PTR(bp);
832
if (INT_GET(node->hdr.info.magic, ARCH_CONVERT) != XFS_DA_NODE_MAGIC) {
833
do_warn("bad dir/attr magic number in inode %llu, file "
834
"bno = %u, fsbno = %llu\n", da_cursor->ino, bno, fsbno);
838
if (INT_GET(node->hdr.count, ARCH_CONVERT) > XFS_DA_NODE_ENTRIES(mp)) {
839
do_warn("bad record count in inode %llu, count = %d, max = %d\n",
840
da_cursor->ino, INT_GET(node->hdr.count, ARCH_CONVERT),
841
XFS_DA_NODE_ENTRIES(mp));
847
* maintain level counter
850
i = da_cursor->active = INT_GET(node->hdr.level, ARCH_CONVERT);
852
if (INT_GET(node->hdr.level, ARCH_CONVERT) == i - 1) {
855
if (whichfork == XFS_DATA_FORK)
856
do_warn("bad directory btree for directory "
857
"inode %llu\n", da_cursor->ino);
859
do_warn("bad attribute fork btree for "
860
"inode %llu\n", da_cursor->ino);
866
da_cursor->level[i].hashval =
867
INT_GET(node->btree[0].hashval, ARCH_CONVERT);
868
da_cursor->level[i].bp = bp;
869
da_cursor->level[i].bno = bno;
870
da_cursor->level[i].index = 0;
872
da_cursor->level[i].n = XFS_BUF_TO_DA_INTNODE(bp);
876
* set up new bno for next level down
878
bno = INT_GET(node->btree[0].before, ARCH_CONVERT);
879
} while(node != NULL && i > 1);
882
* now return block number and get out
884
*rbno = da_cursor->level[0].bno = bno;
888
while (i > 1 && i <= da_cursor->active) {
889
libxfs_putbuf(da_cursor->level[i].bp);
897
* blow out buffer for this level and all the rest above as well
898
* if error == 0, we are not expecting to encounter any unreleased
899
* buffers (e.g. if we do, it's a mistake). if error == 1, we're
900
* in an error-handling case so unreleased buffers may exist.
903
release_da_cursor_int(xfs_mount_t *mp,
904
da_bt_cursor_t *cursor,
908
int level = prev_level + 1;
910
if (cursor->level[level].bp != NULL) {
912
do_warn("release_da_cursor_int got unexpected non-null bp, "
913
"dabno = %u\n", cursor->level[level].bno);
917
libxfs_putbuf(cursor->level[level].bp);
918
cursor->level[level].bp = NULL;
921
if (level < cursor->active)
922
release_da_cursor_int(mp, cursor, level, error);
928
release_da_cursor(xfs_mount_t *mp,
929
da_bt_cursor_t *cursor,
932
release_da_cursor_int(mp, cursor, prev_level, 0);
936
err_release_da_cursor(xfs_mount_t *mp,
937
da_bt_cursor_t *cursor,
940
release_da_cursor_int(mp, cursor, prev_level, 1);
944
* like traverse_int_dablock only it does far less checking
945
* and doesn't maintain the cursor. Just gets you to the
946
* leftmost block in the directory. returns the fsbno
947
* of that block if successful, NULLDFSBNO if not.
950
get_first_dblock_fsbno(xfs_mount_t *mp,
956
xfs_da_intnode_t *node;
961
* traverse down left-side of tree until we hit the
962
* left-most leaf block setting up the btree cursor along
969
fsbno = get_bmapi(mp, dino, ino, bno, XFS_DATA_FORK);
971
if (fsbno == NULLDFSBNO) {
972
do_warn("bmap of block #%u of inode %llu failed\n",
977
if (INT_GET(dino->di_core.di_size, ARCH_CONVERT) <= XFS_LBSIZE(mp))
982
* walk down left side of btree, release buffers as you
983
* go. if the root block is a leaf (single-level btree),
988
bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, fsbno),
989
XFS_FSB_TO_BB(mp, 1), 0);
991
do_warn("can't read block %u (fsbno %llu) for directory "
992
"inode %llu\n", bno, fsbno, ino);
996
node = (xfs_da_intnode_t *)XFS_BUF_PTR(bp);
998
if (INT_GET(node->hdr.info.magic, ARCH_CONVERT) != XFS_DA_NODE_MAGIC) {
999
do_warn("bad dir/attr magic number in inode %llu, file "
1000
"bno = %u, fsbno = %llu\n", ino, bno, fsbno);
1006
i = INT_GET(node->hdr.level, ARCH_CONVERT);
1007
bno = INT_GET(node->btree[0].before, ARCH_CONVERT);
1011
fsbno = get_bmapi(mp, dino, ino, bno, XFS_DATA_FORK);
1013
if (fsbno == NULLDFSBNO) {
1014
do_warn("bmap of block #%u of inode %llu failed\n", bno, ino);
1025
* make sure that all entries in all blocks along the right side of
1026
* of the tree are used and hashval's are consistent. level is the
1027
* level of the descendent block. returns 0 if good (even if it had
1028
* to be fixed up), and 1 if bad. The right edge of the tree is
1029
* technically a block boundary. this routine should be used then
1030
* instead of verify_da_path().
1033
verify_final_da_path(xfs_mount_t *mp,
1034
da_bt_cursor_t *cursor,
1037
xfs_da_intnode_t *node;
1040
int this_level = p_level + 1;
1043
fprintf(stderr, "in verify_final_da_path, this_level = %d\n",
1047
* the index should point to the next "unprocessed" entry
1048
* in the block which should be the final (rightmost) entry
1050
entry = cursor->level[this_level].index;
1051
node = (xfs_da_intnode_t *)XFS_BUF_PTR(cursor->level[this_level].bp);
1053
* check internal block consistency on this level -- ensure
1054
* that all entries are used, encountered and expected hashvals
1057
if (entry != INT_GET(node->hdr.count, ARCH_CONVERT) - 1) {
1058
do_warn("directory/attribute block used/count inconsistency - %d/%hu\n",
1059
entry, INT_GET(node->hdr.count, ARCH_CONVERT));
1063
* hash values monotonically increasing ???
1065
if (cursor->level[this_level].hashval >=
1066
INT_GET(node->btree[entry].hashval, ARCH_CONVERT)) {
1067
do_warn("directory/attribute block hashvalue inconsistency, "
1068
"expected > %u / saw %u\n", cursor->level[this_level].hashval,
1069
INT_GET(node->btree[entry].hashval, ARCH_CONVERT));
1072
if (INT_GET(node->hdr.info.forw, ARCH_CONVERT) != 0) {
1073
do_warn("bad directory/attribute forward block pointer, expected 0, "
1074
"saw %u\n", INT_GET(node->hdr.info.forw, ARCH_CONVERT));
1078
do_warn("bad directory block in dir ino %llu\n", cursor->ino);
1082
* keep track of greatest block # -- that gets
1083
* us the length of the directory
1085
if (cursor->level[this_level].bno > cursor->greatest_bno)
1086
cursor->greatest_bno = cursor->level[this_level].bno;
1089
* ok, now check descendant block number against this level
1091
if (cursor->level[p_level].bno !=
1092
INT_GET(node->btree[entry].before, ARCH_CONVERT)) {
1094
fprintf(stderr, "bad directory btree pointer, child bno should be %d, "
1095
"block bno is %d, hashval is %u\n",
1096
INT_GET(node->btree[entry].before, ARCH_CONVERT),
1097
cursor->level[p_level].bno,
1098
cursor->level[p_level].hashval);
1099
fprintf(stderr, "verify_final_da_path returns 1 (bad) #1a\n");
1104
if (cursor->level[p_level].hashval !=
1105
INT_GET(node->btree[entry].hashval, ARCH_CONVERT)) {
1107
do_warn("correcting bad hashval in non-leaf dir/attr block\n");
1108
do_warn("\tin (level %d) in inode %llu.\n",
1109
this_level, cursor->ino);
1110
INT_SET(node->btree[entry].hashval, ARCH_CONVERT,
1111
cursor->level[p_level].hashval);
1112
cursor->level[this_level].dirty++;
1114
do_warn("would correct bad hashval in non-leaf dir/attr "
1115
"block\n\tin (level %d) in inode %llu.\n",
1116
this_level, cursor->ino);
1121
* release/write buffer
1123
ASSERT(cursor->level[this_level].dirty == 0 ||
1124
(cursor->level[this_level].dirty && !no_modify));
1126
if (cursor->level[this_level].dirty && !no_modify)
1127
libxfs_writebuf(cursor->level[this_level].bp, 0);
1129
libxfs_putbuf(cursor->level[this_level].bp);
1131
cursor->level[this_level].bp = NULL;
1134
* bail out if this is the root block (top of tree)
1136
if (this_level >= cursor->active) {
1138
fprintf(stderr, "verify_final_da_path returns 0 (ok)\n");
1143
* set hashvalue to correctl reflect the now-validated
1144
* last entry in this block and continue upwards validation
1146
cursor->level[this_level].hashval =
1147
INT_GET(node->btree[entry].hashval, ARCH_CONVERT);
1148
return(verify_final_da_path(mp, cursor, this_level));
1152
* Verifies the path from a descendant block up to the root.
1153
* Should be called when the descendant level traversal hits
1154
* a block boundary before crossing the boundary (reading in a new
1157
* the directory/attr btrees work differently to the other fs btrees.
1158
* each interior block contains records that are <hashval, bno>
1159
* pairs. The bno is a file bno, not a filesystem bno. The last
1160
* hashvalue in the block <bno> will be <hashval>. BUT unlike
1161
* the freespace btrees, the *last* value in each block gets
1162
* propagated up the tree instead of the first value in each block.
1163
* that is, the interior records point to child blocks and the *greatest*
1164
* hash value contained by the child block is the one the block above
1165
* uses as the key for the child block.
1167
* level is the level of the descendent block. returns 0 if good,
1168
* and 1 if bad. The descendant block may be a leaf block.
1170
* the invariant here is that the values in the cursor for the
1171
* levels beneath this level (this_level) and the cursor index
1172
* for this level *must* be valid.
1174
* that is, the hashval/bno info is accurate for all
1175
* DESCENDANTS and match what the node[index] information
1176
* for the current index in the cursor for this level.
1178
* the index values in the cursor for the descendant level
1179
* are allowed to be off by one as they will reflect the
1180
* next entry at those levels to be processed.
1182
* the hashvalue for the current level can't be set until
1183
* we hit the last entry in the block so, it's garbage
1184
* until set by this routine.
1186
* bno and bp for the current block/level are always valid
1187
* since they have to be set so we can get a buffer for the
1191
verify_da_path(xfs_mount_t *mp,
1192
da_bt_cursor_t *cursor,
1195
xfs_da_intnode_t *node;
1196
xfs_da_intnode_t *newnode;
1202
int this_level = p_level + 1;
1205
* index is currently set to point to the entry that
1206
* should be processed now in this level.
1208
entry = cursor->level[this_level].index;
1209
node = (xfs_da_intnode_t *)XFS_BUF_PTR(cursor->level[this_level].bp);
1212
* if this block is out of entries, validate this
1213
* block and move on to the next block.
1214
* and update cursor value for said level
1216
if (entry >= INT_GET(node->hdr.count, ARCH_CONVERT)) {
1218
* update the hash value for this level before
1219
* validating it. bno value should be ok since
1220
* it was set when the block was first read in.
1222
cursor->level[this_level].hashval =
1223
INT_GET(node->btree[entry - 1].hashval, ARCH_CONVERT);
1226
* keep track of greatest block # -- that gets
1227
* us the length of the directory
1229
if (cursor->level[this_level].bno > cursor->greatest_bno)
1230
cursor->greatest_bno = cursor->level[this_level].bno;
1233
* validate the path for the current used-up block
1234
* before we trash it
1236
if (verify_da_path(mp, cursor, this_level))
1239
* ok, now get the next buffer and check sibling pointers
1241
dabno = INT_GET(node->hdr.info.forw, ARCH_CONVERT);
1243
fsbno = blkmap_get(cursor->blkmap, dabno);
1245
if (fsbno == NULLDFSBNO) {
1246
do_warn("can't get map info for block %u of directory "
1247
"inode %llu\n", dabno, cursor->ino);
1251
bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, fsbno),
1252
XFS_FSB_TO_BB(mp, 1), 0);
1254
do_warn("can't read block %u (%llu) for directory inode %llu\n",
1255
dabno, fsbno, cursor->ino);
1259
newnode = (xfs_da_intnode_t *)XFS_BUF_PTR(bp);
1261
* verify magic number and back pointer, sanity-check
1262
* entry count, verify level
1265
if (INT_GET(newnode->hdr.info.magic, ARCH_CONVERT) != XFS_DA_NODE_MAGIC) {
1266
do_warn("bad magic number %x in block %u (%llu) for directory "
1268
INT_GET(newnode->hdr.info.magic, ARCH_CONVERT),
1269
dabno, fsbno, cursor->ino);
1272
if (INT_GET(newnode->hdr.info.back, ARCH_CONVERT) !=
1273
cursor->level[this_level].bno) {
1274
do_warn("bad back pointer in block %u (%llu) for directory "
1275
"inode %llu\n", dabno, fsbno, cursor->ino);
1278
if (INT_GET(newnode->hdr.count, ARCH_CONVERT) >
1279
XFS_DA_NODE_ENTRIES(mp)) {
1280
do_warn("entry count %d too large in block %u (%llu) for "
1281
"directory inode %llu\n",
1282
INT_GET(newnode->hdr.count, ARCH_CONVERT),
1283
dabno, fsbno, cursor->ino);
1286
if (INT_GET(newnode->hdr.level, ARCH_CONVERT) != this_level) {
1287
do_warn("bad level %d in block %u (%llu) for directory inode "
1288
"%llu\n", INT_GET(newnode->hdr.level, ARCH_CONVERT),
1289
dabno, fsbno, cursor->ino);
1294
fprintf(stderr, "verify_da_path returns 1 (bad) #4\n");
1300
* update cursor, write out the *current* level if
1301
* required. don't write out the descendant level
1303
ASSERT(cursor->level[this_level].dirty == 0 ||
1304
(cursor->level[this_level].dirty && !no_modify));
1306
if (cursor->level[this_level].dirty && !no_modify)
1307
libxfs_writebuf(cursor->level[this_level].bp, 0);
1309
libxfs_putbuf(cursor->level[this_level].bp);
1310
cursor->level[this_level].bp = bp;
1311
cursor->level[this_level].dirty = 0;
1312
cursor->level[this_level].bno = dabno;
1313
cursor->level[this_level].hashval =
1314
INT_GET(newnode->btree[0].hashval, ARCH_CONVERT);
1316
cursor->level[this_level].n = newnode;
1320
entry = cursor->level[this_level].index = 0;
1323
* ditto for block numbers
1325
if (cursor->level[p_level].bno !=
1326
INT_GET(node->btree[entry].before, ARCH_CONVERT)) {
1328
fprintf(stderr, "bad directory btree pointer, child bno should be %d, "
1329
"block bno is %d, hashval is %u\n",
1330
INT_GET(node->btree[entry].before, ARCH_CONVERT),
1331
cursor->level[p_level].bno,
1332
cursor->level[p_level].hashval);
1333
fprintf(stderr, "verify_da_path returns 1 (bad) #1a\n");
1338
* ok, now validate last hashvalue in the descendant
1339
* block against the hashval in the current entry
1341
if (cursor->level[p_level].hashval !=
1342
INT_GET(node->btree[entry].hashval, ARCH_CONVERT)) {
1344
do_warn("correcting bad hashval in interior dir/attr block\n");
1345
do_warn("\tin (level %d) in inode %llu.\n",
1346
this_level, cursor->ino);
1347
INT_SET(node->btree[entry].hashval, ARCH_CONVERT,
1348
cursor->level[p_level].hashval);
1349
cursor->level[this_level].dirty++;
1351
do_warn("would correct bad hashval in interior dir/attr "
1352
"block\n\tin (level %d) in inode %llu.\n",
1353
this_level, cursor->ino);
1357
* increment index for this level to point to next entry
1358
* (which should point to the next descendant block)
1360
cursor->level[this_level].index++;
1362
fprintf(stderr, "verify_da_path returns 0 (ok)\n");
1369
* handles junking directory leaf block entries that have zero lengths
1370
* buf_dirty is an in/out, set to 1 if the leaf was modified.
1371
* we do NOT initialize it to zero if nothing happened because it
1372
* may be already set by the caller. Assumes that the block
1373
* has been compacted before calling this routine.
1376
junk_zerolen_dir_leaf_entries(
1378
xfs_dir_leafblock_t *leaf,
1382
xfs_dir_leaf_entry_t *entry;
1383
xfs_dir_leaf_name_t *namest;
1384
xfs_dir_leaf_hdr_t *hdr;
1385
xfs_dir_leaf_map_t *map;
1389
int current_hole = 0;
1399
entry = &leaf->entries[0];
1403
* we can convert the entries to one character entries
1404
* as long as we have space. Once we run out, then
1405
* we have to delete really delete (copy over) an entry.
1406
* however, that frees up some space that we could use ...
1408
* so the idea is, we'll use up space from all the holes,
1409
* potentially leaving each hole too small to do any good.
1410
* then if need to, we'll delete entries and use that space
1411
* up from the top-most byte down. that may leave a 4th hole
1412
* but we can represent that by correctly setting the value
1413
* of firstused. that leaves any hole between the end of
1414
* the entry list and firstused so it doesn't have to be
1415
* recorded in the hole map.
1418
for (bytes = i = 0; i < INT_GET(hdr->count, ARCH_CONVERT); entry++, i++) {
1420
* skip over entries that are good or already converted
1422
if (entry->namelen != 0)
1428
* try and use up existing holes first until they get
1429
* too small, then set bytes to the # of bytes between
1430
* the current heap beginning and the last used byte
1431
* in the entry table.
1433
if (bytes < sizeof(xfs_dir_leaf_name_t) &&
1434
current_hole < XFS_DIR_LEAF_MAPSIZE) {
1436
* skip over holes that are too small
1438
while (current_hole < XFS_DIR_LEAF_MAPSIZE &&
1439
INT_GET(hdr->freemap[current_hole].size, ARCH_CONVERT) <
1440
sizeof(xfs_dir_leaf_name_t)) {
1444
if (current_hole < XFS_DIR_LEAF_MAPSIZE)
1445
bytes = INT_GET(hdr->freemap[current_hole].size, ARCH_CONVERT);
1447
bytes = (int) INT_GET(hdr->firstused, ARCH_CONVERT) -
1448
((__psint_t) &leaf->entries[INT_GET(hdr->count, ARCH_CONVERT)] -
1454
for (map = &hdr->freemap[0];
1455
current_hole < XFS_DIR_LEAF_MAPSIZE &&
1456
INT_GET(map->size, ARCH_CONVERT) < sizeof(xfs_dir_leaf_name_t);
1462
* if we can use an existing hole, do it. otherwise,
1463
* delete entries until the deletions create a big enough
1464
* hole to convert another entry. then use up those bytes
1465
* bytes until you run low. then delete entries again ...
1467
if (current_hole < XFS_DIR_LEAF_MAPSIZE) {
1468
ASSERT(sizeof(xfs_dir_leaf_name_t) <= bytes);
1470
do_warn("marking bad entry in directory inode %llu\n",
1474
INT_SET(entry->nameidx, ARCH_CONVERT, INT_GET(hdr->freemap[current_hole].base, ARCH_CONVERT) +
1475
bytes - sizeof(xfs_dir_leaf_name_t));
1477
namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
1478
tmp_ino = NULLFSINO;
1479
XFS_DIR_SF_PUT_DIRINO_ARCH(&tmp_ino, &namest->inumber, ARCH_CONVERT);
1480
namest->name[0] = '/';
1482
if (INT_GET(entry->nameidx, ARCH_CONVERT) < INT_GET(hdr->firstused, ARCH_CONVERT))
1483
INT_SET(hdr->firstused, ARCH_CONVERT, INT_GET(entry->nameidx, ARCH_CONVERT));
1484
INT_MOD(hdr->freemap[current_hole].size, ARCH_CONVERT, -(sizeof(xfs_dir_leaf_name_t)));
1485
INT_MOD(hdr->namebytes, ARCH_CONVERT, +1);
1488
* delete the table entry and try and account for the
1489
* space in the holemap. don't have to update namebytes
1490
* or firstused since we're not actually deleting any
1491
* bytes from the heap. following code swiped from
1492
* xfs_dir_leaf_remove() in xfs_dir_leaf.c
1494
INT_MOD(hdr->count, ARCH_CONVERT, -1);
1496
"deleting zero length entry in directory inode %llu\n",
1499
* overwrite the bad entry unless it's the
1500
* last entry in the list (highly unlikely).
1501
* zero out the free'd bytes.
1503
if (INT_GET(hdr->count, ARCH_CONVERT) - i > 0) {
1504
memmove(entry, entry + 1, (INT_GET(hdr->count, ARCH_CONVERT) - i) *
1505
sizeof(xfs_dir_leaf_entry_t));
1507
bzero((void *) ((__psint_t) entry +
1508
(INT_GET(leaf->hdr.count, ARCH_CONVERT) - i - 1) *
1509
sizeof(xfs_dir_leaf_entry_t)),
1510
sizeof(xfs_dir_leaf_entry_t));
1512
start = (__psint_t) &leaf->entries[INT_GET(hdr->count, ARCH_CONVERT)] -
1514
tablesize = sizeof(xfs_dir_leaf_entry_t) *
1515
(INT_GET(hdr->count, ARCH_CONVERT) + 1) + sizeof(xfs_dir_leaf_hdr_t);
1516
map = &hdr->freemap[0];
1517
tmp = INT_GET(map->size, ARCH_CONVERT);
1518
before = after = -1;
1519
smallest = XFS_DIR_LEAF_MAPSIZE - 1;
1520
for (j = 0; j < XFS_DIR_LEAF_MAPSIZE; map++, j++) {
1521
ASSERT(INT_GET(map->base, ARCH_CONVERT) < XFS_LBSIZE(mp));
1522
ASSERT(INT_GET(map->size, ARCH_CONVERT) < XFS_LBSIZE(mp));
1523
if (INT_GET(map->base, ARCH_CONVERT) == tablesize) {
1524
INT_MOD(map->base, ARCH_CONVERT, -(sizeof(xfs_dir_leaf_entry_t)));
1525
INT_MOD(map->size, ARCH_CONVERT, sizeof(xfs_dir_leaf_entry_t));
1528
if ((INT_GET(map->base, ARCH_CONVERT) + INT_GET(map->size, ARCH_CONVERT)) == start) {
1530
} else if (INT_GET(map->base, ARCH_CONVERT) == start +
1531
sizeof(xfs_dir_leaf_entry_t)) {
1533
} else if (INT_GET(map->size, ARCH_CONVERT) < tmp) {
1534
tmp = INT_GET(map->size, ARCH_CONVERT);
1540
* Coalesce adjacent freemap regions,
1541
* or replace the smallest region.
1543
if ((before >= 0) || (after >= 0)) {
1544
if ((before >= 0) && (after >= 0)) {
1545
map = &hdr->freemap[before];
1546
INT_MOD(map->size, ARCH_CONVERT, sizeof(xfs_dir_leaf_entry_t));
1547
INT_MOD(map->size, ARCH_CONVERT, INT_GET(hdr->freemap[after].size, ARCH_CONVERT));
1548
INT_ZERO(hdr->freemap[after].base, ARCH_CONVERT);
1549
INT_ZERO(hdr->freemap[after].size, ARCH_CONVERT);
1550
} else if (before >= 0) {
1551
map = &hdr->freemap[before];
1552
INT_MOD(map->size, ARCH_CONVERT, sizeof(xfs_dir_leaf_entry_t));
1554
map = &hdr->freemap[after];
1555
INT_SET(map->base, ARCH_CONVERT, start);
1556
INT_MOD(map->size, ARCH_CONVERT, sizeof(xfs_dir_leaf_entry_t));
1560
* Replace smallest region
1561
* (if it is smaller than free'd entry)
1563
map = &hdr->freemap[smallest];
1564
if (INT_GET(map->size, ARCH_CONVERT) < sizeof(xfs_dir_leaf_entry_t)) {
1565
INT_SET(map->base, ARCH_CONVERT, start);
1566
INT_SET(map->size, ARCH_CONVERT, sizeof(xfs_dir_leaf_entry_t));
1569
* mark as needing compaction
1575
* do we have to delete stuff or is there
1576
* room for deletions?
1578
ASSERT(current_hole == XFS_DIR_LEAF_MAPSIZE);
1581
* here, bytes == number of unused bytes from
1582
* end of list to top (beginning) of heap
1583
* (firstused). It's ok to leave extra
1584
* unused bytes in that region because they
1585
* wind up before firstused (which we reset
1588
if (bytes < sizeof(xfs_dir_leaf_name_t)) {
1590
* have to delete an entry because
1591
* we have no room to convert it to
1595
"deleting entry in directory inode %llu\n",
1598
* overwrite the bad entry unless it's the
1599
* last entry in the list (highly unlikely).
1601
if (INT_GET(leaf->hdr.count, ARCH_CONVERT) - i - 1> 0) {
1602
memmove(entry, entry + 1,
1603
(INT_GET(leaf->hdr.count, ARCH_CONVERT) - i - 1) *
1604
sizeof(xfs_dir_leaf_entry_t));
1606
bzero((void *) ((__psint_t) entry +
1607
(INT_GET(leaf->hdr.count, ARCH_CONVERT) - i - 1) *
1608
sizeof(xfs_dir_leaf_entry_t)),
1609
sizeof(xfs_dir_leaf_entry_t));
1612
* bump up free byte count, drop other
1613
* index vars since the table just
1614
* shrank by one entry and we don't
1615
* want to miss any as we walk the table
1617
bytes += sizeof(xfs_dir_leaf_entry_t);
1618
INT_MOD(leaf->hdr.count, ARCH_CONVERT, -1);
1623
* convert entry using the bytes in between
1624
* the end of the entry table and the heap
1627
INT_MOD(leaf->hdr.firstused, ARCH_CONVERT, -(sizeof(xfs_dir_leaf_name_t)));
1628
INT_SET(entry->nameidx, ARCH_CONVERT, INT_GET(leaf->hdr.firstused, ARCH_CONVERT));
1630
namest = XFS_DIR_LEAF_NAMESTRUCT(leaf,
1631
INT_GET(entry->nameidx, ARCH_CONVERT));
1632
tmp_ino = NULLFSINO;
1633
XFS_DIR_SF_PUT_DIRINO_ARCH(&tmp_ino,
1634
&namest->inumber, ARCH_CONVERT);
1635
namest->name[0] = '/';
1637
bytes -= sizeof(xfs_dir_leaf_entry_t);
1647
static char dirbuf[64 * 1024];
1650
* called by both node dir and leaf dir processing routines
1651
* validates all contents *but* the sibling pointers (forw/back)
1652
* and the magic number.
1654
* returns 0 if the directory is ok or has been brought to the
1655
* stage that it can be fixed up later (in phase 6),
1656
* 1 if it has to be junked.
1658
* Right now we fix a lot of things (TBD == to be deleted).
1660
* incorrect . entries - inode # is corrected
1661
* entries with mismatched hashvalue/name strings - hashvalue reset
1662
* entries whose hashvalues are out-of-order - entry marked TBD
1663
* .. entries with invalid inode numbers - entry marked TBD
1664
* entries with invalid inode numbers - entry marked TBD
1665
* multiple . entries - all but the first entry are marked TBD
1666
* zero-length entries - entry is deleted
1667
* entries with an out-of-bounds name index ptr - entry is deleted
1669
* entries marked TBD have the first character of the name (which
1670
* lives in the heap) have the first character in the name set
1671
* to '/' -- an illegal value.
1673
* entries deleted right here are deleted by blowing away the entry
1674
* (but leaving the heap untouched). any space that was used
1675
* by the deleted entry will be reclaimed by the block freespace
1676
* (da_freemap) processing code.
1678
* if two entries claim the same space in the heap (say, due to
1679
* bad entry name index pointers), we lose the directory. We could
1680
* try harder to fix this but it'll do for now.
1684
process_leaf_dir_block(
1686
xfs_dir_leafblock_t *leaf,
1689
xfs_dahash_t last_hashval, /* last hashval encountered */
1695
int *buf_dirty, /* is buffer dirty? */
1696
xfs_dahash_t *next_hashval) /* greatest hashval in block */
1699
xfs_dir_leaf_entry_t *entry;
1700
xfs_dir_leaf_entry_t *s_entry;
1701
xfs_dir_leaf_entry_t *d_entry;
1702
xfs_dir_leafblock_t *new_leaf;
1704
xfs_dir_leaf_name_t *namest;
1705
ino_tree_node_t *irec_p;
1707
xfs_dahash_t hashval;
1718
int zero_len_entries;
1719
char fname[MAXNAMELEN + 1];
1720
da_hole_map_t holemap;
1721
da_hole_map_t bholemap;
1723
unsigned char *dir_freemap;
1727
fprintf(stderr, "\tprocess_leaf_dir_block - ino %llu\n", ino);
1731
* clear static dir block freespace bitmap
1733
init_da_freemap(dir_freemap);
1737
* XXX - alternatively, do this for parallel usage.
1738
* set up block freespace map. head part of dir leaf block
1739
* including all entries are packed so we can use sizeof
1740
* and not worry about alignment.
1743
if ((dir_freemap = alloc_da_freemap(mp)) == NULL) {
1744
do_error("couldn't allocate directory block freemap\n");
1750
first_used = mp->m_sb.sb_blocksize;
1751
zero_len_entries = 0;
1754
i = stop = sizeof(xfs_dir_leaf_hdr_t);
1755
if (set_da_freemap(mp, dir_freemap, 0, stop)) {
1757
"directory block header conflicts with used space in directory inode %llu\n",
1763
* verify structure: monotonically increasing hash value for
1764
* all leaf entries, indexes for all entries must be within
1765
* this fs block (trivially true for 64K blocks). also track
1766
* used space so we can check the freespace map. check for
1767
* zero-length entries. for now, if anything's wrong, we
1768
* junk the directory and we'll pick up no-longer referenced
1769
* inodes on a later pass.
1771
for (i = 0, entry = &leaf->entries[0];
1772
i < INT_GET(leaf->hdr.count, ARCH_CONVERT);
1775
* check that the name index isn't out of bounds
1776
* if it is, delete the entry since we can't
1779
if (INT_GET(entry->nameidx, ARCH_CONVERT) >= mp->m_sb.sb_blocksize) {
1783
if (INT_GET(leaf->hdr.count, ARCH_CONVERT) > 1) {
1785
"nameidx %d for entry #%d, bno %d, ino %llu > fs blocksize, deleting entry\n",
1786
INT_GET(entry->nameidx, ARCH_CONVERT), i, da_bno, ino);
1787
ASSERT(INT_GET(leaf->hdr.count, ARCH_CONVERT) > i);
1789
bytes = (INT_GET(leaf->hdr.count, ARCH_CONVERT) - i) *
1790
sizeof(xfs_dir_leaf_entry_t);
1793
* compress table unless we're
1794
* only dealing with 1 entry
1795
* (the last one) in which case
1799
sizeof(xfs_dir_leaf_entry_t)) {
1800
memmove(entry, entry + 1,
1803
((__psint_t) entry + bytes),
1804
sizeof(xfs_dir_leaf_entry_t));
1807
sizeof(xfs_dir_leaf_entry_t));
1811
* sync vars to match smaller table.
1812
* don't have to worry about freespace
1813
* map since we haven't set it for
1816
INT_MOD(leaf->hdr.count, ARCH_CONVERT, -1);
1821
"nameidx %d, entry #%d, bno %d, ino %llu > fs blocksize, marking entry bad\n",
1822
INT_GET(entry->nameidx, ARCH_CONVERT), i, da_bno, ino);
1823
INT_SET(entry->nameidx, ARCH_CONVERT, mp->m_sb.sb_blocksize -
1824
sizeof(xfs_dir_leaf_name_t));
1825
namest = XFS_DIR_LEAF_NAMESTRUCT(leaf,
1826
INT_GET(entry->nameidx, ARCH_CONVERT));
1828
XFS_DIR_SF_PUT_DIRINO_ARCH(&lino,
1829
&namest->inumber, ARCH_CONVERT);
1830
namest->name[0] = '/';
1834
"nameidx %d, entry #%d, bno %d, ino %llu > fs blocksize, would delete entry\n",
1835
INT_GET(entry->nameidx, ARCH_CONVERT), i, da_bno, ino);
1840
* inode processing -- make sure the inode
1841
* is in our tree or we add it to the uncertain
1842
* list if the inode # is valid. if namelen is 0,
1843
* we can still try for the inode as long as nameidx
1846
namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
1847
XFS_DIR_SF_GET_DIRINO_ARCH(&namest->inumber, &lino, ARCH_CONVERT);
1850
* we may have to blow out an entry because of bad
1851
* inode numbers. do NOT touch the name until after
1852
* we've computed the hashvalue and done a namecheck()
1855
if (!ino_discovery && lino == NULLFSINO) {
1857
* don't do a damned thing. We already
1858
* found this (or did it ourselves) during
1861
} else if (verify_inum(mp, lino)) {
1863
* bad inode number. clear the inode
1864
* number and the entry will get removed
1865
* later. We don't trash the directory
1866
* since it's still structurally intact.
1869
"invalid ino number %llu in dir ino %llu, entry #%d, bno %d\n",
1870
lino, ino, i, da_bno);
1873
"\tclearing ino number in entry %d...\n", i);
1876
XFS_DIR_SF_PUT_DIRINO_ARCH(&lino, &namest->inumber, ARCH_CONVERT);
1880
"\twould clear ino number in entry %d...\n", i);
1882
} else if (lino == mp->m_sb.sb_rbmino) {
1884
"entry #%d, bno %d in directory %llu references realtime bitmap inode %llu\n",
1885
i, da_bno, ino, lino);
1888
"\tclearing ino number in entry %d...\n", i);
1891
XFS_DIR_SF_PUT_DIRINO_ARCH(&lino, &namest->inumber, ARCH_CONVERT);
1895
"\twould clear ino number in entry %d...\n", i);
1897
} else if (lino == mp->m_sb.sb_rsumino) {
1899
"entry #%d, bno %d in directory %llu references realtime summary inode %llu\n",
1900
i, da_bno, ino, lino);
1903
"\tclearing ino number in entry %d...\n", i);
1906
XFS_DIR_SF_PUT_DIRINO_ARCH(&lino, &namest->inumber, ARCH_CONVERT);
1910
"\twould clear ino number in entry %d...\n", i);
1912
} else if (lino == mp->m_sb.sb_uquotino) {
1914
"entry #%d, bno %d in directory %llu references user quota inode %llu\n",
1915
i, da_bno, ino, lino);
1918
"\tclearing ino number in entry %d...\n", i);
1921
XFS_DIR_SF_PUT_DIRINO_ARCH(&lino, &namest->inumber, ARCH_CONVERT);
1925
"\twould clear ino number in entry %d...\n", i);
1927
} else if (lino == mp->m_sb.sb_gquotino) {
1929
"entry #%d, bno %d in directory %llu references group quota inode %llu\n",
1930
i, da_bno, ino, lino);
1933
"\tclearing ino number in entry %d...\n", i);
1936
XFS_DIR_SF_PUT_DIRINO_ARCH(&lino, &namest->inumber, ARCH_CONVERT);
1940
"\twould clear ino number in entry %d...\n", i);
1942
} else if (lino == old_orphanage_ino) {
1944
* do nothing, silently ignore it, entry has
1945
* already been marked TBD since old_orphanage_ino
1948
} else if ((irec_p = find_inode_rec(
1949
XFS_INO_TO_AGNO(mp, lino),
1950
XFS_INO_TO_AGINO(mp, lino))) != NULL) {
1952
* inode recs should have only confirmed
1955
ino_off = XFS_INO_TO_AGINO(mp, lino) -
1956
irec_p->ino_startnum;
1957
ASSERT(is_inode_confirmed(irec_p, ino_off));
1959
* if inode is marked free and we're in inode
1960
* discovery mode, leave the entry alone for now.
1961
* if the inode turns out to be used, we'll figure
1962
* that out when we scan it. If the inode really
1963
* is free, we'll hit this code again in phase 4
1964
* after we've finished inode discovery and blow
1965
* out the entry then.
1967
if (!ino_discovery && is_inode_free(irec_p, ino_off)) {
1970
"entry references free inode %llu in directory %llu, will clear entry\n",
1973
XFS_DIR_SF_PUT_DIRINO_ARCH(&lino,
1974
&namest->inumber, ARCH_CONVERT);
1978
"entry references free inode %llu in directory %llu, would clear entry\n",
1982
} else if (ino_discovery) {
1983
add_inode_uncertain(mp, lino, 0);
1986
"bad ino number %llu in dir ino %llu, entry #%d, bno %d\n",
1987
lino, ino, i, da_bno);
1989
do_warn("clearing inode number...\n");
1991
XFS_DIR_SF_PUT_DIRINO_ARCH(&lino, &namest->inumber, ARCH_CONVERT);
1994
do_warn("would clear inode number...\n");
1998
* if we have a zero-length entry, trash it.
1999
* we may lose the inode (chunk) if we don't
2000
* finish the repair successfully and the inode
2001
* isn't mentioned anywhere else (like in the inode
2002
* tree) but the alternative is to risk losing the
2003
* entire directory by trying to use the next byte
2004
* to turn the entry into a 1-char entry. That's
2005
* probably a safe bet but if it didn't work, we'd
2006
* lose the entire directory the way we currently do
2007
* things. (Maybe we should change that later :-).
2009
if (entry->namelen == 0) {
2012
if (INT_GET(leaf->hdr.count, ARCH_CONVERT) > 1) {
2014
"entry #%d, dir inode %llu, has zero-len name, deleting entry\n",
2016
ASSERT(INT_GET(leaf->hdr.count, ARCH_CONVERT) > i);
2018
bytes = (INT_GET(leaf->hdr.count, ARCH_CONVERT) - i) *
2019
sizeof(xfs_dir_leaf_entry_t);
2022
* compress table unless we're
2023
* only dealing with 1 entry
2024
* (the last one) in which case
2027
if (bytes > sizeof(xfs_dir_leaf_entry_t)) {
2028
memmove(entry, entry + 1,
2031
((__psint_t) entry + bytes),
2032
sizeof(xfs_dir_leaf_entry_t));
2035
sizeof(xfs_dir_leaf_entry_t));
2039
* sync vars to match smaller table.
2040
* don't have to worry about freespace
2041
* map since we haven't set it for
2044
INT_MOD(leaf->hdr.count, ARCH_CONVERT, -1);
2049
* if it's the only entry, preserve the
2050
* inode number for now
2053
"entry #%d, dir inode %llu, has zero-len name, marking entry bad\n",
2055
INT_SET(entry->nameidx, ARCH_CONVERT, mp->m_sb.sb_blocksize -
2056
sizeof(xfs_dir_leaf_name_t));
2057
namest = XFS_DIR_LEAF_NAMESTRUCT(leaf,
2058
INT_GET(entry->nameidx, ARCH_CONVERT));
2059
XFS_DIR_SF_PUT_DIRINO_ARCH(&lino, &namest->inumber, ARCH_CONVERT);
2060
namest->name[0] = '/';
2062
} else if (INT_GET(entry->nameidx, ARCH_CONVERT) + entry->namelen > XFS_LBSIZE(mp)) {
2064
"bad size, entry #%d in dir inode %llu, block %u -- entry overflows block\n",
2070
start = (__psint_t)&leaf->entries[i] - (__psint_t)leaf;;
2071
stop = start + sizeof(xfs_dir_leaf_entry_t);
2073
if (set_da_freemap(mp, dir_freemap, start, stop)) {
2075
"dir entry slot %d in block %u conflicts with used space in dir inode %llu\n",
2081
* check if the name is legal. if so, then
2082
* check that the name and hashvalues match.
2084
* if the name is illegal, we don't check the
2085
* hashvalue computed from it. we just make
2086
* sure that the hashvalue in the entry is
2087
* monotonically increasing wrt to the previous
2090
* Note that we do NOT have to check the length
2091
* because the length is stored in a one-byte
2092
* unsigned int which max's out at MAXNAMELEN
2093
* making it impossible for the stored length
2094
* value to be out of range.
2096
bcopy(namest->name, fname, entry->namelen);
2097
fname[entry->namelen] = '\0';
2098
hashval = libxfs_da_hashname(fname, entry->namelen);
2101
* only complain about illegal names in phase 3 (when
2102
* inode discovery is turned on). Otherwise, we'd complain
2103
* a lot during phase 4. If the name is illegal, leave
2104
* the hash value in that entry alone.
2106
nm_illegal = namecheck(fname, entry->namelen);
2108
if (ino_discovery && nm_illegal) {
2110
* junk the entry, illegal name
2114
"illegal name \"%s\" in directory inode %llu, entry will be cleared\n",
2116
namest->name[0] = '/';
2120
"illegal name \"%s\" in directory inode %llu, entry would be cleared\n",
2123
} else if (!nm_illegal && INT_GET(entry->hashval, ARCH_CONVERT) != hashval) {
2125
* try resetting the hashvalue to the correct
2126
* value for the string, if the string has been
2127
* corrupted, too, that will get picked up next
2129
do_warn("\tmismatched hash value for entry \"%s\"\n",
2133
"\t\tin directory inode %llu. resetting hash value.\n",
2135
INT_SET(entry->hashval, ARCH_CONVERT, hashval);
2139
"\t\tin directory inode %llu. would reset hash value.\n",
2145
* now we can mark entries with NULLFSINO's bad
2147
if (!no_modify && lino == NULLFSINO) {
2148
namest->name[0] = '/';
2153
* regardless of whether the entry has or hasn't been
2154
* marked for deletion, the hash value ordering must
2157
if (INT_GET(entry->hashval, ARCH_CONVERT) < last_hashval) {
2159
* blow out the entry -- set hashval to sane value
2160
* and set the first character in the string to
2161
* the illegal value '/'. Reset the hash value
2162
* to the last hashvalue so that verify_da_path
2163
* will fix up the interior pointers correctly.
2164
* the entry will be deleted later (by routines
2165
* that need only the entry #). We keep the
2166
* inode number in the entry so we can attach
2167
* the inode to the orphanage later.
2169
do_warn("\tbad hash ordering for entry \"%s\"\n",
2173
"\t\tin directory inode %llu. will clear entry\n",
2175
INT_SET(entry->hashval, ARCH_CONVERT, last_hashval);
2176
namest->name[0] = '/';
2180
"\t\tin directory inode %llu. would clear entry\n",
2185
*next_hashval = last_hashval = INT_GET(entry->hashval, ARCH_CONVERT);
2188
* if heap data conflicts with something,
2189
* blow it out and skip the rest of the loop
2191
if (set_da_freemap(mp, dir_freemap, INT_GET(entry->nameidx, ARCH_CONVERT),
2192
INT_GET(entry->nameidx, ARCH_CONVERT) + sizeof(xfs_dir_leaf_name_t) +
2193
entry->namelen - 1)) {
2195
"name \"%s\" (block %u, slot %d) conflicts with used space in dir inode %llu\n",
2196
fname, da_bno, i, ino);
2202
"will clear entry \"%s\" (#%d) in directory inode %llu\n",
2206
"would clear entry \"%s\" (#%d)in directory inode %llu\n",
2213
* keep track of heap stats (first byte used, total bytes used)
2215
if (INT_GET(entry->nameidx, ARCH_CONVERT) < first_used)
2216
first_used = INT_GET(entry->nameidx, ARCH_CONVERT);
2217
bytes_used += entry->namelen;
2220
* special . or .. entry processing
2222
if (entry->namelen == 2 && namest->name[0] == '.' &&
2223
namest->name[1] == '.') {
2231
fprintf(stderr, "process_leaf_dir_block found .. entry (parent) = %llu\n", lino);
2234
* what if .. == .? legal only in
2235
* the root inode. blow out entry
2236
* and set parent to NULLFSINO otherwise.
2239
ino != mp->m_sb.sb_rootino) {
2240
*parent = NULLFSINO;
2242
"bad .. entry in dir ino %llu, points to self",
2245
do_warn("will clear entry\n");
2247
namest->name[0] = '/';
2250
do_warn("would clear entry\n");
2252
} else if (ino != lino &&
2253
ino == mp->m_sb.sb_rootino) {
2255
* we have to make sure that . == ..
2260
"correcting .. entry in root inode %llu, was %llu\n",
2262
XFS_DIR_SF_PUT_DIRINO_ARCH(
2264
&namest->inumber, ARCH_CONVERT);
2268
"bad .. entry (%llu) in root inode %llu should be %llu\n",
2275
* can't fix the directory unless we know
2276
* which .. entry is the right one. Both
2277
* have valid inode numbers, match the hash
2278
* value and the hash values are ordered
2279
* properly or we wouldn't be here. So
2280
* since both seem equally valid, trash
2285
"multiple .. entries in directory inode %llu, will clear second entry\n",
2287
namest->name[0] = '/';
2291
"multiple .. entries in directory inode %llu, would clear second entry\n",
2295
} else if (entry->namelen == 1 && namest->name[0] == '.') {
2304
". in directory inode %llu has wrong value (%llu), fixing entry...\n",
2306
XFS_DIR_SF_PUT_DIRINO_ARCH(&ino,
2307
&namest->inumber, ARCH_CONVERT);
2311
". in directory inode %llu has wrong value (%llu)\n",
2317
"multiple . entries in directory inode %llu\n",
2320
* mark entry as to be junked.
2324
"will clear one . entry in directory inode %llu\n",
2326
namest->name[0] = '/';
2330
"would clear one . entry in directory inode %llu\n",
2336
* all the rest -- make sure only . references self
2340
"entry \"%s\" in directory inode %llu points to self, ",
2343
do_warn("will clear entry\n");
2344
namest->name[0] = '/';
2347
do_warn("would clear entry\n");
2354
* compare top of heap values and reset as required. if the
2355
* holes flag is set, don't reset first_used unless it's
2356
* pointing to used bytes. we're being conservative here
2357
* since the block will get compacted anyhow by the kernel.
2359
if ((leaf->hdr.holes == 0 && first_used != INT_GET(leaf->hdr.firstused, ARCH_CONVERT)) ||
2360
INT_GET(leaf->hdr.firstused, ARCH_CONVERT) > first_used) {
2364
"- resetting first used heap value from %d to %d in block %u of dir ino %llu\n",
2365
(int) INT_GET(leaf->hdr.firstused, ARCH_CONVERT), first_used,
2367
INT_SET(leaf->hdr.firstused, ARCH_CONVERT, first_used);
2372
"- would reset first used value from %d to %d in block %u of dir ino %llu\n",
2373
(int) INT_GET(leaf->hdr.firstused, ARCH_CONVERT), first_used,
2378
if (bytes_used != INT_GET(leaf->hdr.namebytes, ARCH_CONVERT)) {
2382
"- resetting namebytes cnt from %d to %d in block %u of dir inode %llu\n",
2383
(int) INT_GET(leaf->hdr.namebytes, ARCH_CONVERT), bytes_used,
2385
INT_SET(leaf->hdr.namebytes, ARCH_CONVERT, bytes_used);
2390
"- would reset namebytes cnt from %d to %d in block %u of dir inode %llu\n",
2391
(int) INT_GET(leaf->hdr.namebytes, ARCH_CONVERT), bytes_used,
2397
* If the hole flag is not set, then we know that there can
2398
* be no lost holes. If the hole flag is set, then it's ok
2399
* if the on-disk holemap doesn't describe everything as long
2400
* as what it does describe doesn't conflict with reality.
2405
bholemap.lost_holes = leaf->hdr.holes;
2406
for (i = 0; i < XFS_DIR_LEAF_MAPSIZE; i++) {
2407
bholemap.hentries[i].base = INT_GET(leaf->hdr.freemap[i].base, ARCH_CONVERT);
2408
bholemap.hentries[i].size = INT_GET(leaf->hdr.freemap[i].size, ARCH_CONVERT);
2412
* Ok, now set up our own freespace list
2413
* (XFS_DIR_LEAF_MAPSIZE (3) * biggest regions)
2414
* and see if they match what's in the block
2416
bzero(&holemap, sizeof(da_hole_map_t));
2417
process_da_freemap(mp, dir_freemap, &holemap);
2419
if (zero_len_entries) {
2421
} else if (leaf->hdr.holes == 0) {
2422
if (holemap.lost_holes > 0) {
2425
"- found unexpected lost holes in block %u, dir inode %llu\n",
2429
} else if (compare_da_freemaps(mp, &holemap, &bholemap,
2430
XFS_DIR_LEAF_MAPSIZE, ino, da_bno)) {
2433
"- hole info non-optimal in block %u, dir inode %llu\n",
2437
} else if (verify_da_freemap(mp, dir_freemap, &holemap, ino, da_bno)) {
2440
"- hole info incorrect in block %u, dir inode %llu\n",
2447
* have to reset block hole info
2451
"- existing hole info for block %d, dir inode %llu (base, size) - \n",
2454
for (i = 0; i < XFS_DIR_LEAF_MAPSIZE; i++) {
2456
"- (%d, %d) ", bholemap.hentries[i].base,
2457
bholemap.hentries[i].size);
2459
do_warn("- holes flag = %d\n", bholemap.lost_holes);
2465
"- compacting block %u in dir inode %llu\n",
2468
new_leaf = (xfs_dir_leafblock_t *) &dirbuf[0];
2471
* copy leaf block header
2473
bcopy(&leaf->hdr, &new_leaf->hdr,
2474
sizeof(xfs_dir_leaf_hdr_t));
2477
* reset count in case we have some zero length entries
2478
* that are being junked
2481
first_used = XFS_LBSIZE(mp);
2482
first_byte = (char *) new_leaf
2483
+ (__psint_t) XFS_LBSIZE(mp);
2486
* copy entry table and pack names starting from the end
2489
for (i = 0, s_entry = &leaf->entries[0],
2490
d_entry = &new_leaf->entries[0];
2491
i < INT_GET(leaf->hdr.count, ARCH_CONVERT);
2494
* skip zero-length entries
2496
if (s_entry->namelen == 0)
2499
bytes = sizeof(xfs_dir_leaf_name_t)
2500
+ s_entry->namelen - 1;
2502
if ((__psint_t) first_byte - bytes <
2503
sizeof(xfs_dir_leaf_entry_t)
2504
+ (__psint_t) d_entry) {
2506
"not enough space in block %u of dir inode %llu for all entries\n",
2511
first_used -= bytes;
2512
first_byte -= bytes;
2514
INT_SET(d_entry->nameidx, ARCH_CONVERT, first_used);
2515
INT_SET(d_entry->hashval, ARCH_CONVERT, INT_GET(s_entry->hashval, ARCH_CONVERT));
2516
d_entry->namelen = s_entry->namelen;
2519
bcopy((char *) leaf + INT_GET(s_entry->nameidx, ARCH_CONVERT),
2526
ASSERT((char *) first_byte >= (char *) d_entry);
2527
ASSERT(first_used <= XFS_LBSIZE(mp));
2530
* zero space between end of table and top of heap
2532
bzero(d_entry, (__psint_t) first_byte
2533
- (__psint_t) d_entry);
2538
if (num_entries != INT_GET(new_leaf->hdr.count, ARCH_CONVERT))
2539
INT_SET(new_leaf->hdr.count, ARCH_CONVERT, num_entries);
2541
INT_SET(new_leaf->hdr.firstused, ARCH_CONVERT, first_used);
2542
new_leaf->hdr.holes = 0;
2543
new_leaf->hdr.pad1 = 0;
2545
INT_SET(new_leaf->hdr.freemap[0].base, ARCH_CONVERT, (__psint_t) d_entry
2546
- (__psint_t) new_leaf);
2547
INT_SET(new_leaf->hdr.freemap[0].size, ARCH_CONVERT, (__psint_t) first_byte
2548
- (__psint_t) d_entry);
2550
ASSERT(INT_GET(new_leaf->hdr.freemap[0].base, ARCH_CONVERT) < first_used);
2551
ASSERT(INT_GET(new_leaf->hdr.freemap[0].base, ARCH_CONVERT) ==
2552
(__psint_t) (&new_leaf->entries[0])
2553
- (__psint_t) new_leaf
2554
+ i * sizeof(xfs_dir_leaf_entry_t));
2555
ASSERT(INT_GET(new_leaf->hdr.freemap[0].base, ARCH_CONVERT) < XFS_LBSIZE(mp));
2556
ASSERT(INT_GET(new_leaf->hdr.freemap[0].size, ARCH_CONVERT) < XFS_LBSIZE(mp));
2557
ASSERT(INT_GET(new_leaf->hdr.freemap[0].base, ARCH_CONVERT) +
2558
INT_GET(new_leaf->hdr.freemap[0].size, ARCH_CONVERT) == first_used);
2560
INT_ZERO(new_leaf->hdr.freemap[1].base, ARCH_CONVERT);
2561
INT_ZERO(new_leaf->hdr.freemap[1].size, ARCH_CONVERT);
2562
INT_ZERO(new_leaf->hdr.freemap[2].base, ARCH_CONVERT);
2563
INT_ZERO(new_leaf->hdr.freemap[2].size, ARCH_CONVERT);
2566
* final step, copy block back
2568
bcopy(new_leaf, leaf, mp->m_sb.sb_blocksize);
2574
"- would compact block %u in dir inode %llu\n",
2581
* now take care of deleting or marking the entries with
2582
* zero-length namelen's
2584
junk_zerolen_dir_leaf_entries(mp, leaf, ino, buf_dirty);
2588
fprintf(stderr, "process_leaf_dir_block returns %d\n", res);
2590
return((res > 0) ? 1 : 0);
2594
* returns 0 if the directory is ok, 1 if it has to be junked.
2597
process_leaf_dir_level(xfs_mount_t *mp,
2598
da_bt_cursor_t *da_cursor,
2605
xfs_dir_leafblock_t *leaf;
2608
xfs_dfsbno_t dev_bno;
2610
xfs_dablk_t prev_bno;
2613
xfs_daddr_t bd_addr;
2614
xfs_dahash_t current_hashval = 0;
2615
xfs_dahash_t greatest_hashval;
2618
fprintf(stderr, "process_leaf_dir_level - ino %llu\n", da_cursor->ino);
2621
da_bno = da_cursor->level[0].bno;
2622
ino = da_cursor->ino;
2626
dev_bno = blkmap_get(da_cursor->blkmap, da_bno);
2628
* directory code uses 0 as the NULL block pointer
2629
* since 0 is the root block and no directory block
2630
* pointer can point to the root block of the btree
2632
ASSERT(da_bno != 0);
2634
if (dev_bno == NULLDFSBNO) {
2635
do_warn("can't map block %u for directory inode %llu\n",
2640
bd_addr = (xfs_daddr_t)XFS_FSB_TO_DADDR(mp, dev_bno);
2642
bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, dev_bno),
2643
XFS_FSB_TO_BB(mp, 1), 0);
2645
do_warn("can't read file block %u (fsbno %llu, daddr %lld) "
2646
"for directory inode %llu\n",
2647
da_bno, dev_bno, (__int64_t) bd_addr, ino);
2651
leaf = (xfs_dir_leafblock_t *)XFS_BUF_PTR(bp);
2654
* check magic number for leaf directory btree block
2656
if (INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) != XFS_DIR_LEAF_MAGIC) {
2657
do_warn("bad directory leaf magic # %#x for dir ino %llu\n",
2658
INT_GET(leaf->hdr.info.magic, ARCH_CONVERT), ino);
2663
* keep track of greatest block # -- that gets
2664
* us the length of the directory
2666
if (da_bno > da_cursor->greatest_bno)
2667
da_cursor->greatest_bno = da_bno;
2671
* for each block, process the block, verify it's path,
2672
* then get next block. update cursor values along the way
2674
if (process_leaf_dir_block(mp, leaf, da_bno, ino,
2675
current_hashval, ino_discovery,
2676
da_cursor->blkmap, dot, dotdot, parent,
2677
&buf_dirty, &greatest_hashval)) {
2683
* index can be set to hdr.count so match the
2684
* indexes of the interior blocks -- which at the
2685
* end of the block will point to 1 after the final
2686
* real entry in the block
2688
da_cursor->level[0].hashval = greatest_hashval;
2689
da_cursor->level[0].bp = bp;
2690
da_cursor->level[0].bno = da_bno;
2691
da_cursor->level[0].index = INT_GET(leaf->hdr.count, ARCH_CONVERT);
2692
da_cursor->level[0].dirty = buf_dirty;
2694
if (INT_GET(leaf->hdr.info.back, ARCH_CONVERT) != prev_bno) {
2695
do_warn("bad sibling back pointer for directory block %u "
2696
"in directory inode %llu\n", da_bno, ino);
2702
da_bno = INT_GET(leaf->hdr.info.forw, ARCH_CONVERT);
2705
if (verify_da_path(mp, da_cursor, 0)) {
2710
current_hashval = greatest_hashval;
2712
ASSERT(buf_dirty == 0 || (buf_dirty && !no_modify));
2714
if (buf_dirty && !no_modify) {
2716
libxfs_writebuf(bp, 0);
2720
} while (da_bno != 0 && res == 0);
2722
if (verify_final_da_path(mp, da_cursor, 0)) {
2724
* verify the final path up (right-hand-side) if still ok
2726
do_warn("bad hash path in directory %llu\n", da_cursor->ino);
2731
fprintf(stderr, "process_leaf_dir_level returns %d (%s)\n",
2732
res, ((res) ? "bad" : "ok"));
2735
* redundant but just for testing
2737
release_da_cursor(mp, da_cursor, 0);
2743
* release all buffers holding interior btree blocks
2745
err_release_da_cursor(mp, da_cursor, 0);
2751
* a node directory is a true btree directory -- where the directory
2752
* has gotten big enough that it is represented as a non-trivial (e.g.
2753
* has more than just a root block) btree.
2755
* Note that if we run into any problems, we trash the
2756
* directory. Even if it's the root directory,
2757
* we'll be able to traverse all the disconnected
2758
* subtrees later (phase 6).
2760
* one day, if we actually fix things, we'll set repair to 1 to
2761
* indicate that we have or that we should.
2763
* dirname can be set to NULL if the name is unknown (or to
2764
* the string representation of the inode)
2766
* returns 0 if things are ok, 1 if bad (directory needs to be junked)
2778
xfs_ino_t *parent, /* out - parent ino # or NULLFSINO */
2784
da_bt_cursor_t da_cursor;
2787
fprintf(stderr, "process_node_dir - ino %llu\n", ino);
2789
*repair = *dot = *dotdot = 0;
2790
*parent = NULLFSINO;
2793
* try again -- traverse down left-side of tree until we hit
2794
* the left-most leaf block setting up the btree cursor along
2795
* the way. Then walk the leaf blocks left-to-right, calling
2796
* a parent-verification routine each time we traverse a block.
2798
bzero(&da_cursor, sizeof(da_bt_cursor_t));
2800
da_cursor.active = 0;
2802
da_cursor.ino = ino;
2803
da_cursor.dip = dip;
2804
da_cursor.greatest_bno = 0;
2805
da_cursor.blkmap = blkmap;
2808
* now process interior node
2811
error = traverse_int_dablock(mp, &da_cursor, &bno, XFS_DATA_FORK);
2817
* now pass cursor and bno into leaf-block processing routine
2818
* the leaf dir level routine checks the interior paths
2819
* up to the root including the final right-most path.
2822
error = process_leaf_dir_level(mp, &da_cursor, ino_discovery,
2823
repair, dot, dotdot, parent);
2829
* sanity check inode size
2831
if (INT_GET(dip->di_core.di_size, ARCH_CONVERT) <
2832
(da_cursor.greatest_bno + 1) * mp->m_sb.sb_blocksize) {
2833
if ((xfs_fsize_t) (da_cursor.greatest_bno
2834
* mp->m_sb.sb_blocksize) > UINT_MAX) {
2836
"out of range internal directory block numbers (inode %llu)\n",
2842
"setting directory inode (%llu) size to %llu bytes, was %lld bytes\n",
2844
(xfs_dfiloff_t) (da_cursor.greatest_bno + 1)
2845
* mp->m_sb.sb_blocksize,
2846
INT_GET(dip->di_core.di_size, ARCH_CONVERT));
2848
INT_SET(dip->di_core.di_size, ARCH_CONVERT, (xfs_fsize_t)
2849
(da_cursor.greatest_bno + 1) * mp->m_sb.sb_blocksize);
2855
* a leaf directory is one where the directory is too big for
2856
* the inode data fork but is small enough to fit into one
2857
* directory btree block (filesystem block) outside the inode
2859
* returns NULLFSINO if the directory is cannot be salvaged
2860
* and the .. ino if things are ok (even if the directory had
2861
* to be altered to make it ok).
2863
* dirname can be set to NULL if the name is unknown (or to
2864
* the string representation of the inode)
2866
* returns 0 if things are ok, 1 if bad (directory needs to be junked)
2877
int *dot, /* out - 1 if there is a dot, else 0 */
2878
int *dotdot, /* out - 1 if there's a dotdot, else 0 */
2879
xfs_ino_t *parent, /* out - parent ino # or NULLFSINO */
2880
char *dirname, /* in - directory pathname */
2881
int *repair) /* out - 1 if something was fixed */
2883
xfs_dir_leafblock_t *leaf;
2884
xfs_dahash_t next_hashval;
2890
fprintf(stderr, "process_leaf_dir - ino %llu\n", ino);
2892
*repair = *dot = *dotdot = 0;
2893
*parent = NULLFSINO;
2895
bno = blkmap_get(blkmap, 0);
2896
if (bno == NULLDFSBNO) {
2897
do_warn("block 0 for directory inode %llu is missing\n", ino);
2900
bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, bno),
2901
XFS_FSB_TO_BB(mp, 1), 0);
2903
do_warn("can't read block 0 for directory inode %llu\n", ino);
2909
leaf = (xfs_dir_leafblock_t *)XFS_BUF_PTR(bp);
2912
* check magic number for leaf directory btree block
2914
if (INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) != XFS_DIR_LEAF_MAGIC) {
2915
do_warn("bad directory leaf magic # %#x for dir ino %llu\n",
2916
INT_GET(leaf->hdr.info.magic, ARCH_CONVERT), ino);
2921
if (process_leaf_dir_block(mp, leaf, 0, ino, 0, ino_discovery, blkmap,
2922
dot, dotdot, parent, &buf_dirty, &next_hashval)) {
2924
* the block is bad. lose the directory.
2925
* XXX - later, we should try and just lose
2926
* the block without losing the entire directory
2928
ASSERT(*dotdot == 0 || (*dotdot == 1 && *parent != NULLFSINO));
2934
* check sibling pointers in leaf block (above doesn't do it)
2936
if (INT_GET(leaf->hdr.info.forw, ARCH_CONVERT) != 0 ||
2937
INT_GET(leaf->hdr.info.back, ARCH_CONVERT) != 0) {
2939
do_warn("clearing forw/back pointers for directory inode "
2942
INT_ZERO(leaf->hdr.info.forw, ARCH_CONVERT);
2943
INT_ZERO(leaf->hdr.info.back, ARCH_CONVERT);
2945
do_warn("would clear forw/back pointers for directory inode "
2950
ASSERT(buf_dirty == 0 || (buf_dirty && !no_modify));
2952
if (buf_dirty && !no_modify)
2953
libxfs_writebuf(bp, 0);
2961
* returns 1 if things are bad (directory needs to be junked)
2962
* and 0 if things are ok. If ino_discovery is 1, add unknown
2963
* inodes to uncertain inode list.
2981
*parent = NULLFSINO;
2985
* branch off depending on the type of inode. This routine
2986
* is only called ONCE so all the subordinate routines will
2987
* fix '.' and junk '..' if they're bogus.
2989
if (INT_GET(dip->di_core.di_size, ARCH_CONVERT) <= XFS_DFORK_DSIZE_ARCH(dip, mp, ARCH_CONVERT)) {
2992
if (process_shortform_dir(mp, ino, dip, ino_discovery,
2993
dino_dirty, parent, dirname, &repair)) {
2996
} else if (INT_GET(dip->di_core.di_size, ARCH_CONVERT) <= XFS_LBSIZE(mp)) {
2997
if (process_leaf_dir(mp, ino, dip, ino_discovery,
2998
dino_dirty, blkmap, &dot, &dotdot,
2999
parent, dirname, &repair)) {
3003
if (process_node_dir(mp, ino, dip, ino_discovery,
3004
blkmap, &dot, &dotdot,
3005
parent, dirname, &repair)) {
3010
* bad . entries in all directories will be fixed up in phase 6
3013
do_warn("no . entry for directory %llu\n", ino);
3017
* shortform dirs always have a .. entry. .. for all longform
3018
* directories will get fixed in phase 6. .. for other shortform
3019
* dirs also get fixed there. .. for a shortform root was
3020
* fixed in place since we know what it should be
3022
if (dotdot == 0 && ino != mp->m_sb.sb_rootino) {
3023
do_warn("no .. entry for directory %llu\n", ino);
3024
} else if (dotdot == 0 && ino == mp->m_sb.sb_rootino) {
3025
do_warn("no .. entry for root directory %llu\n", ino);
3026
need_root_dotdot = 1;
3030
fprintf(stderr, "(process_dir), parent of %llu is %llu\n", ino, parent);