]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - repair/da_util.c
xfsprogs: Release v6.7.0
[thirdparty/xfsprogs-dev.git] / repair / da_util.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0
360f4a2e
ES
2/*
3 * Copyright (c) 2015 Red Hat, Inc.
4 * All Rights Reserved.
360f4a2e
ES
5 */
6
7/* Various utilities for repair of directory and attribute metadata */
8
9#include "libxfs.h"
10#include "globals.h"
11#include "err_protos.h"
12#include "bmap.h"
13#include "da_util.h"
14
360f4a2e
ES
15/*
16 * the cursor gets passed up and down the da btree processing
17 * routines. The interior block processing routines use the
18 * cursor to determine if the pointers to and from the preceding
19 * and succeeding sibling blocks are ok and whether the values in
20 * the current block are consistent with the entries in the parent
21 * nodes. When a block is traversed, a parent-verification routine
22 * is called to verify if the next logical entry in the next level up
23 * is consistent with the greatest hashval in the next block of the
24 * current level. The verification routine is itself recursive and
25 * calls itself if it has to traverse an interior block to get
26 * the next logical entry. The routine recurses upwards through
27 * the tree until it finds a block where it can simply step to
28 * the next entry. The hashval in that entry should be equal to
29 * the hashval being passed to it (the greatest hashval in the block
30 * that the entry points to). If that isn't true, then the tree
31 * is blown and we need to trash it, salvage and trash it, or fix it.
32 * Currently, we just trash it.
33 */
34
35/*
36 * Multibuffer handling.
37 * V2 directory blocks can be noncontiguous, needing multiple buffers.
5cd3b070 38 * attr blocks are single blocks; this code handles that as well.
360f4a2e
ES
39 */
40struct xfs_buf *
41da_read_buf(
42 xfs_mount_t *mp,
43 int nex,
44 bmap_ext_t *bmp,
45 const struct xfs_buf_ops *ops)
46{
47#define MAP_ARRAY_SZ 4
48 struct xfs_buf_map map_array[MAP_ARRAY_SZ];
49 struct xfs_buf_map *map;
50 struct xfs_buf *bp;
51 int i;
52
53 if (nex > MAP_ARRAY_SZ) {
54 map = calloc(nex, sizeof(*map));
55 if (map == NULL) {
56 do_error(_("couldn't malloc dir2 buffer list\n"));
57 exit(1);
58 }
59 } else {
60 /* common case avoids calloc/free */
61 map = map_array;
62 }
63 for (i = 0; i < nex; i++) {
64 map[i].bm_bn = XFS_FSB_TO_DADDR(mp, bmp[i].startblock);
65 map[i].bm_len = XFS_FSB_TO_BB(mp, bmp[i].blockcount);
66 }
4c947857
DW
67 libxfs_buf_read_map(mp->m_dev, map, nex, LIBXFS_READBUF_SALVAGE,
68 &bp, ops);
360f4a2e
ES
69 if (map != map_array)
70 free(map);
71 return bp;
72}
73
5cd3b070
ES
74#define FORKNAME(type) (type == XFS_DATA_FORK ? _("directory") : _("attribute"))
75
360f4a2e
ES
76/*
77 * walk tree from root to the left-most leaf block reading in
78 * blocks and setting up cursor. passes back file block number of the
79 * left-most leaf block if successful (bno). returns 1 if successful,
80 * 0 if unsuccessful.
81 */
82int
83traverse_int_dablock(
84 xfs_mount_t *mp,
85 da_bt_cursor_t *da_cursor,
86 xfs_dablk_t *rbno,
87 int whichfork)
88{
89 bmap_ext_t *bmp;
90 xfs_dablk_t bno;
91 struct xfs_buf *bp;
92 int i;
93 int nex;
94 xfs_da_intnode_t *node;
95 bmap_ext_t lbmp;
96 struct xfs_da_geometry *geo;
360f4a2e
ES
97 struct xfs_da3_icnode_hdr nodehdr;
98
99 if (whichfork == XFS_DATA_FORK) {
100 geo = mp->m_dir_geo;
101 bno = geo->leafblk;
102 } else {
103 geo = mp->m_attr_geo;
104 bno = 0;
105 }
106
107 /*
108 * traverse down left-side of tree until we hit the
109 * left-most leaf block setting up the btree cursor along
110 * the way.
111 */
112 i = -1;
113 node = NULL;
114 da_cursor->active = 0;
115
116 do {
117 /*
118 * read in each block along the way and set up cursor
119 */
120 nex = blkmap_getn(da_cursor->blkmap, bno,
121 geo->fsbcount, &bmp, &lbmp);
122
123 if (nex == 0)
124 goto error_out;
125
126 bp = da_read_buf(mp, nex, bmp, &xfs_da3_node_buf_ops);
127 if (bmp != &lbmp)
128 free(bmp);
129
130 if (!bp) {
131 do_warn(
5cd3b070
ES
132_("can't read %s block %u for inode %" PRIu64 "\n"),
133 FORKNAME(whichfork), bno, da_cursor->ino);
360f4a2e
ES
134 goto error_out;
135 }
136
be752639
DW
137 /* corrupt leafn/node; rebuild the dir. */
138 if (bp->b_error == -EFSBADCRC || bp->b_error == -EFSCORRUPTED) {
139 do_warn(
140_("corrupt %s tree block %u for inode %" PRIu64 "\n"),
141 FORKNAME(whichfork), bno, da_cursor->ino);
142 libxfs_buf_relse(bp);
143 goto error_out;
144 }
145
360f4a2e 146 node = bp->b_addr;
08c16786 147 libxfs_da3_node_hdr_from_disk(mp, &nodehdr, node);
360f4a2e
ES
148
149 if (whichfork == XFS_DATA_FORK &&
150 (nodehdr.magic == XFS_DIR2_LEAFN_MAGIC ||
151 nodehdr.magic == XFS_DIR3_LEAFN_MAGIC)) {
152 if (i != -1) {
153 do_warn(
154_("found non-root LEAFN node in inode %" PRIu64 " bno = %u\n"),
155 da_cursor->ino, bno);
156 }
157 *rbno = 0;
e02ba985 158 libxfs_buf_relse(bp);
360f4a2e
ES
159 return 1;
160 }
161
162 if (nodehdr.magic != XFS_DA_NODE_MAGIC &&
163 nodehdr.magic != XFS_DA3_NODE_MAGIC) {
164 do_warn(
5cd3b070
ES
165_("bad %s magic number 0x%x in inode %" PRIu64 " bno = %u\n"),
166 FORKNAME(whichfork), nodehdr.magic,
360f4a2e 167 da_cursor->ino, bno);
e02ba985 168 libxfs_buf_relse(bp);
360f4a2e
ES
169 goto error_out;
170 }
171
360f4a2e
ES
172 if (nodehdr.count > geo->node_ents) {
173 do_warn(
5cd3b070
ES
174_("bad %s record count in inode %" PRIu64 ", count = %d, max = %d\n"),
175 FORKNAME(whichfork), da_cursor->ino,
176 nodehdr.count, geo->node_ents);
e02ba985 177 libxfs_buf_relse(bp);
360f4a2e
ES
178 goto error_out;
179 }
180
181 /*
182 * maintain level counter
183 */
184 if (i == -1) {
185 i = da_cursor->active = nodehdr.level;
186 if (i < 1 || i >= XFS_DA_NODE_MAXDEPTH) {
187 do_warn(
188_("bad header depth for directory inode %" PRIu64 "\n"),
189 da_cursor->ino);
e02ba985 190 libxfs_buf_relse(bp);
360f4a2e
ES
191 i = -1;
192 goto error_out;
193 }
194 } else {
195 if (nodehdr.level == i - 1) {
196 i--;
197 } else {
198 do_warn(
5cd3b070
ES
199_("bad %s btree for inode %" PRIu64 "\n"),
200 FORKNAME(whichfork), da_cursor->ino);
e02ba985 201 libxfs_buf_relse(bp);
360f4a2e
ES
202 goto error_out;
203 }
204 }
205
8faa51a8
CH
206 da_cursor->level[i].hashval =
207 be32_to_cpu(nodehdr.btree[0].hashval);
360f4a2e
ES
208 da_cursor->level[i].bp = bp;
209 da_cursor->level[i].bno = bno;
210 da_cursor->level[i].index = 0;
211
212 /*
213 * set up new bno for next level down
214 */
8faa51a8 215 bno = be32_to_cpu(nodehdr.btree[0].before);
360f4a2e
ES
216 } while (node != NULL && i > 1);
217
218 /*
219 * now return block number and get out
220 */
221 *rbno = da_cursor->level[0].bno = bno;
222 return 1;
223
224error_out:
225 while (i > 1 && i <= da_cursor->active) {
e02ba985 226 libxfs_buf_relse(da_cursor->level[i].bp);
360f4a2e
ES
227 i++;
228 }
229
230 return 0;
231}
232
233/*
234 * blow out buffer for this level and all the rest above as well
235 * if error == 0, we are not expecting to encounter any unreleased
236 * buffers (e.g. if we do, it's a mistake). if error == 1, we're
237 * in an error-handling case so unreleased buffers may exist.
238 */
239static void
240release_da_cursor_int(
241 xfs_mount_t *mp,
242 da_bt_cursor_t *cursor,
243 int prev_level,
244 int error)
245{
246 int level = prev_level + 1;
247
248 if (cursor->level[level].bp != NULL) {
249 if (!error) {
250 do_warn(_("release_da_cursor_int got unexpected "
251 "non-null bp, dabno = %u\n"),
252 cursor->level[level].bno);
253 }
254 ASSERT(error != 0);
255
e02ba985 256 libxfs_buf_relse(cursor->level[level].bp);
360f4a2e
ES
257 cursor->level[level].bp = NULL;
258 }
259
260 if (level < cursor->active)
261 release_da_cursor_int(mp, cursor, level, error);
262
263 return;
264}
265
266void
267release_da_cursor(
268 xfs_mount_t *mp,
269 da_bt_cursor_t *cursor,
270 int prev_level)
271{
272 release_da_cursor_int(mp, cursor, prev_level, 0);
273}
274
275void
276err_release_da_cursor(
277 xfs_mount_t *mp,
278 da_bt_cursor_t *cursor,
279 int prev_level)
280{
281 release_da_cursor_int(mp, cursor, prev_level, 1);
282}
283
284/*
285 * make sure that all entries in all blocks along the right side of
286 * of the tree are used and hashval's are consistent. level is the
287 * level of the descendent block. returns 0 if good (even if it had
288 * to be fixed up), and 1 if bad. The right edge of the tree is
289 * technically a block boundary. This routine should be used then
290 * instead of verify_da_path().
291 */
292int
293verify_final_da_path(
294 xfs_mount_t *mp,
295 da_bt_cursor_t *cursor,
5cd3b070
ES
296 const int p_level,
297 int whichfork)
360f4a2e
ES
298{
299 xfs_da_intnode_t *node;
300 xfs_dahash_t hashval;
301 int bad = 0;
302 int entry;
303 int this_level = p_level + 1;
360f4a2e
ES
304 struct xfs_da3_icnode_hdr nodehdr;
305
306#ifdef XR_DIR_TRACE
307 fprintf(stderr, "in verify_final_da_path, this_level = %d\n",
308 this_level);
309#endif
310
311 /*
312 * the index should point to the next "unprocessed" entry
313 * in the block which should be the final (rightmost) entry
314 */
315 entry = cursor->level[this_level].index;
316 node = cursor->level[this_level].bp->b_addr;
08c16786 317 libxfs_da3_node_hdr_from_disk(mp, &nodehdr, node);
360f4a2e
ES
318
319 /*
320 * check internal block consistency on this level -- ensure
321 * that all entries are used, encountered and expected hashvals
322 * match, etc.
323 */
324 if (entry != nodehdr.count - 1) {
325 do_warn(
5cd3b070
ES
326_("%s block used/count inconsistency - %d/%hu\n"),
327 FORKNAME(whichfork), entry, nodehdr.count);
360f4a2e
ES
328 bad++;
329 }
330 /*
331 * hash values monotonically increasing ???
332 */
b7b81f33 333 if (cursor->level[this_level].hashval >
8faa51a8 334 be32_to_cpu(nodehdr.btree[entry].hashval)) {
5cd3b070
ES
335 do_warn(
336_("%s block hashvalue inconsistency, expected > %u / saw %u\n"),
337 FORKNAME(whichfork),
360f4a2e 338 cursor->level[this_level].hashval,
8faa51a8 339 be32_to_cpu(nodehdr.btree[entry].hashval));
360f4a2e
ES
340 bad++;
341 }
342 if (nodehdr.forw != 0) {
5cd3b070
ES
343 do_warn(
344_("bad %s forward block pointer, expected 0, saw %u\n"),
345 FORKNAME(whichfork), nodehdr.forw);
360f4a2e
ES
346 bad++;
347 }
348 if (bad) {
5cd3b070
ES
349 do_warn(_("bad %s block in inode %" PRIu64 "\n"),
350 FORKNAME(whichfork), cursor->ino);
360f4a2e
ES
351 return 1;
352 }
353 /*
354 * keep track of greatest block # -- that gets
f8149110 355 * us the length of the directory/attribute
360f4a2e
ES
356 */
357 if (cursor->level[this_level].bno > cursor->greatest_bno)
358 cursor->greatest_bno = cursor->level[this_level].bno;
359
360 /*
361 * ok, now check descendant block number against this level
362 */
8faa51a8
CH
363 if (cursor->level[p_level].bno !=
364 be32_to_cpu(nodehdr.btree[entry].before)) {
360f4a2e 365#ifdef XR_DIR_TRACE
5cd3b070 366 fprintf(stderr, "bad %s btree pointer, child bno should "
360f4a2e 367 "be %d, block bno is %d, hashval is %u\n",
8faa51a8
CH
368 FORKNAME(whichfork),
369 be16_to_cpu(nodehdr.btree[entry].before),
360f4a2e
ES
370 cursor->level[p_level].bno,
371 cursor->level[p_level].hashval);
372 fprintf(stderr, "verify_final_da_path returns 1 (bad) #1a\n");
373#endif
374 return 1;
375 }
376
377 if (cursor->level[p_level].hashval !=
8faa51a8 378 be32_to_cpu(nodehdr.btree[entry].hashval)) {
360f4a2e
ES
379 if (!no_modify) {
380 do_warn(
5cd3b070 381_("correcting bad hashval in non-leaf %s block\n"
360f4a2e 382 "\tin (level %d) in inode %" PRIu64 ".\n"),
5cd3b070 383 FORKNAME(whichfork), this_level, cursor->ino);
8faa51a8 384 nodehdr.btree[entry].hashval = cpu_to_be32(
360f4a2e
ES
385 cursor->level[p_level].hashval);
386 cursor->level[this_level].dirty++;
387 } else {
388 do_warn(
5cd3b070 389_("would correct bad hashval in non-leaf %s block\n"
360f4a2e 390 "\tin (level %d) in inode %" PRIu64 ".\n"),
5cd3b070 391 FORKNAME(whichfork), this_level, cursor->ino);
360f4a2e
ES
392 }
393 }
394
395 /*
396 * Note: squirrel hashval away _before_ releasing the
397 * buffer, preventing a use-after-free problem.
398 */
8faa51a8 399 hashval = be32_to_cpu(nodehdr.btree[entry].hashval);
360f4a2e
ES
400
401 /*
402 * release/write buffer
403 */
404 ASSERT(cursor->level[this_level].dirty == 0 ||
405 (cursor->level[this_level].dirty && !no_modify));
406
18b4f688 407 if (cursor->level[this_level].dirty && !no_modify) {
f524ae04 408 libxfs_buf_mark_dirty(cursor->level[this_level].bp);
18b4f688
DW
409 libxfs_buf_relse(cursor->level[this_level].bp);
410 }
360f4a2e 411 else
e02ba985 412 libxfs_buf_relse(cursor->level[this_level].bp);
360f4a2e
ES
413
414 cursor->level[this_level].bp = NULL;
415
416 /*
417 * bail out if this is the root block (top of tree)
418 */
419 if (this_level >= cursor->active) {
420#ifdef XR_DIR_TRACE
421 fprintf(stderr, "verify_final_da_path returns 0 (ok)\n");
422#endif
423 return 0;
424 }
425 /*
426 * set hashvalue to correctly reflect the now-validated
427 * last entry in this block and continue upwards validation
428 */
429 cursor->level[this_level].hashval = hashval;
430
5cd3b070 431 return verify_final_da_path(mp, cursor, this_level, whichfork);
360f4a2e
ES
432}
433
434/*
435 * Verifies the path from a descendant block up to the root.
436 * Should be called when the descendant level traversal hits
437 * a block boundary before crossing the boundary (reading in a new
438 * block).
439 *
440 * the directory/attr btrees work differently to the other fs btrees.
441 * each interior block contains records that are <hashval, bno>
442 * pairs. The bno is a file bno, not a filesystem bno. The last
443 * hashvalue in the block <bno> will be <hashval>. BUT unlike
444 * the freespace btrees, the *last* value in each block gets
445 * propagated up the tree instead of the first value in each block.
446 * that is, the interior records point to child blocks and the *greatest*
447 * hash value contained by the child block is the one the block above
448 * uses as the key for the child block.
449 *
450 * level is the level of the descendent block. returns 0 if good,
451 * and 1 if bad. The descendant block may be a leaf block.
452 *
453 * the invariant here is that the values in the cursor for the
454 * levels beneath this level (this_level) and the cursor index
455 * for this level *must* be valid.
456 *
457 * that is, the hashval/bno info is accurate for all
458 * DESCENDANTS and match what the node[index] information
459 * for the current index in the cursor for this level.
460 *
461 * the index values in the cursor for the descendant level
462 * are allowed to be off by one as they will reflect the
463 * next entry at those levels to be processed.
464 *
465 * the hashvalue for the current level can't be set until
466 * we hit the last entry in the block so, it's garbage
467 * until set by this routine.
468 *
469 * bno and bp for the current block/level are always valid
470 * since they have to be set so we can get a buffer for the
471 * block.
472 */
473int
474verify_da_path(
475 xfs_mount_t *mp,
476 da_bt_cursor_t *cursor,
477 const int p_level,
478 int whichfork)
479{
480 xfs_da_intnode_t *node;
481 xfs_da_intnode_t *newnode;
482 xfs_dablk_t dabno;
483 struct xfs_buf *bp;
484 int bad;
485 int entry;
486 int this_level = p_level + 1;
487 bmap_ext_t *bmp;
488 int nex;
489 bmap_ext_t lbmp;
490 struct xfs_da_geometry *geo;
360f4a2e
ES
491 struct xfs_da3_icnode_hdr nodehdr;
492
493 if (whichfork == XFS_DATA_FORK)
494 geo = mp->m_dir_geo;
495 else
496 geo = mp->m_attr_geo;
497
3cc93dda
DW
498 /* No buffer at this level, tree is corrupt. */
499 if (cursor->level[this_level].bp == NULL)
500 return 1;
501
360f4a2e
ES
502 /*
503 * index is currently set to point to the entry that
504 * should be processed now in this level.
505 */
506 entry = cursor->level[this_level].index;
507 node = cursor->level[this_level].bp->b_addr;
08c16786 508 libxfs_da3_node_hdr_from_disk(mp, &nodehdr, node);
360f4a2e 509
3cc93dda
DW
510 /* No entries in this node? Tree is corrupt. */
511 if (nodehdr.count == 0)
512 return 1;
513
360f4a2e
ES
514 /*
515 * if this block is out of entries, validate this
516 * block and move on to the next block.
517 * and update cursor value for said level
518 */
519 if (entry >= nodehdr.count) {
520 /*
521 * update the hash value for this level before
522 * validating it. bno value should be ok since
523 * it was set when the block was first read in.
524 */
525 cursor->level[this_level].hashval =
8faa51a8 526 be32_to_cpu(nodehdr.btree[entry - 1].hashval);
360f4a2e
ES
527
528 /*
529 * keep track of greatest block # -- that gets
530 * us the length of the directory
531 */
532 if (cursor->level[this_level].bno > cursor->greatest_bno)
533 cursor->greatest_bno = cursor->level[this_level].bno;
534
535 /*
536 * validate the path for the current used-up block
537 * before we trash it
538 */
539 if (verify_da_path(mp, cursor, this_level, whichfork))
540 return 1;
541 /*
542 * ok, now get the next buffer and check sibling pointers
543 */
544 dabno = nodehdr.forw;
545 ASSERT(dabno != 0);
546 nex = blkmap_getn(cursor->blkmap, dabno, geo->fsbcount,
547 &bmp, &lbmp);
548 if (nex == 0) {
549 do_warn(
5cd3b070
ES
550_("can't get map info for %s block %u of inode %" PRIu64 "\n"),
551 FORKNAME(whichfork), dabno, cursor->ino);
360f4a2e
ES
552 return 1;
553 }
554
555 bp = da_read_buf(mp, nex, bmp, &xfs_da3_node_buf_ops);
556 if (bmp != &lbmp)
557 free(bmp);
558
559 if (!bp) {
560 do_warn(
5cd3b070
ES
561_("can't read %s block %u for inode %" PRIu64 "\n"),
562 FORKNAME(whichfork), dabno, cursor->ino);
360f4a2e
ES
563 return 1;
564 }
be752639
DW
565 if (bp->b_error == -EFSCORRUPTED || bp->b_error == -EFSBADCRC) {
566 do_warn(
567_("corrupt %s tree block %u for inode %" PRIu64 "\n"),
568 FORKNAME(whichfork), dabno, cursor->ino);
569 libxfs_buf_relse(bp);
570 return 1;
571 }
360f4a2e
ES
572
573 newnode = bp->b_addr;
08c16786 574 libxfs_da3_node_hdr_from_disk(mp, &nodehdr, newnode);
360f4a2e
ES
575
576 /*
577 * verify magic number and back pointer, sanity-check
578 * entry count, verify level
579 */
580 bad = 0;
581 if (nodehdr.magic != XFS_DA_NODE_MAGIC &&
582 nodehdr.magic != XFS_DA3_NODE_MAGIC) {
583 do_warn(
5cd3b070
ES
584_("bad magic number %x in %s block %u for inode %" PRIu64 "\n"),
585 nodehdr.magic, FORKNAME(whichfork),
360f4a2e
ES
586 dabno, cursor->ino);
587 bad++;
588 }
589 if (nodehdr.back != cursor->level[this_level].bno) {
590 do_warn(
5cd3b070
ES
591_("bad back pointer in %s block %u for inode %" PRIu64 "\n"),
592 FORKNAME(whichfork), dabno, cursor->ino);
360f4a2e
ES
593 bad++;
594 }
595 if (nodehdr.count > geo->node_ents) {
596 do_warn(
5cd3b070
ES
597_("entry count %d too large in %s block %u for inode %" PRIu64 "\n"),
598 nodehdr.count, FORKNAME(whichfork),
360f4a2e
ES
599 dabno, cursor->ino);
600 bad++;
601 }
602 if (nodehdr.level != this_level) {
603 do_warn(
5cd3b070
ES
604_("bad level %d in %s block %u for inode %" PRIu64 "\n"),
605 nodehdr.level, FORKNAME(whichfork),
360f4a2e
ES
606 dabno, cursor->ino);
607 bad++;
608 }
609 if (bad) {
610#ifdef XR_DIR_TRACE
611 fprintf(stderr, "verify_da_path returns 1 (bad) #4\n");
612#endif
e02ba985 613 libxfs_buf_relse(bp);
360f4a2e
ES
614 return 1;
615 }
616
617 /*
618 * update cursor, write out the *current* level if
619 * required. don't write out the descendant level
620 */
621 ASSERT(cursor->level[this_level].dirty == 0 ||
622 (cursor->level[this_level].dirty && !no_modify));
623
624 /*
625 * If block looks ok but CRC didn't match, make sure to
626 * recompute it.
627 */
628 if (!no_modify &&
629 cursor->level[this_level].bp->b_error == -EFSBADCRC)
630 cursor->level[this_level].dirty = 1;
631
18b4f688 632 if (cursor->level[this_level].dirty && !no_modify) {
f524ae04 633 libxfs_buf_mark_dirty(cursor->level[this_level].bp);
18b4f688
DW
634 libxfs_buf_relse(cursor->level[this_level].bp);
635 }
360f4a2e 636 else
e02ba985 637 libxfs_buf_relse(cursor->level[this_level].bp);
360f4a2e
ES
638
639 /* switch cursor to point at the new buffer we just read */
640 cursor->level[this_level].bp = bp;
641 cursor->level[this_level].dirty = 0;
642 cursor->level[this_level].bno = dabno;
643 cursor->level[this_level].hashval =
8faa51a8 644 be32_to_cpu(nodehdr.btree[0].hashval);
360f4a2e
ES
645
646 entry = cursor->level[this_level].index = 0;
647 }
648 /*
649 * ditto for block numbers
650 */
8faa51a8
CH
651 if (cursor->level[p_level].bno !=
652 be32_to_cpu(nodehdr.btree[entry].before)) {
360f4a2e 653#ifdef XR_DIR_TRACE
5cd3b070 654 fprintf(stderr, "bad %s btree pointer, child bno "
360f4a2e 655 "should be %d, block bno is %d, hashval is %u\n",
8faa51a8
CH
656 FORKNAME(whichfork),
657 be32_to_cpu(nodehdr.btree[entry].before),
360f4a2e
ES
658 cursor->level[p_level].bno,
659 cursor->level[p_level].hashval);
660 fprintf(stderr, "verify_da_path returns 1 (bad) #1a\n");
661#endif
662 return 1;
663 }
664 /*
665 * ok, now validate last hashvalue in the descendant
666 * block against the hashval in the current entry
667 */
668 if (cursor->level[p_level].hashval !=
8faa51a8 669 be32_to_cpu(nodehdr.btree[entry].hashval)) {
360f4a2e
ES
670 if (!no_modify) {
671 do_warn(
5cd3b070 672_("correcting bad hashval in interior %s block\n"
360f4a2e 673 "\tin (level %d) in inode %" PRIu64 ".\n"),
5cd3b070 674 FORKNAME(whichfork), this_level, cursor->ino);
8faa51a8 675 nodehdr.btree[entry].hashval = cpu_to_be32(
360f4a2e
ES
676 cursor->level[p_level].hashval);
677 cursor->level[this_level].dirty++;
678 } else {
679 do_warn(
5cd3b070 680_("would correct bad hashval in interior %s block\n"
360f4a2e 681 "\tin (level %d) in inode %" PRIu64 ".\n"),
5cd3b070 682 FORKNAME(whichfork), this_level, cursor->ino);
360f4a2e
ES
683 }
684 }
685 /*
686 * increment index for this level to point to next entry
687 * (which should point to the next descendant block)
688 */
689 cursor->level[this_level].index++;
690#ifdef XR_DIR_TRACE
691 fprintf(stderr, "verify_da_path returns 0 (ok)\n");
692#endif
693 return 0;
694}