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