]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - repair/dir2.c
3d7abdd31a19a4759577961234356d9c4b2368c9
[thirdparty/xfsprogs-dev.git] / repair / dir2.c
1 /*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
3 *
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.
7 *
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.
11 *
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.
18 *
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.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */
32
33 #include <libxfs.h>
34 #include "avl.h"
35 #include "globals.h"
36 #include "incore.h"
37 #include "err_protos.h"
38 #include "dinode.h"
39 #include "dir.h"
40 #include "dir2.h"
41 #include "bmap.h"
42
43 /*
44 * Tag bad directory entries with this.
45 * We can't tag them with -1 since that will look like a
46 * data_unused_t instead of a data_entry_t.
47 */
48 #define BADFSINO ((xfs_ino_t)0xfeffffffffffffffULL)
49
50 /*
51 * Known bad inode list. These are seen when the leaf and node
52 * block linkages are incorrect.
53 */
54 typedef struct dir2_bad {
55 xfs_ino_t ino;
56 struct dir2_bad *next;
57 } dir2_bad_t;
58 dir2_bad_t *dir2_bad_list;
59
60 void
61 dir2_add_badlist(
62 xfs_ino_t ino)
63 {
64 dir2_bad_t *l;
65
66 if ((l = malloc(sizeof(dir2_bad_t))) == NULL) {
67 do_error("malloc failed (%u bytes) dir2_add_badlist:ino %llu\n",
68 sizeof(dir2_bad_t), ino);
69 exit(1);
70 }
71 l->next = dir2_bad_list;
72 dir2_bad_list = l;
73 l->ino = ino;
74 }
75
76 int
77 dir2_is_badino(
78 xfs_ino_t ino)
79 {
80 dir2_bad_t *l;
81
82 for (l = dir2_bad_list; l; l = l->next)
83 if (l->ino == ino)
84 return 1;
85 return 0;
86 }
87
88 /*
89 * Multibuffer handling.
90 * V2 directory blocks can be noncontiguous, needing multiple buffers.
91 */
92 xfs_dabuf_t *
93 da_read_buf(
94 xfs_mount_t *mp,
95 int nex,
96 bmap_ext_t *bmp)
97 {
98 xfs_buf_t *bp;
99 xfs_buf_t **bplist;
100 xfs_dabuf_t *dabuf;
101 int i;
102 int off;
103
104 bplist = calloc(nex, sizeof(*bplist));
105 if (bplist == NULL) {
106 do_error("couldn't malloc dir2 buffer list\n");
107 exit(1);
108 }
109 for (i = 0; i < nex; i++) {
110 bplist[i] = libxfs_readbuf(mp->m_dev,
111 XFS_FSB_TO_DADDR(mp, bmp[i].startblock),
112 XFS_FSB_TO_BB(mp, bmp[i].blockcount), 0);
113 if (!bplist[i])
114 goto failed;
115 }
116 dabuf = malloc(XFS_DA_BUF_SIZE(nex));
117 if (dabuf == NULL) {
118 do_error("couldn't malloc dir2 buffer header\n");
119 exit(1);
120 }
121 dabuf->dirty = 0;
122 dabuf->nbuf = nex;
123 if (nex == 1) {
124 bp = bplist[0];
125 dabuf->bbcount = (short)BTOBB(XFS_BUF_COUNT(bp));
126 dabuf->data = XFS_BUF_PTR(bp);
127 dabuf->bps[0] = bp;
128 } else {
129 for (i = 0, dabuf->bbcount = 0; i < nex; i++) {
130 dabuf->bps[i] = bp = bplist[i];
131 dabuf->bbcount += BTOBB(XFS_BUF_COUNT(bp));
132 }
133 dabuf->data = malloc(BBTOB(dabuf->bbcount));
134 if (dabuf->data == NULL) {
135 do_error("couldn't malloc dir2 buffer data\n");
136 exit(1);
137 }
138 for (i = off = 0; i < nex; i++, off += XFS_BUF_COUNT(bp)) {
139 bp = bplist[i];
140 bcopy(XFS_BUF_PTR(bp), (char *)dabuf->data + off,
141 XFS_BUF_COUNT(bp));
142 }
143 }
144 return dabuf;
145 failed:
146 for (i = 0; i < nex; i++)
147 libxfs_putbuf(bplist[i]);
148 free(bplist);
149 return NULL;
150 }
151
152 static void
153 da_buf_clean(
154 xfs_dabuf_t *dabuf)
155 {
156 xfs_buf_t *bp;
157 int i;
158 int off;
159
160 if (dabuf->dirty) {
161 dabuf->dirty = 0;
162 for (i=off=0; i < dabuf->nbuf; i++, off += XFS_BUF_COUNT(bp)) {
163 bp = dabuf->bps[i];
164 bcopy((char *)dabuf->data + off, XFS_BUF_PTR(bp),
165 XFS_BUF_COUNT(bp));
166 }
167 }
168 }
169
170 static void
171 da_buf_done(
172 xfs_dabuf_t *dabuf)
173 {
174 da_buf_clean(dabuf);
175 if (dabuf->nbuf > 1)
176 free(dabuf->data);
177 free(dabuf);
178 }
179
180 int
181 da_bwrite(
182 xfs_mount_t *mp,
183 xfs_dabuf_t *dabuf)
184 {
185 xfs_buf_t *bp;
186 xfs_buf_t **bplist;
187 int e;
188 int error;
189 int i;
190 int nbuf;
191 int off;
192
193 if ((nbuf = dabuf->nbuf) == 1) {
194 bplist = &bp;
195 bp = dabuf->bps[0];
196 } else {
197 bplist = malloc(nbuf * sizeof(*bplist));
198 if (bplist == NULL) {
199 do_error("couldn't malloc dir2 buffer list\n");
200 exit(1);
201 }
202 bcopy(dabuf->bps, bplist, nbuf * sizeof(*bplist));
203 for (i = off = 0; i < nbuf; i++, off += XFS_BUF_COUNT(bp)) {
204 bp = bplist[i];
205 bcopy((char *)dabuf->data + off, XFS_BUF_PTR(bp),
206 XFS_BUF_COUNT(bp));
207 }
208 }
209 da_buf_done(dabuf);
210 for (i = error = 0; i < nbuf; i++) {
211 e = libxfs_writebuf(bplist[i], 0);
212 if (e)
213 error = e;
214 }
215 if (bplist != &bp)
216 free(bplist);
217 return error;
218 }
219
220 void
221 da_brelse(
222 xfs_dabuf_t *dabuf)
223 {
224 xfs_buf_t *bp;
225 xfs_buf_t **bplist;
226 int i;
227 int nbuf;
228
229 if ((nbuf = dabuf->nbuf) == 1) {
230 bplist = &bp;
231 bp = dabuf->bps[0];
232 } else {
233 bplist = malloc(nbuf * sizeof(*bplist));
234 if (bplist == NULL) {
235 do_error("couldn't malloc dir2 buffer list\n");
236 exit(1);
237 }
238 bcopy(dabuf->bps, bplist, nbuf * sizeof(*bplist));
239 }
240 da_buf_done(dabuf);
241 for (i = 0; i < nbuf; i++)
242 libxfs_putbuf(bplist[i]);
243 if (bplist != &bp)
244 free(bplist);
245 }
246
247 /*
248 * walk tree from root to the left-most leaf block reading in
249 * blocks and setting up cursor. passes back file block number of the
250 * left-most leaf block if successful (bno). returns 1 if successful,
251 * 0 if unsuccessful.
252 */
253 int
254 traverse_int_dir2block(xfs_mount_t *mp,
255 dir2_bt_cursor_t *da_cursor,
256 xfs_dablk_t *rbno)
257 {
258 bmap_ext_t *bmp;
259 xfs_dablk_t bno;
260 xfs_dabuf_t *bp;
261 int i;
262 int nex;
263 xfs_da_intnode_t *node;
264
265 /*
266 * traverse down left-side of tree until we hit the
267 * left-most leaf block setting up the btree cursor along
268 * the way.
269 */
270 bno = mp->m_dirleafblk;
271 i = -1;
272 node = NULL;
273 da_cursor->active = 0;
274
275 do {
276 /*
277 * read in each block along the way and set up cursor
278 */
279 nex = blkmap_getn(da_cursor->blkmap, bno, mp->m_dirblkfsbs,
280 &bmp);
281
282 if (nex == 0)
283 goto error_out;
284
285 bp = da_read_buf(mp, nex, bmp);
286 free(bmp);
287 if (bp == NULL) {
288 do_warn("can't read block %u for directory inode "
289 "%llu\n",
290 bno, da_cursor->ino);
291 goto error_out;
292 }
293
294 node = bp->data;
295
296 if (INT_GET(node->hdr.info.magic, ARCH_CONVERT) ==
297 XFS_DIR2_LEAFN_MAGIC) {
298 if ( i != -1 ) {
299 do_warn("found non-root LEAFN node in inode "
300 "%llu bno = %u\n",
301 da_cursor->ino, bno);
302 }
303 if (INT_GET(node->hdr.level, ARCH_CONVERT) >= 1) {
304 do_warn("LEAFN node level is %d inode %llu "
305 "bno = %u\n",
306 INT_GET(node->hdr.level, ARCH_CONVERT),
307 da_cursor->ino, bno);
308 }
309 *rbno = 0;
310 da_brelse(bp);
311 return(1);
312 } else if (INT_GET(node->hdr.info.magic, ARCH_CONVERT) !=
313 XFS_DA_NODE_MAGIC) {
314 da_brelse(bp);
315 do_warn("bad dir magic number 0x%x in inode %llu "
316 "bno = %u\n",
317 INT_GET(node->hdr.info.magic, ARCH_CONVERT),
318 da_cursor->ino, bno);
319 goto error_out;
320 }
321 if (INT_GET(node->hdr.count, ARCH_CONVERT) >
322 XFS_DA_NODE_ENTRIES(mp)) {
323 da_brelse(bp);
324 do_warn("bad record count in inode %llu, count = %d, "
325 "max = %d\n", da_cursor->ino,
326 INT_GET(node->hdr.count, ARCH_CONVERT),
327 XFS_DA_NODE_ENTRIES(mp));
328 goto error_out;
329 }
330
331 /*
332 * maintain level counter
333 */
334 if (i == -1)
335 i = da_cursor->active =
336 INT_GET(node->hdr.level, ARCH_CONVERT);
337 else {
338 if (INT_GET(node->hdr.level, ARCH_CONVERT) == i - 1) {
339 i--;
340 } else {
341 do_warn("bad directory btree for directory "
342 "inode %llu\n",
343 da_cursor->ino);
344 da_brelse(bp);
345 goto error_out;
346 }
347 }
348
349 da_cursor->level[i].hashval =
350 INT_GET(node->btree[0].hashval, ARCH_CONVERT);
351 da_cursor->level[i].bp = bp;
352 da_cursor->level[i].bno = bno;
353 da_cursor->level[i].index = 0;
354
355 /*
356 * set up new bno for next level down
357 */
358 bno = INT_GET(node->btree[0].before, ARCH_CONVERT);
359 } while (node != NULL && i > 1);
360
361 /*
362 * now return block number and get out
363 */
364 *rbno = da_cursor->level[0].bno = bno;
365 return(1);
366
367 error_out:
368 while (i > 1 && i <= da_cursor->active) {
369 da_brelse(da_cursor->level[i].bp);
370 i++;
371 }
372
373 return(0);
374 }
375
376 /*
377 * blow out buffer for this level and all the rest above as well
378 * if error == 0, we are not expecting to encounter any unreleased
379 * buffers (e.g. if we do, it's a mistake). if error == 1, we're
380 * in an error-handling case so unreleased buffers may exist.
381 */
382 void
383 release_dir2_cursor_int(xfs_mount_t *mp,
384 dir2_bt_cursor_t *cursor,
385 int prev_level,
386 int error)
387 {
388 int level = prev_level + 1;
389
390 if (cursor->level[level].bp != NULL) {
391 if (!error) {
392 do_warn("release_dir2_cursor_int got unexpected "
393 "non-null bp, dabno = %u\n",
394 cursor->level[level].bno);
395 }
396 ASSERT(error != 0);
397
398 da_brelse(cursor->level[level].bp);
399 cursor->level[level].bp = NULL;
400 }
401
402 if (level < cursor->active)
403 release_dir2_cursor_int(mp, cursor, level, error);
404
405 return;
406 }
407
408 void
409 release_dir2_cursor(xfs_mount_t *mp,
410 dir2_bt_cursor_t *cursor,
411 int prev_level)
412 {
413 release_dir2_cursor_int(mp, cursor, prev_level, 0);
414 }
415
416 void
417 err_release_dir2_cursor(xfs_mount_t *mp,
418 dir2_bt_cursor_t *cursor,
419 int prev_level)
420 {
421 release_dir2_cursor_int(mp, cursor, prev_level, 1);
422 }
423
424 /*
425 * make sure that all entries in all blocks along the right side of
426 * of the tree are used and hashval's are consistent. level is the
427 * level of the descendent block. returns 0 if good (even if it had
428 * to be fixed up), and 1 if bad. The right edge of the tree is
429 * technically a block boundary. This routine should be used then
430 * instead of verify_dir2_path().
431 */
432 int
433 verify_final_dir2_path(xfs_mount_t *mp,
434 dir2_bt_cursor_t *cursor,
435 const int p_level)
436 {
437 xfs_da_intnode_t *node;
438 int bad = 0;
439 int entry;
440 int this_level = p_level + 1;
441
442 /*
443 * the index should point to the next "unprocessed" entry
444 * in the block which should be the final (rightmost) entry
445 */
446 entry = cursor->level[this_level].index;
447 node = (xfs_da_intnode_t *)(cursor->level[this_level].bp->data);
448 /*
449 * check internal block consistency on this level -- ensure
450 * that all entries are used, encountered and expected hashvals
451 * match, etc.
452 */
453 if (entry != INT_GET(node->hdr.count, ARCH_CONVERT) - 1) {
454 do_warn("directory block used/count inconsistency - %d / %hu\n",
455 entry, INT_GET(node->hdr.count, ARCH_CONVERT));
456 bad++;
457 }
458 /*
459 * hash values monotonically increasing ???
460 */
461 if (cursor->level[this_level].hashval >= INT_GET(node->btree[entry].hashval, ARCH_CONVERT)) {
462 do_warn("directory/attribute block hashvalue inconsistency, "
463 "expected > %u / saw %u\n",
464 cursor->level[this_level].hashval,
465 INT_GET(node->btree[entry].hashval, ARCH_CONVERT));
466 bad++;
467 }
468 if (INT_GET(node->hdr.info.forw, ARCH_CONVERT) != 0) {
469 do_warn("bad directory/attribute forward block pointer, "
470 "expected 0, saw %u\n",
471 INT_GET(node->hdr.info.forw, ARCH_CONVERT));
472 bad++;
473 }
474 if (bad) {
475 do_warn("bad directory block in inode %llu\n", cursor->ino);
476 return(1);
477 }
478 /*
479 * keep track of greatest block # -- that gets
480 * us the length of the directory
481 */
482 if (cursor->level[this_level].bno > cursor->greatest_bno)
483 cursor->greatest_bno = cursor->level[this_level].bno;
484
485 /*
486 * ok, now check descendant block number against this level
487 */
488 if (cursor->level[p_level].bno != INT_GET(node->btree[entry].before, ARCH_CONVERT)) {
489 return(1);
490 }
491
492 if (cursor->level[p_level].hashval != INT_GET(node->btree[entry].hashval, ARCH_CONVERT)) {
493 if (!no_modify) {
494 do_warn("correcting bad hashval in non-leaf dir "
495 "block\n");
496 do_warn("\tin (level %d) in inode %llu.\n",
497 this_level, cursor->ino);
498 INT_SET(node->btree[entry].hashval, ARCH_CONVERT, cursor->level[p_level].hashval);
499 cursor->level[this_level].dirty++;
500 } else {
501 do_warn("would correct bad hashval in non-leaf dir "
502 "block\n");
503 do_warn("\tin (level %d) in inode %llu.\n",
504 this_level, cursor->ino);
505 }
506 }
507
508 /*
509 * release/write buffer
510 */
511 ASSERT(cursor->level[this_level].dirty == 0 ||
512 (cursor->level[this_level].dirty && !no_modify));
513
514 if (cursor->level[this_level].dirty && !no_modify)
515 da_bwrite(mp, cursor->level[this_level].bp);
516 else
517 da_brelse(cursor->level[this_level].bp);
518
519 cursor->level[this_level].bp = NULL;
520
521 /*
522 * bail out if this is the root block (top of tree)
523 */
524 if (this_level >= cursor->active) {
525 return(0);
526 }
527 /*
528 * set hashvalue to correctl reflect the now-validated
529 * last entry in this block and continue upwards validation
530 */
531 cursor->level[this_level].hashval = INT_GET(node->btree[entry].hashval, ARCH_CONVERT);
532
533 return(verify_final_dir2_path(mp, cursor, this_level));
534 }
535
536 /*
537 * Verifies the path from a descendant block up to the root.
538 * Should be called when the descendant level traversal hits
539 * a block boundary before crossing the boundary (reading in a new
540 * block).
541 *
542 * the directory/attr btrees work differently to the other fs btrees.
543 * each interior block contains records that are <hashval, bno>
544 * pairs. The bno is a file bno, not a filesystem bno. The last
545 * hashvalue in the block <bno> will be <hashval>. BUT unlike
546 * the freespace btrees, the *last* value in each block gets
547 * propagated up the tree instead of the first value in each block.
548 * that is, the interior records point to child blocks and the *greatest*
549 * hash value contained by the child block is the one the block above
550 * uses as the key for the child block.
551 *
552 * level is the level of the descendent block. returns 0 if good,
553 * and 1 if bad. The descendant block may be a leaf block.
554 *
555 * the invariant here is that the values in the cursor for the
556 * levels beneath this level (this_level) and the cursor index
557 * for this level *must* be valid.
558 *
559 * that is, the hashval/bno info is accurate for all
560 * DESCENDANTS and match what the node[index] information
561 * for the current index in the cursor for this level.
562 *
563 * the index values in the cursor for the descendant level
564 * are allowed to be off by one as they will reflect the
565 * next entry at those levels to be processed.
566 *
567 * the hashvalue for the current level can't be set until
568 * we hit the last entry in the block so, it's garbage
569 * until set by this routine.
570 *
571 * bno and bp for the current block/level are always valid
572 * since they have to be set so we can get a buffer for the
573 * block.
574 */
575 int
576 verify_dir2_path(xfs_mount_t *mp,
577 dir2_bt_cursor_t *cursor,
578 const int p_level)
579 {
580 xfs_da_intnode_t *node;
581 xfs_da_intnode_t *newnode;
582 xfs_dablk_t dabno;
583 xfs_dabuf_t *bp;
584 int bad;
585 int entry;
586 int this_level = p_level + 1;
587 bmap_ext_t *bmp;
588 int nex;
589
590 /*
591 * index is currently set to point to the entry that
592 * should be processed now in this level.
593 */
594 entry = cursor->level[this_level].index;
595 node = cursor->level[this_level].bp->data;
596
597 /*
598 * if this block is out of entries, validate this
599 * block and move on to the next block.
600 * and update cursor value for said level
601 */
602 if (entry >= INT_GET(node->hdr.count, ARCH_CONVERT)) {
603 /*
604 * update the hash value for this level before
605 * validating it. bno value should be ok since
606 * it was set when the block was first read in.
607 */
608 cursor->level[this_level].hashval =
609 INT_GET(node->btree[entry - 1].hashval, ARCH_CONVERT);
610
611 /*
612 * keep track of greatest block # -- that gets
613 * us the length of the directory
614 */
615 if (cursor->level[this_level].bno > cursor->greatest_bno)
616 cursor->greatest_bno = cursor->level[this_level].bno;
617
618 /*
619 * validate the path for the current used-up block
620 * before we trash it
621 */
622 if (verify_dir2_path(mp, cursor, this_level))
623 return(1);
624 /*
625 * ok, now get the next buffer and check sibling pointers
626 */
627 dabno = INT_GET(node->hdr.info.forw, ARCH_CONVERT);
628 ASSERT(dabno != 0);
629 nex = blkmap_getn(cursor->blkmap, dabno, mp->m_dirblkfsbs,
630 &bmp);
631 if (nex == 0) {
632 do_warn("can't get map info for block %u of directory "
633 "inode %llu\n",
634 dabno, cursor->ino);
635 return(1);
636 }
637
638 bp = da_read_buf(mp, nex, bmp);
639
640 if (bp == NULL) {
641 do_warn("can't read block %u for directory inode "
642 "%llu\n",
643 dabno, cursor->ino);
644 return(1);
645 }
646
647 newnode = bp->data;
648 /*
649 * verify magic number and back pointer, sanity-check
650 * entry count, verify level
651 */
652 bad = 0;
653 if (INT_GET(newnode->hdr.info.magic, ARCH_CONVERT) != XFS_DA_NODE_MAGIC) {
654 do_warn("bad magic number %x in block %u for directory "
655 "inode %llu\n",
656 INT_GET(newnode->hdr.info.magic, ARCH_CONVERT), dabno, cursor->ino);
657 bad++;
658 }
659 if (INT_GET(newnode->hdr.info.back, ARCH_CONVERT) != cursor->level[this_level].bno) {
660 do_warn("bad back pointer in block %u for directory "
661 "inode %llu\n",
662 dabno, cursor->ino);
663 bad++;
664 }
665 if (INT_GET(newnode->hdr.count, ARCH_CONVERT) > XFS_DA_NODE_ENTRIES(mp)) {
666 do_warn("entry count %d too large in block %u for "
667 "directory inode %llu\n",
668 INT_GET(newnode->hdr.count, ARCH_CONVERT), dabno, cursor->ino);
669 bad++;
670 }
671 if (INT_GET(newnode->hdr.level, ARCH_CONVERT) != this_level) {
672 do_warn("bad level %d in block %u for directory inode "
673 "%llu\n",
674 INT_GET(newnode->hdr.level, ARCH_CONVERT), dabno, cursor->ino);
675 bad++;
676 }
677 if (bad) {
678 da_brelse(bp);
679 return(1);
680 }
681 /*
682 * update cursor, write out the *current* level if
683 * required. don't write out the descendant level
684 */
685 ASSERT(cursor->level[this_level].dirty == 0 ||
686 (cursor->level[this_level].dirty && !no_modify));
687
688 if (cursor->level[this_level].dirty && !no_modify)
689 da_bwrite(mp, cursor->level[this_level].bp);
690 else
691 da_brelse(cursor->level[this_level].bp);
692 cursor->level[this_level].bp = bp;
693 cursor->level[this_level].dirty = 0;
694 cursor->level[this_level].bno = dabno;
695 cursor->level[this_level].hashval = INT_GET(newnode->btree[0].hashval, ARCH_CONVERT);
696 node = newnode;
697
698 entry = cursor->level[this_level].index = 0;
699 }
700 /*
701 * ditto for block numbers
702 */
703 if (cursor->level[p_level].bno != INT_GET(node->btree[entry].before, ARCH_CONVERT)) {
704 return(1);
705 }
706 /*
707 * ok, now validate last hashvalue in the descendant
708 * block against the hashval in the current entry
709 */
710 if (cursor->level[p_level].hashval != INT_GET(node->btree[entry].hashval, ARCH_CONVERT)) {
711 if (!no_modify) {
712 do_warn("correcting bad hashval in interior dir "
713 "block\n");
714 do_warn("\tin (level %d) in inode %llu.\n",
715 this_level, cursor->ino);
716 INT_SET(node->btree[entry].hashval, ARCH_CONVERT, cursor->level[p_level].hashval);
717 cursor->level[this_level].dirty++;
718 } else {
719 do_warn("would correct bad hashval in interior dir "
720 "block\n");
721 do_warn("\tin (level %d) in inode %llu.\n",
722 this_level, cursor->ino);
723 }
724 }
725 /*
726 * increment index for this level to point to next entry
727 * (which should point to the next descendant block)
728 */
729 cursor->level[this_level].index++;
730 return(0);
731 }
732
733 /*
734 * Fix up a shortform directory which was in long form (i8count set)
735 * and is now in short form (i8count clear).
736 * Return pointer to the end of the data when done.
737 */
738 void
739 process_sf_dir2_fixi8(
740 xfs_dir2_sf_t *sfp,
741 xfs_dir2_sf_entry_t **next_sfep)
742 {
743 xfs_ino_t ino;
744 xfs_dir2_sf_t *newsfp;
745 xfs_dir2_sf_entry_t *newsfep;
746 xfs_dir2_sf_t *oldsfp;
747 xfs_dir2_sf_entry_t *oldsfep;
748 int oldsize;
749
750 newsfp = sfp;
751 oldsize = (__psint_t)*next_sfep - (__psint_t)sfp;
752 oldsfp = malloc(oldsize);
753 if (oldsfp == NULL) {
754 do_error("couldn't malloc dir2 shortform copy\n");
755 exit(1);
756 }
757 memmove(oldsfp, newsfp, oldsize);
758 INT_SET(newsfp->hdr.count, ARCH_CONVERT, INT_GET(oldsfp->hdr.count, ARCH_CONVERT));
759 newsfp->hdr.i8count = 0;
760 ino = XFS_DIR2_SF_GET_INUMBER_ARCH(oldsfp, &oldsfp->hdr.parent, ARCH_CONVERT);
761 XFS_DIR2_SF_PUT_INUMBER_ARCH(newsfp, &ino, &newsfp->hdr.parent, ARCH_CONVERT);
762 oldsfep = XFS_DIR2_SF_FIRSTENTRY(oldsfp);
763 newsfep = XFS_DIR2_SF_FIRSTENTRY(newsfp);
764 while ((int)((char *)oldsfep - (char *)oldsfp) < oldsize) {
765 newsfep->namelen = oldsfep->namelen;
766 XFS_DIR2_SF_PUT_OFFSET_ARCH(newsfep,
767 XFS_DIR2_SF_GET_OFFSET_ARCH(oldsfep, ARCH_CONVERT), ARCH_CONVERT);
768 memmove(newsfep->name, oldsfep->name, newsfep->namelen);
769 ino = XFS_DIR2_SF_GET_INUMBER_ARCH(oldsfp,
770 XFS_DIR2_SF_INUMBERP(oldsfep), ARCH_CONVERT);
771 XFS_DIR2_SF_PUT_INUMBER_ARCH(newsfp, &ino,
772 XFS_DIR2_SF_INUMBERP(newsfep), ARCH_CONVERT);
773 oldsfep = XFS_DIR2_SF_NEXTENTRY(oldsfp, oldsfep);
774 newsfep = XFS_DIR2_SF_NEXTENTRY(newsfp, newsfep);
775 }
776 *next_sfep = newsfep;
777 free(oldsfp);
778 }
779
780 /*
781 * Regenerate legal (minimal) offsets for the shortform directory.
782 */
783 static void
784 process_sf_dir2_fixoff(
785 xfs_dinode_t *dip)
786 {
787 int i;
788 int offset;
789 xfs_dir2_sf_entry_t *sfep;
790 xfs_dir2_sf_t *sfp;
791
792 for (i = 0, sfp = &dip->di_u.di_dir2sf,
793 sfep = XFS_DIR2_SF_FIRSTENTRY(sfp),
794 offset = XFS_DIR2_DATA_FIRST_OFFSET;
795 i < INT_GET(sfp->hdr.count, ARCH_CONVERT);
796 i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
797 XFS_DIR2_SF_PUT_OFFSET_ARCH(sfep, offset, ARCH_CONVERT);
798 offset += XFS_DIR2_DATA_ENTSIZE(sfep->namelen);
799 }
800 }
801
802 /*
803 * this routine performs inode discovery and tries to fix things
804 * in place. available redundancy -- inode data size should match
805 * used directory space in inode.
806 * a non-zero return value means the directory is bogus and should be blasted.
807 */
808 /* ARGSUSED */
809 static int
810 process_sf_dir2(
811 xfs_mount_t *mp,
812 xfs_ino_t ino,
813 xfs_dinode_t *dip,
814 int ino_discovery,
815 int *dino_dirty, /* out - 1 if dinode buffer dirty */
816 char *dirname, /* directory pathname */
817 xfs_ino_t *parent, /* out - NULLFSINO if entry not exist */
818 int *repair) /* out - 1 if dir was fixed up */
819 {
820 int bad_offset;
821 int bad_sfnamelen;
822 int i;
823 int i8;
824 __int64_t ino_dir_size;
825 int ino_off;
826 ino_tree_node_t *irec_p;
827 int junkit;
828 char *junkreason = NULL;
829 xfs_ino_t lino;
830 int max_size;
831 char name[MAXNAMELEN + 1];
832 int namelen;
833 xfs_dir2_sf_entry_t *next_sfep;
834 int num_entries;
835 int offset;
836 xfs_dir2_sf_t *sfp;
837 xfs_dir2_sf_entry_t *sfep;
838 int tmp_elen;
839 int tmp_len;
840 xfs_dir2_sf_entry_t *tmp_sfep;
841 xfs_ino_t zero = 0;
842
843 sfp = &dip->di_u.di_dir2sf;
844 max_size = XFS_DFORK_DSIZE_ARCH(dip, mp, ARCH_CONVERT);
845 num_entries = INT_GET(sfp->hdr.count, ARCH_CONVERT);
846 ino_dir_size = INT_GET(dip->di_core.di_size, ARCH_CONVERT);
847 offset = XFS_DIR2_DATA_FIRST_OFFSET;
848 i8 = bad_offset = *repair = 0;
849
850 ASSERT(ino_dir_size <= max_size);
851
852 /*
853 * check for bad entry count
854 */
855 if (num_entries * XFS_DIR2_SF_ENTSIZE_BYNAME(sfp, 1) +
856 XFS_DIR2_SF_HDR_SIZE(0) > max_size ||
857 num_entries == 0)
858 num_entries = 0xFF;
859
860 /*
861 * run through entries, stop at first bad entry, don't need
862 * to check for .. since that's encoded in its own field
863 */
864 sfep = next_sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
865 for (i = 0;
866 i < num_entries && ino_dir_size > (char *)next_sfep - (char *)sfp;
867 i++) {
868 tmp_sfep = NULL;
869 sfep = next_sfep;
870 junkit = 0;
871 bad_sfnamelen = 0;
872 lino = XFS_DIR2_SF_GET_INUMBER_ARCH(sfp, XFS_DIR2_SF_INUMBERP(sfep), ARCH_CONVERT);
873 /*
874 * if entry points to self, junk it since only '.' or '..'
875 * should do that and shortform dirs don't contain either
876 * entry. if inode number is invalid, trash entry.
877 * if entry points to special inodes, trash it.
878 * if inode is unknown but number is valid,
879 * add it to the list of uncertain inodes. don't
880 * have to worry about an entry pointing to a
881 * deleted lost+found inode because the entry was
882 * deleted at the same time that the inode was cleared.
883 */
884 if (lino == ino) {
885 junkit = 1;
886 junkreason = "current";
887 } else if (verify_inum(mp, lino)) {
888 junkit = 1;
889 junkreason = "invalid";
890 } else if (lino == mp->m_sb.sb_rbmino) {
891 junkit = 1;
892 junkreason = "realtime bitmap";
893 } else if (lino == mp->m_sb.sb_rsumino) {
894 junkit = 1;
895 junkreason = "realtime summary";
896 } else if (lino == mp->m_sb.sb_uquotino) {
897 junkit = 1;
898 junkreason = "user quota";
899 } else if (lino == mp->m_sb.sb_gquotino) {
900 junkit = 1;
901 junkreason = "group quota";
902 } else if ((irec_p = find_inode_rec(XFS_INO_TO_AGNO(mp, lino),
903 XFS_INO_TO_AGINO(mp, lino))) != NULL) {
904 /*
905 * if inode is marked free and we're in inode
906 * discovery mode, leave the entry alone for now.
907 * if the inode turns out to be used, we'll figure
908 * that out when we scan it. If the inode really
909 * is free, we'll hit this code again in phase 4
910 * after we've finished inode discovery and blow
911 * out the entry then.
912 */
913 ino_off = XFS_INO_TO_AGINO(mp, lino) -
914 irec_p->ino_startnum;
915 ASSERT(is_inode_confirmed(irec_p, ino_off));
916 if (is_inode_free(irec_p, ino_off) && !ino_discovery) {
917 junkit = 1;
918 junkreason = "free";
919 }
920 } else if (ino_discovery) {
921 /*
922 * put the inode on the uncertain list. we'll
923 * pull the inode off the list and check it later.
924 * if the inode turns out be bogus, we'll delete
925 * this entry in phase 6.
926 */
927 add_inode_uncertain(mp, lino, 0);
928 } else {
929 /*
930 * blow the entry out. we know about all
931 * undiscovered entries now (past inode discovery
932 * phase) so this is clearly a bogus entry.
933 */
934 junkit = 1;
935 junkreason = "non-existent";
936 }
937 namelen = sfep->namelen;
938 if (junkit)
939 do_warn("entry \"%*.*s\" in shortform directory %llu "
940 "references %s inode %llu\n",
941 namelen, namelen, sfep->name, ino, junkreason,
942 lino);
943 if (namelen == 0) {
944 /*
945 * if we're really lucky, this is
946 * the last entry in which case we
947 * can use the dir size to set the
948 * namelen value. otherwise, forget
949 * it because we're not going to be
950 * able to find the next entry.
951 */
952 bad_sfnamelen = 1;
953
954 if (i == num_entries - 1) {
955 namelen = ino_dir_size -
956 ((__psint_t) &sfep->name[0] -
957 (__psint_t) sfp);
958 if (!no_modify) {
959 do_warn("zero length entry in "
960 "shortform dir %llu, resetting "
961 "to %d\n",
962 ino, namelen);
963 sfep->namelen = namelen;
964 } else {
965 do_warn("zero length entry in "
966 "shortform dir %llu, would set "
967 "to %d\n",
968 ino, namelen);
969 }
970 } else {
971 do_warn("zero length entry in shortform dir "
972 "%llu",
973 ino);
974 if (!no_modify)
975 do_warn(", junking %d entries\n",
976 num_entries - i);
977 else
978 do_warn(", would junk %d entries\n",
979 num_entries - i);
980 /*
981 * don't process the rest of the directory,
982 * break out of processing looop
983 */
984 break;
985 }
986 } else if ((__psint_t) sfep - (__psint_t) sfp +
987 + XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp, sfep)
988 > ino_dir_size) {
989 bad_sfnamelen = 1;
990
991 if (i == num_entries - 1) {
992 namelen = ino_dir_size -
993 ((__psint_t) &sfep->name[0] -
994 (__psint_t) sfp);
995 do_warn("size of last entry overflows space "
996 "left in in shortform dir %llu, ",
997 ino);
998 if (!no_modify) {
999 do_warn("resetting to %d\n",
1000 namelen);
1001 sfep->namelen = namelen;
1002 *dino_dirty = 1;
1003 } else {
1004 do_warn("would reset to %d\n",
1005 namelen);
1006 }
1007 } else {
1008 do_warn("size of entry #%d overflows space "
1009 "left in in shortform dir %llu\n",
1010 i, ino);
1011 if (!no_modify) {
1012 if (i == num_entries - 1)
1013 do_warn("junking entry #%d\n",
1014 i);
1015 else
1016 do_warn("junking %d entries\n",
1017 num_entries - i);
1018 } else {
1019 if (i == num_entries - 1)
1020 do_warn("would junk entry "
1021 "#%d\n",
1022 i);
1023 else
1024 do_warn("would junk %d "
1025 "entries\n",
1026 num_entries - i);
1027 }
1028
1029 break;
1030 }
1031 }
1032
1033 /*
1034 * check for illegal chars in name.
1035 * no need to check for bad length because
1036 * the length value is stored in a byte
1037 * so it can't be too big, it can only wrap
1038 */
1039 if (namecheck((char *)&sfep->name[0], namelen)) {
1040 /*
1041 * junk entry
1042 */
1043 do_warn("entry contains illegal character in shortform "
1044 "dir %llu\n",
1045 ino);
1046 junkit = 1;
1047 }
1048
1049 if (XFS_DIR2_SF_GET_OFFSET_ARCH(sfep, ARCH_CONVERT) < offset) {
1050 do_warn("entry contains offset out of order in "
1051 "shortform dir %llu\n",
1052 ino);
1053 bad_offset = 1;
1054 }
1055 offset = XFS_DIR2_SF_GET_OFFSET_ARCH(sfep, ARCH_CONVERT) +
1056 XFS_DIR2_DATA_ENTSIZE(namelen);
1057
1058 /*
1059 * junk the entry by copying up the rest of the
1060 * fork over the current entry and decrementing
1061 * the entry count. if we're in no_modify mode,
1062 * just issue the warning instead. then continue
1063 * the loop with the next_sfep pointer set to the
1064 * correct place in the fork and other counters
1065 * properly set to reflect the deletion if it
1066 * happened.
1067 */
1068 if (junkit) {
1069 bcopy(sfep->name, name, namelen);
1070 name[namelen] = '\0';
1071
1072 if (!no_modify) {
1073 tmp_elen =
1074 XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp, sfep);
1075 INT_MOD(dip->di_core.di_size, ARCH_CONVERT, -(tmp_elen));
1076 ino_dir_size -= tmp_elen;
1077
1078 tmp_sfep = (xfs_dir2_sf_entry_t *)
1079 ((__psint_t) sfep + tmp_elen);
1080 tmp_len = max_size - ((__psint_t) tmp_sfep
1081 - (__psint_t) sfp);
1082
1083 memmove(sfep, tmp_sfep, tmp_len);
1084
1085 INT_MOD(sfp->hdr.count, ARCH_CONVERT, -1);
1086 num_entries--;
1087 bzero((void *) ((__psint_t) sfep + tmp_len),
1088 tmp_elen);
1089
1090 /*
1091 * reset the tmp value to the current
1092 * pointer so we'll process the entry
1093 * we just moved up
1094 */
1095 tmp_sfep = sfep;
1096
1097 /*
1098 * WARNING: drop the index i by one
1099 * so it matches the decremented count
1100 * for accurate comparisons later
1101 */
1102 i--;
1103
1104 *dino_dirty = 1;
1105 *repair = 1;
1106
1107 do_warn("junking entry \"%s\" in directory "
1108 "inode %llu\n",
1109 name, ino);
1110 } else {
1111 do_warn("would have junked entry \"%s\" in "
1112 "directory inode %llu\n",
1113 name, ino);
1114 }
1115 } else if (lino > XFS_DIR2_MAX_SHORT_INUM)
1116 i8++;
1117 /*
1118 * go onto next entry unless we've just junked an
1119 * entry in which the current entry pointer points
1120 * to an unprocessed entry. have to take into zero-len
1121 * entries into account in no modify mode since we
1122 * calculate size based on next_sfep.
1123 */
1124 next_sfep = (tmp_sfep == NULL)
1125 ? (xfs_dir2_sf_entry_t *) ((__psint_t) sfep
1126 + ((!bad_sfnamelen)
1127 ? XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp,
1128 sfep)
1129 : XFS_DIR2_SF_ENTSIZE_BYNAME(sfp,
1130 namelen)))
1131 : tmp_sfep;
1132 }
1133
1134 /* sync up sizes and entry counts */
1135
1136 if (INT_GET(sfp->hdr.count, ARCH_CONVERT) != i) {
1137 if (no_modify) {
1138 do_warn("would have corrected entry count in directory "
1139 "%llu from %d to %d\n",
1140 ino, INT_GET(sfp->hdr.count, ARCH_CONVERT), i);
1141 } else {
1142 do_warn("corrected entry count in directory %llu, was "
1143 "%d, now %d\n",
1144 ino, INT_GET(sfp->hdr.count, ARCH_CONVERT), i);
1145 INT_SET(sfp->hdr.count, ARCH_CONVERT, i);
1146 *dino_dirty = 1;
1147 *repair = 1;
1148 }
1149 }
1150
1151 if (sfp->hdr.i8count != i8) {
1152 if (no_modify) {
1153 do_warn("would have corrected i8 count in directory "
1154 "%llu from %d to %d\n",
1155 ino, sfp->hdr.i8count, i8);
1156 } else {
1157 do_warn("corrected i8 count in directory %llu, was %d, "
1158 "now %d\n",
1159 ino, sfp->hdr.i8count, i8);
1160 if (i8 == 0)
1161 process_sf_dir2_fixi8(sfp, &next_sfep);
1162 else
1163 sfp->hdr.i8count = i8;
1164 *dino_dirty = 1;
1165 *repair = 1;
1166 }
1167 }
1168
1169 if ((__psint_t) next_sfep - (__psint_t) sfp != ino_dir_size) {
1170 if (no_modify) {
1171 do_warn("would have corrected directory %llu size from "
1172 "%lld to %lld\n",
1173 ino, (__int64_t) ino_dir_size,
1174 (__int64_t)((__psint_t)next_sfep -
1175 (__psint_t)sfp));
1176 } else {
1177 do_warn("corrected directory %llu size, was %lld, now "
1178 "%lld\n",
1179 ino, (__int64_t) ino_dir_size,
1180 (__int64_t)((__psint_t)next_sfep -
1181 (__psint_t)sfp));
1182
1183 INT_SET(dip->di_core.di_size, ARCH_CONVERT, (xfs_fsize_t)((__psint_t)next_sfep -
1184 (__psint_t)sfp));
1185 *dino_dirty = 1;
1186 *repair = 1;
1187 }
1188 }
1189 if (offset + (INT_GET(sfp->hdr.count, ARCH_CONVERT) + 2) * sizeof(xfs_dir2_leaf_entry_t) +
1190 sizeof(xfs_dir2_block_tail_t) > mp->m_dirblksize) {
1191 do_warn("directory %llu offsets too high\n", ino);
1192 bad_offset = 1;
1193 }
1194 if (bad_offset) {
1195 if (no_modify) {
1196 do_warn("would have corrected entry offsets in "
1197 "directory %llu\n",
1198 ino);
1199 } else {
1200 do_warn("corrected entry offsets in directory %llu\n",
1201 ino);
1202 process_sf_dir2_fixoff(dip);
1203 *dino_dirty = 1;
1204 *repair = 1;
1205 }
1206 }
1207
1208 /*
1209 * check parent (..) entry
1210 */
1211 *parent = XFS_DIR2_SF_GET_INUMBER_ARCH(sfp, &sfp->hdr.parent, ARCH_CONVERT);
1212
1213 /*
1214 * if parent entry is bogus, null it out. we'll fix it later .
1215 */
1216 if (verify_inum(mp, *parent)) {
1217
1218 do_warn("bogus .. inode number (%llu) in directory inode "
1219 "%llu, ",
1220 *parent, ino);
1221 *parent = NULLFSINO;
1222 if (!no_modify) {
1223 do_warn("clearing inode number\n");
1224
1225 XFS_DIR2_SF_PUT_INUMBER_ARCH(sfp, &zero, &sfp->hdr.parent, ARCH_CONVERT);
1226 *dino_dirty = 1;
1227 *repair = 1;
1228 } else {
1229 do_warn("would clear inode number\n");
1230 }
1231 } else if (ino == mp->m_sb.sb_rootino && ino != *parent) {
1232 /*
1233 * root directories must have .. == .
1234 */
1235 if (!no_modify) {
1236 do_warn("corrected root directory %llu .. entry, was "
1237 "%llu, now %llu\n",
1238 ino, *parent, ino);
1239 *parent = ino;
1240 XFS_DIR2_SF_PUT_INUMBER_ARCH(sfp, parent, &sfp->hdr.parent, ARCH_CONVERT);
1241 *dino_dirty = 1;
1242 *repair = 1;
1243 } else {
1244 do_warn("would have corrected root directory %llu .. "
1245 "entry from %llu to %llu\n",
1246 ino, *parent, ino);
1247 }
1248 } else if (ino == *parent && ino != mp->m_sb.sb_rootino) {
1249 /*
1250 * likewise, non-root directories can't have .. pointing
1251 * to .
1252 */
1253 *parent = NULLFSINO;
1254 do_warn("bad .. entry in directory inode %llu, points to "
1255 "self,",
1256 ino);
1257 if (!no_modify) {
1258 do_warn(" clearing inode number\n");
1259
1260 XFS_DIR2_SF_PUT_INUMBER_ARCH(sfp, &zero, &sfp->hdr.parent, ARCH_CONVERT);
1261 *dino_dirty = 1;
1262 *repair = 1;
1263 } else {
1264 do_warn(" would clear inode number\n");
1265 }
1266 }
1267
1268 return(0);
1269 }
1270
1271 /*
1272 * Process one directory data block.
1273 */
1274 /* ARGSUSED */
1275 static int
1276 process_dir2_data(
1277 xfs_mount_t *mp,
1278 xfs_ino_t ino,
1279 xfs_dinode_t *dip,
1280 int ino_discovery,
1281 char *dirname, /* directory pathname */
1282 xfs_ino_t *parent, /* out - NULLFSINO if entry not exist */
1283 xfs_dabuf_t *bp,
1284 int *dot, /* out - 1 if there is a dot, else 0 */
1285 int *dotdot, /* out - 1 if there's a dotdot, else 0 */
1286 xfs_dablk_t da_bno,
1287 char *endptr)
1288 {
1289 int badbest;
1290 xfs_dir2_data_free_t *bf;
1291 int clearino;
1292 char *clearreason = NULL;
1293 xfs_dir2_data_t *d;
1294 xfs_dir2_data_entry_t *dep;
1295 xfs_dir2_data_free_t *dfp;
1296 xfs_dir2_data_unused_t *dup;
1297 int freeseen;
1298 int i;
1299 int ino_off;
1300 ino_tree_node_t *irec_p;
1301 int junkit;
1302 int lastfree;
1303 int nm_illegal;
1304 char *ptr;
1305
1306 d = bp->data;
1307 bf = d->hdr.bestfree;
1308 ptr = (char *)d->u;
1309 badbest = lastfree = freeseen = 0;
1310 if (INT_GET(bf[0].length, ARCH_CONVERT) == 0) {
1311 badbest |= INT_GET(bf[0].offset, ARCH_CONVERT) != 0;
1312 freeseen |= 1 << 0;
1313 }
1314 if (INT_GET(bf[1].length, ARCH_CONVERT) == 0) {
1315 badbest |= INT_GET(bf[1].offset, ARCH_CONVERT) != 0;
1316 freeseen |= 1 << 1;
1317 }
1318 if (INT_GET(bf[2].length, ARCH_CONVERT) == 0) {
1319 badbest |= INT_GET(bf[2].offset, ARCH_CONVERT) != 0;
1320 freeseen |= 1 << 2;
1321 }
1322 badbest |= INT_GET(bf[0].length, ARCH_CONVERT) < INT_GET(bf[1].length, ARCH_CONVERT);
1323 badbest |= INT_GET(bf[1].length, ARCH_CONVERT) < INT_GET(bf[2].length, ARCH_CONVERT);
1324 while (ptr < endptr) {
1325 dup = (xfs_dir2_data_unused_t *)ptr;
1326 /*
1327 * If it's unused, look for the space in the bestfree table.
1328 * If we find it, account for that, else make sure it doesn't
1329 * need to be there.
1330 */
1331 if (INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG) {
1332 if (ptr + INT_GET(dup->length, ARCH_CONVERT) > endptr || INT_GET(dup->length, ARCH_CONVERT) == 0 ||
1333 (INT_GET(dup->length, ARCH_CONVERT) & (XFS_DIR2_DATA_ALIGN - 1)))
1334 break;
1335 if (INT_GET(*XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(dup, ARCH_CONVERT), ARCH_CONVERT) !=
1336 (char *)dup - (char *)d)
1337 break;
1338 badbest |= lastfree != 0;
1339 dfp = xfs_dir2_data_freefind(d, dup);
1340 if (dfp) {
1341 i = dfp - bf;
1342 badbest |= (freeseen & (1 << i)) != 0;
1343 freeseen |= 1 << i;
1344 } else
1345 badbest |= INT_GET(dup->length, ARCH_CONVERT) > INT_GET(bf[2].length, ARCH_CONVERT);
1346 ptr += INT_GET(dup->length, ARCH_CONVERT);
1347 lastfree = 1;
1348 continue;
1349 }
1350 dep = (xfs_dir2_data_entry_t *)ptr;
1351 if (ptr + XFS_DIR2_DATA_ENTSIZE(dep->namelen) > endptr)
1352 break;
1353 if (INT_GET(*XFS_DIR2_DATA_ENTRY_TAG_P(dep), ARCH_CONVERT) != (char *)dep - (char *)d)
1354 break;
1355 ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
1356 lastfree = 0;
1357 }
1358 /*
1359 * Dropped out before we processed everything, give up.
1360 * Phase 6 will kill this block if we don't kill the inode.
1361 */
1362 if (ptr != endptr) {
1363 do_warn("corrupt block %u in directory inode %llu\n",
1364 da_bno, ino);
1365 if (!no_modify)
1366 do_warn("\twill junk block\n");
1367 else
1368 do_warn("\twould junk block\n");
1369 return 1;
1370 }
1371 ptr = (char *)d->u;
1372 /*
1373 * Process the entries now.
1374 */
1375 while (ptr < endptr) {
1376 dup = (xfs_dir2_data_unused_t *)ptr;
1377 if (INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG) {
1378 ptr += INT_GET(dup->length, ARCH_CONVERT);
1379 continue;
1380 }
1381 dep = (xfs_dir2_data_entry_t *)ptr;
1382 /*
1383 * We may have to blow out an entry because of bad inode
1384 * numbers. Do NOT touch the name until after we've computed
1385 * the hashvalue and done a namecheck() on the name.
1386 */
1387 if (!ino_discovery && INT_GET(dep->inumber, ARCH_CONVERT) == BADFSINO) {
1388 /*
1389 * Don't do a damned thing. We already found this
1390 * (or did it ourselves) during phase 3.
1391 */
1392 clearino = 0;
1393 } else if (verify_inum(mp, INT_GET(dep->inumber, ARCH_CONVERT))) {
1394 /*
1395 * Bad inode number. Clear the inode number and the
1396 * entry will get removed later. We don't trash the
1397 * directory since it's still structurally intact.
1398 */
1399 clearino = 1;
1400 clearreason = "invalid";
1401 } else if (INT_GET(dep->inumber, ARCH_CONVERT) == mp->m_sb.sb_rbmino) {
1402 clearino = 1;
1403 clearreason = "realtime bitmap";
1404 } else if (INT_GET(dep->inumber, ARCH_CONVERT) == mp->m_sb.sb_rsumino) {
1405 clearino = 1;
1406 clearreason = "realtime summary";
1407 } else if (INT_GET(dep->inumber, ARCH_CONVERT) == mp->m_sb.sb_uquotino) {
1408 clearino = 1;
1409 clearreason = "user quota";
1410 } else if (INT_GET(dep->inumber, ARCH_CONVERT) == mp->m_sb.sb_gquotino) {
1411 clearino = 1;
1412 clearreason = "group quota";
1413 } else if (INT_GET(dep->inumber, ARCH_CONVERT) == old_orphanage_ino) {
1414 /*
1415 * Do nothing, silently ignore it, entry has already
1416 * been marked TBD since old_orphanage_ino is set
1417 * non-zero.
1418 */
1419 clearino = 0;
1420 } else if ((irec_p = find_inode_rec(
1421 XFS_INO_TO_AGNO(mp, INT_GET(dep->inumber, ARCH_CONVERT)),
1422 XFS_INO_TO_AGINO(mp, INT_GET(dep->inumber, ARCH_CONVERT)))) != NULL) {
1423 /*
1424 * Inode recs should have only confirmed inodes in them.
1425 */
1426 ino_off =
1427 XFS_INO_TO_AGINO(mp, INT_GET(dep->inumber, ARCH_CONVERT)) -
1428 irec_p->ino_startnum;
1429 ASSERT(is_inode_confirmed(irec_p, ino_off));
1430 /*
1431 * If inode is marked free and we're in inode discovery
1432 * mode, leave the entry alone for now. If the inode
1433 * turns out to be used, we'll figure that out when we
1434 * scan it. If the inode really is free, we'll hit this
1435 * code again in phase 4 after we've finished inode
1436 * discovery and blow out the entry then.
1437 */
1438 if (!ino_discovery && is_inode_free(irec_p, ino_off)) {
1439 clearino = 1;
1440 clearreason = "free";
1441 } else
1442 clearino = 0;
1443 } else if (ino_discovery) {
1444 add_inode_uncertain(mp, INT_GET(dep->inumber, ARCH_CONVERT), 0);
1445 clearino = 0;
1446 } else {
1447 clearino = 1;
1448 clearreason = "non-existent";
1449 }
1450 if (clearino)
1451 do_warn("entry \"%*.*s\" at block %u offset %d in "
1452 "directory inode %llu references %s inode "
1453 "%llu\n",
1454 dep->namelen, dep->namelen, dep->name,
1455 da_bno, (char *)ptr - (char *)d, ino,
1456 clearreason, INT_GET(dep->inumber, ARCH_CONVERT));
1457 /*
1458 * If the name length is 0 (illegal) make it 1 and blast
1459 * the entry.
1460 */
1461 if (dep->namelen == 0) {
1462 do_warn("entry at block %u offset %d in directory "
1463 "inode %llu has 0 namelength\n",
1464 da_bno, (char *)ptr - (char *)d, ino);
1465 if (!no_modify)
1466 dep->namelen = 1;
1467 clearino = 1;
1468 }
1469 /*
1470 * If needed to clear the inode number, do it now.
1471 */
1472 if (clearino) {
1473 if (!no_modify) {
1474 do_warn("\tclearing inode number in entry at "
1475 "offset %d...\n",
1476 (char *)ptr - (char *)d);
1477 INT_SET(dep->inumber, ARCH_CONVERT, BADFSINO);
1478 bp->dirty = 1;
1479 } else {
1480 do_warn("\twould clear inode number in entry "
1481 "at offset %d...\n",
1482 (char *)ptr - (char *)d);
1483 }
1484 }
1485 /*
1486 * Only complain about illegal names in phase 3 (when inode
1487 * discovery is turned on). Otherwise, we'd complain a lot
1488 * during phase 4.
1489 */
1490 junkit = INT_GET(dep->inumber, ARCH_CONVERT) == BADFSINO;
1491 nm_illegal = namecheck((char *)dep->name, dep->namelen);
1492 if (ino_discovery && nm_illegal) {
1493 do_warn("entry at block %u offset %d in directory "
1494 "inode %llu has illegal name \"%*.*s\": ",
1495 da_bno, (char *)ptr - (char *)d, ino,
1496 dep->namelen, dep->namelen, dep->name);
1497 junkit = 1;
1498 }
1499 /*
1500 * Now we can mark entries with BADFSINO's bad.
1501 */
1502 if (!no_modify && INT_GET(dep->inumber, ARCH_CONVERT) == BADFSINO) {
1503 dep->name[0] = '/';
1504 bp->dirty = 1;
1505 junkit = 0;
1506 }
1507 /*
1508 * Special .. entry processing.
1509 */
1510 if (dep->namelen == 2 &&
1511 dep->name[0] == '.' && dep->name[1] == '.') {
1512 if (!*dotdot) {
1513 (*dotdot)++;
1514 *parent = INT_GET(dep->inumber, ARCH_CONVERT);
1515 /*
1516 * What if .. == .? Legal only in the root
1517 * inode. Blow out entry and set parent to
1518 * NULLFSINO otherwise.
1519 */
1520 if (ino == INT_GET(dep->inumber, ARCH_CONVERT) &&
1521 ino != mp->m_sb.sb_rootino) {
1522 *parent = NULLFSINO;
1523 do_warn("bad .. entry in directory "
1524 "inode %llu, points to self: ",
1525 ino);
1526 junkit = 1;
1527 }
1528 /*
1529 * We have to make sure that . == .. in the
1530 * root inode.
1531 */
1532 else if (ino != INT_GET(dep->inumber, ARCH_CONVERT) &&
1533 ino == mp->m_sb.sb_rootino) {
1534 do_warn("bad .. entry in root "
1535 "directory inode %llu, was "
1536 "%llu: ",
1537 ino, INT_GET(dep->inumber, ARCH_CONVERT));
1538 if (!no_modify) {
1539 do_warn("correcting\n");
1540 INT_SET(dep->inumber, ARCH_CONVERT, ino);
1541 bp->dirty = 1;
1542 } else {
1543 do_warn("would correct\n");
1544 }
1545 }
1546 }
1547 /*
1548 * Can't fix the directory unless we know which ..
1549 * entry is the right one. Both have valid inode
1550 * numbers or we wouldn't be here. So since both
1551 * seem equally valid, trash this one.
1552 */
1553 else {
1554 do_warn("multiple .. entries in directory "
1555 "inode %llu: ",
1556 ino);
1557 junkit = 1;
1558 }
1559 }
1560 /*
1561 * Special . entry processing.
1562 */
1563 else if (dep->namelen == 1 && dep->name[0] == '.') {
1564 if (!*dot) {
1565 (*dot)++;
1566 if (INT_GET(dep->inumber, ARCH_CONVERT) != ino) {
1567 do_warn("bad . entry in directory "
1568 "inode %llu, was %llu: ",
1569 ino, INT_GET(dep->inumber, ARCH_CONVERT));
1570 if (!no_modify) {
1571 do_warn("correcting\n");
1572 INT_SET(dep->inumber, ARCH_CONVERT, ino);
1573 bp->dirty = 1;
1574 } else {
1575 do_warn("would correct\n");
1576 }
1577 }
1578 } else {
1579 do_warn("multiple . entries in directory "
1580 "inode %llu: ",
1581 ino);
1582 junkit = 1;
1583 }
1584 }
1585 /*
1586 * All other entries -- make sure only . references self.
1587 */
1588 else if (INT_GET(dep->inumber, ARCH_CONVERT) == ino) {
1589 do_warn("entry \"%*.*s\" in directory inode %llu "
1590 "points to self: ",
1591 dep->namelen, dep->namelen, dep->name, ino);
1592 junkit = 1;
1593 }
1594 /*
1595 * Clear junked entries.
1596 */
1597 if (junkit) {
1598 if (!no_modify) {
1599 dep->name[0] = '/';
1600 bp->dirty = 1;
1601 do_warn("clearing entry\n");
1602 } else {
1603 do_warn("would clear entry\n");
1604 }
1605 }
1606 /*
1607 * Advance to the next entry.
1608 */
1609 ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
1610 }
1611 /*
1612 * Check the bestfree table.
1613 */
1614 if (freeseen != 7 || badbest) {
1615 do_warn("bad bestfree table in block %u in directory inode "
1616 "%llu: ",
1617 da_bno, ino);
1618 if (!no_modify) {
1619 do_warn("repairing table\n");
1620 libxfs_dir2_data_freescan(mp, d, &i, endptr);
1621 bp->dirty = 1;
1622 } else {
1623 do_warn("would repair table\n");
1624 }
1625 }
1626 return 0;
1627 }
1628
1629 /*
1630 * Process a block-format directory.
1631 */
1632 /* ARGSUSED */
1633 static int
1634 process_block_dir2(
1635 xfs_mount_t *mp,
1636 xfs_ino_t ino,
1637 xfs_dinode_t *dip,
1638 int ino_discovery,
1639 int *dino_dirty, /* out - 1 if dinode buffer dirty */
1640 char *dirname, /* directory pathname */
1641 xfs_ino_t *parent, /* out - NULLFSINO if entry not exist */
1642 blkmap_t *blkmap,
1643 int *dot, /* out - 1 if there is a dot, else 0 */
1644 int *dotdot, /* out - 1 if there's a dotdot, else 0 */
1645 int *repair) /* out - 1 if something was fixed */
1646 {
1647 xfs_dir2_block_t *block;
1648 xfs_dir2_leaf_entry_t *blp;
1649 bmap_ext_t *bmp;
1650 xfs_dabuf_t *bp;
1651 xfs_dir2_block_tail_t *btp;
1652 int nex;
1653 int rval;
1654
1655 *repair = *dot = *dotdot = 0;
1656 *parent = NULLFSINO;
1657 nex = blkmap_getn(blkmap, mp->m_dirdatablk, mp->m_dirblkfsbs, &bmp);
1658 if (nex == 0) {
1659 do_warn("block %u for directory inode %llu is missing\n",
1660 mp->m_dirdatablk, ino);
1661 return 1;
1662 }
1663 bp = da_read_buf(mp, nex, bmp);
1664 free(bmp);
1665 if (bp == NULL) {
1666 do_warn("can't read block %u for directory inode %llu\n",
1667 mp->m_dirdatablk, ino);
1668 return 1;
1669 }
1670 /*
1671 * Verify the block
1672 */
1673 block = bp->data;
1674 if (INT_GET(block->hdr.magic, ARCH_CONVERT) != XFS_DIR2_BLOCK_MAGIC)
1675 do_warn("bad directory block magic # %#x in block %u for "
1676 "directory inode %llu\n",
1677 INT_GET(block->hdr.magic, ARCH_CONVERT), mp->m_dirdatablk, ino);
1678 /*
1679 * process the data area
1680 * this also checks & fixes the bestfree
1681 */
1682 btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
1683 blp = XFS_DIR2_BLOCK_LEAF_P_ARCH(btp, ARCH_CONVERT);
1684 /*
1685 * Don't let this go past the end of the block.
1686 */
1687 if ((char *)blp > (char *)btp)
1688 blp = (xfs_dir2_leaf_entry_t *)btp;
1689 rval = process_dir2_data(mp, ino, dip, ino_discovery, dirname, parent,
1690 bp, dot, dotdot, mp->m_dirdatablk, (char *)blp);
1691 if (bp->dirty && !no_modify) {
1692 *repair = 1;
1693 da_bwrite(mp, bp);
1694 } else
1695 da_brelse(bp);
1696 return rval;
1697 }
1698
1699 /*
1700 * Validates leaf contents, node format directories only.
1701 * magic number and sibling pointers checked by caller.
1702 * Returns 0 if block is ok, 1 if the block is bad.
1703 * Looking for: out of order hash values, bad stale counts.
1704 */
1705 static int
1706 process_leaf_block_dir2(
1707 xfs_mount_t *mp,
1708 xfs_dir2_leaf_t *leaf,
1709 xfs_dablk_t da_bno,
1710 xfs_ino_t ino,
1711 xfs_dahash_t last_hashval,
1712 xfs_dahash_t *next_hashval)
1713 {
1714 int i;
1715 int stale;
1716
1717 for (i = stale = 0; i < INT_GET(leaf->hdr.count, ARCH_CONVERT); i++) {
1718 if ((char *)&leaf->ents[i] >= (char *)leaf + mp->m_dirblksize) {
1719 do_warn("bad entry count in block %u of directory "
1720 "inode %llu\n",
1721 da_bno, ino);
1722 return 1;
1723 }
1724 if (INT_GET(leaf->ents[i].address, ARCH_CONVERT) == XFS_DIR2_NULL_DATAPTR)
1725 stale++;
1726 else if (INT_GET(leaf->ents[i].hashval, ARCH_CONVERT) < last_hashval) {
1727 do_warn("bad hash ordering in block %u of directory "
1728 "inode %llu\n",
1729 da_bno, ino);
1730 return 1;
1731 }
1732 *next_hashval = last_hashval = INT_GET(leaf->ents[i].hashval, ARCH_CONVERT);
1733 }
1734 if (stale != INT_GET(leaf->hdr.stale, ARCH_CONVERT)) {
1735 do_warn("bad stale count in block %u of directory inode %llu\n",
1736 da_bno, ino);
1737 return 1;
1738 }
1739 return 0;
1740 }
1741
1742 /*
1743 * Returns 0 if the directory is ok, 1 if it has to be rebuilt.
1744 */
1745 static int
1746 process_leaf_level_dir2(
1747 xfs_mount_t *mp,
1748 dir2_bt_cursor_t *da_cursor,
1749 int *repair)
1750 {
1751 bmap_ext_t *bmp;
1752 xfs_dabuf_t *bp;
1753 int buf_dirty;
1754 xfs_dahash_t current_hashval;
1755 xfs_dablk_t da_bno;
1756 xfs_dahash_t greatest_hashval;
1757 xfs_ino_t ino;
1758 xfs_dir2_leaf_t *leaf;
1759 int nex;
1760 xfs_dablk_t prev_bno;
1761
1762 da_bno = da_cursor->level[0].bno;
1763 ino = da_cursor->ino;
1764 prev_bno = 0;
1765 bmp = NULL;
1766 current_hashval = 0;
1767 buf_dirty = 0;
1768
1769 do {
1770 nex = blkmap_getn(da_cursor->blkmap, da_bno, mp->m_dirblkfsbs,
1771 &bmp);
1772 /*
1773 * Directory code uses 0 as the NULL block pointer since 0
1774 * is the root block and no directory block pointer can point
1775 * to the root block of the btree.
1776 */
1777 ASSERT(da_bno != 0);
1778
1779 if (nex == 0) {
1780 do_warn("can't map block %u for directory inode %llu\n",
1781 da_bno, ino);
1782 goto error_out;
1783 }
1784 bp = da_read_buf(mp, nex, bmp);
1785 free(bmp);
1786 bmp = NULL;
1787 if (bp == NULL) {
1788 do_warn("can't read file block %u for directory inode "
1789 "%llu\n",
1790 da_bno, ino);
1791 goto error_out;
1792 }
1793 leaf = bp->data;
1794 /*
1795 * Check magic number for leaf directory btree block.
1796 */
1797 if (INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) != XFS_DIR2_LEAFN_MAGIC) {
1798 do_warn("bad directory leaf magic # %#x for directory "
1799 "inode %llu block %u\n",
1800 INT_GET(leaf->hdr.info.magic, ARCH_CONVERT), ino, da_bno);
1801 da_brelse(bp);
1802 goto error_out;
1803 }
1804 buf_dirty = 0;
1805 /*
1806 * For each block, process the block, verify its path,
1807 * then get next block. Update cursor values along the way.
1808 */
1809 if (process_leaf_block_dir2(mp, leaf, da_bno, ino,
1810 current_hashval, &greatest_hashval)) {
1811 da_brelse(bp);
1812 goto error_out;
1813 }
1814 /*
1815 * Index can be set to hdr.count so match the indices of the
1816 * interior blocks -- which at the end of the block will point
1817 * to 1 after the final real entry in the block.
1818 */
1819 da_cursor->level[0].hashval = greatest_hashval;
1820 da_cursor->level[0].bp = bp;
1821 da_cursor->level[0].bno = da_bno;
1822 da_cursor->level[0].index = INT_GET(leaf->hdr.count, ARCH_CONVERT);
1823 da_cursor->level[0].dirty = buf_dirty;
1824
1825 if (INT_GET(leaf->hdr.info.back, ARCH_CONVERT) != prev_bno) {
1826 do_warn("bad sibling back pointer for block %u in "
1827 "directory inode %llu\n",
1828 da_bno, ino);
1829 da_brelse(bp);
1830 goto error_out;
1831 }
1832 prev_bno = da_bno;
1833 da_bno = INT_GET(leaf->hdr.info.forw, ARCH_CONVERT);
1834 if (da_bno != 0) {
1835 if (verify_dir2_path(mp, da_cursor, 0)) {
1836 da_brelse(bp);
1837 goto error_out;
1838 }
1839 }
1840 current_hashval = greatest_hashval;
1841 ASSERT(buf_dirty == 0 || (buf_dirty && !no_modify));
1842 if (buf_dirty && !no_modify) {
1843 *repair = 1;
1844 da_bwrite(mp, bp);
1845 } else
1846 da_brelse(bp);
1847 } while (da_bno != 0);
1848 if (verify_final_dir2_path(mp, da_cursor, 0)) {
1849 /*
1850 * Verify the final path up (right-hand-side) if still ok.
1851 */
1852 do_warn("bad hash path in directory %llu\n", ino);
1853 goto error_out;
1854 }
1855 /*
1856 * Redundant but just for testing.
1857 */
1858 release_dir2_cursor(mp, da_cursor, 0);
1859 return 0;
1860
1861 error_out:
1862 /*
1863 * Release all buffers holding interior btree blocks.
1864 */
1865 err_release_dir2_cursor(mp, da_cursor, 0);
1866 if (bmp)
1867 free(bmp);
1868 return 1;
1869 }
1870
1871 /*
1872 * Return 1 if the directory's leaf/node space is corrupted and
1873 * needs to be rebuilt, 0 if it's ok.
1874 */
1875 static int
1876 process_node_dir2(
1877 xfs_mount_t *mp,
1878 xfs_ino_t ino,
1879 xfs_dinode_t *dip,
1880 blkmap_t *blkmap,
1881 int *repair)
1882 {
1883 xfs_dablk_t bno;
1884 dir2_bt_cursor_t da_cursor;
1885
1886 /*
1887 * Try again -- traverse down left-side of tree until we hit the
1888 * left-most leaf block setting up the btree cursor along the way.
1889 * Then walk the leaf blocks left-to-right, calling a parent
1890 * verification routine each time we traverse a block.
1891 */
1892 bzero(&da_cursor, sizeof(da_cursor));
1893 da_cursor.ino = ino;
1894 da_cursor.dip = dip;
1895 da_cursor.blkmap = blkmap;
1896
1897 /*
1898 * Now process interior node.
1899 */
1900 if (traverse_int_dir2block(mp, &da_cursor, &bno) == 0)
1901 return 1;
1902
1903 /*
1904 * Skip directories with a root marked XFS_DIR2_LEAFN_MAGIC
1905 */
1906 if (bno == 0) {
1907 release_dir2_cursor(mp, &da_cursor, 0);
1908 return 0;
1909 } else {
1910 /*
1911 * Now pass cursor and bno into leaf-block processing routine.
1912 * The leaf dir level routine checks the interior paths up to
1913 * the root including the final right-most path.
1914 */
1915 return process_leaf_level_dir2(mp, &da_cursor, repair);
1916 }
1917 }
1918
1919 /*
1920 * Process leaf and node directories.
1921 * Process the data blocks then, if it's a node directory, check
1922 * the consistency of those blocks.
1923 */
1924 static int
1925 process_leaf_node_dir2(
1926 xfs_mount_t *mp,
1927 xfs_ino_t ino,
1928 xfs_dinode_t *dip,
1929 int ino_discovery,
1930 char *dirname, /* directory pathname */
1931 xfs_ino_t *parent, /* out - NULLFSINO if entry not exist */
1932 blkmap_t *blkmap,
1933 int *dot, /* out - 1 if there is a dot, else 0 */
1934 int *dotdot, /* out - 1 if there's a dotdot, else 0 */
1935 int *repair, /* out - 1 if something was fixed */
1936 int isnode) /* node directory not leaf */
1937 {
1938 bmap_ext_t *bmp;
1939 xfs_dabuf_t *bp;
1940 xfs_dir2_data_t *data;
1941 xfs_dfiloff_t dbno;
1942 int good;
1943 int i;
1944 xfs_dfiloff_t ndbno;
1945 int nex;
1946 int t;
1947
1948 *repair = *dot = *dotdot = good = 0;
1949 *parent = NULLFSINO;
1950 ndbno = NULLDFILOFF;
1951 while ((dbno = blkmap_next_off(blkmap, ndbno, &t)) < mp->m_dirleafblk) {
1952 nex = blkmap_getn(blkmap, dbno, mp->m_dirblkfsbs, &bmp);
1953 ndbno = dbno + mp->m_dirblkfsbs - 1;
1954 if (nex == 0) {
1955 do_warn("block %llu for directory inode %llu is "
1956 "missing\n",
1957 dbno, ino);
1958 continue;
1959 }
1960 bp = da_read_buf(mp, nex, bmp);
1961 free(bmp);
1962 if (bp == NULL) {
1963 do_warn("can't read block %llu for directory inode "
1964 "%llu\n",
1965 dbno, ino);
1966 continue;
1967 }
1968 data = bp->data;
1969 if (INT_GET(data->hdr.magic, ARCH_CONVERT) != XFS_DIR2_DATA_MAGIC)
1970 do_warn("bad directory block magic # %#x in block %llu "
1971 "for directory inode %llu\n",
1972 INT_GET(data->hdr.magic, ARCH_CONVERT), dbno, ino);
1973 i = process_dir2_data(mp, ino, dip, ino_discovery, dirname,
1974 parent, bp, dot, dotdot, (xfs_dablk_t)dbno,
1975 (char *)data + mp->m_dirblksize);
1976 if (i == 0)
1977 good++;
1978 if (bp->dirty && !no_modify) {
1979 *repair = 1;
1980 da_bwrite(mp, bp);
1981 } else
1982 da_brelse(bp);
1983 }
1984 if (good == 0)
1985 return 1;
1986 if (!isnode)
1987 return 0;
1988 if (dir2_is_badino(ino))
1989 return 0;
1990
1991 if (process_node_dir2(mp, ino, dip, blkmap, repair))
1992 dir2_add_badlist(ino);
1993 return 0;
1994
1995 }
1996
1997 /*
1998 * Returns 1 if things are bad (directory needs to be junked)
1999 * and 0 if things are ok. If ino_discovery is 1, add unknown
2000 * inodes to uncertain inode list.
2001 */
2002 int
2003 process_dir2(
2004 xfs_mount_t *mp,
2005 xfs_ino_t ino,
2006 xfs_dinode_t *dip,
2007 int ino_discovery,
2008 int *dino_dirty,
2009 char *dirname,
2010 xfs_ino_t *parent,
2011 blkmap_t *blkmap)
2012 {
2013 int dot;
2014 int dotdot;
2015 xfs_dfiloff_t last;
2016 int repair;
2017 int res;
2018
2019 *parent = NULLFSINO;
2020 dot = dotdot = 0;
2021 last = 0;
2022
2023 /*
2024 * branch off depending on the type of inode. This routine
2025 * is only called ONCE so all the subordinate routines will
2026 * fix '.' and junk '..' if they're bogus.
2027 */
2028 if (blkmap)
2029 last = blkmap_last_off(blkmap);
2030 if (INT_GET(dip->di_core.di_size, ARCH_CONVERT) <= XFS_DFORK_DSIZE_ARCH(dip, mp, ARCH_CONVERT) &&
2031 dip->di_core.di_format == XFS_DINODE_FMT_LOCAL) {
2032 dot = dotdot = 1;
2033 res = process_sf_dir2(mp, ino, dip, ino_discovery, dino_dirty,
2034 dirname, parent, &repair);
2035 } else if (last == mp->m_dirblkfsbs &&
2036 (dip->di_core.di_format == XFS_DINODE_FMT_EXTENTS ||
2037 dip->di_core.di_format == XFS_DINODE_FMT_BTREE)) {
2038 res = process_block_dir2(mp, ino, dip, ino_discovery,
2039 dino_dirty, dirname, parent, blkmap, &dot, &dotdot,
2040 &repair);
2041 } else if (last >= mp->m_dirleafblk + mp->m_dirblkfsbs &&
2042 (dip->di_core.di_format == XFS_DINODE_FMT_EXTENTS ||
2043 dip->di_core.di_format == XFS_DINODE_FMT_BTREE)) {
2044 res = process_leaf_node_dir2(mp, ino, dip, ino_discovery,
2045 dirname, parent, blkmap, &dot, &dotdot, &repair,
2046 last > mp->m_dirleafblk + mp->m_dirblkfsbs);
2047 } else {
2048 do_warn("bad size/format for directory %llu\n", ino);
2049 return 1;
2050 }
2051 /*
2052 * bad . entries in all directories will be fixed up in phase 6
2053 */
2054 if (dot == 0) {
2055 do_warn("no . entry for directory %llu\n", ino);
2056 }
2057
2058 /*
2059 * shortform dirs always have a .. entry. .. for all longform
2060 * directories will get fixed in phase 6. .. for other shortform
2061 * dirs also get fixed there. .. for a shortform root was
2062 * fixed in place since we know what it should be
2063 */
2064 if (dotdot == 0 && ino != mp->m_sb.sb_rootino) {
2065 do_warn("no .. entry for directory %llu\n", ino);
2066 } else if (dotdot == 0 && ino == mp->m_sb.sb_rootino) {
2067 do_warn("no .. entry for root directory %llu\n", ino);
2068 need_root_dotdot = 1;
2069 }
2070
2071 ASSERT((ino != mp->m_sb.sb_rootino && ino != *parent) ||
2072 (ino == mp->m_sb.sb_rootino &&
2073 (ino == *parent || need_root_dotdot == 1)));
2074
2075 return res;
2076 }