]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - repair/dir2.c
xfs_repair: fix indentation problems in upgrade_filesystem
[thirdparty/xfsprogs-dev.git] / repair / dir2.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0
2bd0ea18 2/*
da23017d
NS
3 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
2bd0ea18
NS
5 */
6
6b803e5a 7#include "libxfs.h"
2bd0ea18
NS
8#include "avl.h"
9#include "globals.h"
10#include "incore.h"
11#include "err_protos.h"
12#include "dinode.h"
2bd0ea18
NS
13#include "dir2.h"
14#include "bmap.h"
360f4a2e 15#include "da_util.h"
cb5b3ef4 16#include "prefetch.h"
2556c98b 17#include "progress.h"
2bd0ea18 18
2bd0ea18
NS
19/*
20 * Known bad inode list. These are seen when the leaf and node
21 * block linkages are incorrect.
22 */
fdfd70e7 23struct dir2_bad {
2bd0ea18
NS
24 xfs_ino_t ino;
25 struct dir2_bad *next;
fdfd70e7 26};
2bd0ea18 27
fdfd70e7
DC
28static struct dir2_bad *dir2_bad_list;
29pthread_mutex_t dir2_bad_list_lock = PTHREAD_MUTEX_INITIALIZER;
8b8a6b02
CH
30
31static void
2bd0ea18
NS
32dir2_add_badlist(
33 xfs_ino_t ino)
34{
fdfd70e7 35 struct dir2_bad *l;
2bd0ea18 36
fdfd70e7
DC
37 l = malloc(sizeof(*l));
38 if (!l) {
507f4e33 39 do_error(
5d1b7f0f 40_("malloc failed (%zu bytes) dir2_add_badlist:ino %" PRIu64 "\n"),
fdfd70e7 41 sizeof(*l), ino);
2bd0ea18
NS
42 exit(1);
43 }
fdfd70e7 44 pthread_mutex_lock(&dir2_bad_list_lock);
2bd0ea18
NS
45 l->next = dir2_bad_list;
46 dir2_bad_list = l;
47 l->ino = ino;
fdfd70e7 48 pthread_mutex_unlock(&dir2_bad_list_lock);
2bd0ea18
NS
49}
50
fdfd70e7 51bool
2bd0ea18
NS
52dir2_is_badino(
53 xfs_ino_t ino)
54{
fdfd70e7
DC
55 struct dir2_bad *l;
56 bool ret = false;
2bd0ea18 57
fdfd70e7
DC
58 pthread_mutex_lock(&dir2_bad_list_lock);
59 for (l = dir2_bad_list; l; l = l->next) {
60 if (l->ino == ino) {
61 ret = true;
62 break;
63 }
64 }
65 pthread_mutex_unlock(&dir2_bad_list_lock);
66 return ret;
2bd0ea18
NS
67}
68
2bd0ea18
NS
69/*
70 * Fix up a shortform directory which was in long form (i8count set)
71 * and is now in short form (i8count clear).
72 * Return pointer to the end of the data when done.
73 */
74void
75process_sf_dir2_fixi8(
494434d7 76 struct xfs_mount *mp,
a354abc8 77 struct xfs_dir2_sf_hdr *sfp,
2bd0ea18
NS
78 xfs_dir2_sf_entry_t **next_sfep)
79{
80 xfs_ino_t ino;
a354abc8 81 struct xfs_dir2_sf_hdr *newsfp;
2bd0ea18 82 xfs_dir2_sf_entry_t *newsfep;
a354abc8 83 struct xfs_dir2_sf_hdr *oldsfp;
2bd0ea18
NS
84 xfs_dir2_sf_entry_t *oldsfep;
85 int oldsize;
86
87 newsfp = sfp;
ee6cd73e 88 oldsize = (intptr_t)*next_sfep - (intptr_t)sfp;
2bd0ea18
NS
89 oldsfp = malloc(oldsize);
90 if (oldsfp == NULL) {
507f4e33 91 do_error(_("couldn't malloc dir2 shortform copy\n"));
2bd0ea18
NS
92 exit(1);
93 }
94 memmove(oldsfp, newsfp, oldsize);
a354abc8
DC
95 newsfp->count = oldsfp->count;
96 newsfp->i8count = 0;
c29a562f 97 ino = libxfs_dir2_sf_get_parent_ino(oldsfp);
8a7190bd 98 libxfs_dir2_sf_put_parent_ino(newsfp, ino);
a354abc8
DC
99 oldsfep = xfs_dir2_sf_firstentry(oldsfp);
100 newsfep = xfs_dir2_sf_firstentry(newsfp);
2bd0ea18
NS
101 while ((int)((char *)oldsfep - (char *)oldsfp) < oldsize) {
102 newsfep->namelen = oldsfep->namelen;
5e656dbb
BN
103 xfs_dir2_sf_put_offset(newsfep,
104 xfs_dir2_sf_get_offset(oldsfep));
2bd0ea18 105 memmove(newsfep->name, oldsfep->name, newsfep->namelen);
e96bd2d3
CH
106 ino = libxfs_dir2_sf_get_ino(mp, oldsfp, oldsfep);
107 libxfs_dir2_sf_put_ino(mp, newsfp, newsfep, ino);
660836c9
CH
108 oldsfep = libxfs_dir2_sf_nextentry(mp, oldsfp, oldsfep);
109 newsfep = libxfs_dir2_sf_nextentry(mp, newsfp, newsfep);
2bd0ea18
NS
110 }
111 *next_sfep = newsfep;
112 free(oldsfp);
113}
114
115/*
116 * Regenerate legal (minimal) offsets for the shortform directory.
117 */
118static void
119process_sf_dir2_fixoff(
584f90b0 120 xfs_mount_t *mp,
2bd0ea18
NS
121 xfs_dinode_t *dip)
122{
123 int i;
124 int offset;
125 xfs_dir2_sf_entry_t *sfep;
a354abc8 126 struct xfs_dir2_sf_hdr *sfp;
2bd0ea18 127
a354abc8
DC
128 sfp = (struct xfs_dir2_sf_hdr *)XFS_DFORK_DPTR(dip);
129 sfep = xfs_dir2_sf_firstentry(sfp);
58a1d356 130 offset = mp->m_dir_geo->data_first_offset;
5e656dbb 131
a354abc8 132 for (i = 0; i < sfp->count; i++) {
5e656dbb 133 xfs_dir2_sf_put_offset(sfep, offset);
271a654f 134 offset += libxfs_dir2_data_entsize(mp, sfep->namelen);
660836c9 135 sfep = libxfs_dir2_sf_nextentry(mp, sfp, sfep);
2bd0ea18
NS
136 }
137}
138
139/*
140 * this routine performs inode discovery and tries to fix things
141 * in place. available redundancy -- inode data size should match
142 * used directory space in inode.
143 * a non-zero return value means the directory is bogus and should be blasted.
144 */
145/* ARGSUSED */
146static int
147process_sf_dir2(
148 xfs_mount_t *mp,
149 xfs_ino_t ino,
150 xfs_dinode_t *dip,
151 int ino_discovery,
152 int *dino_dirty, /* out - 1 if dinode buffer dirty */
153 char *dirname, /* directory pathname */
154 xfs_ino_t *parent, /* out - NULLFSINO if entry not exist */
155 int *repair) /* out - 1 if dir was fixed up */
156{
157 int bad_offset;
158 int bad_sfnamelen;
159 int i;
160 int i8;
14f8b681 161 int64_t ino_dir_size;
2bd0ea18
NS
162 int ino_off;
163 ino_tree_node_t *irec_p;
164 int junkit;
165 char *junkreason = NULL;
166 xfs_ino_t lino;
167 int max_size;
168 char name[MAXNAMELEN + 1];
169 int namelen;
170 xfs_dir2_sf_entry_t *next_sfep;
171 int num_entries;
172 int offset;
a354abc8 173 struct xfs_dir2_sf_hdr *sfp;
2bd0ea18
NS
174 xfs_dir2_sf_entry_t *sfep;
175 int tmp_elen;
176 int tmp_len;
177 xfs_dir2_sf_entry_t *tmp_sfep;
2bd0ea18 178
a354abc8 179 sfp = (struct xfs_dir2_sf_hdr *)XFS_DFORK_DPTR(dip);
46eca962 180 max_size = XFS_DFORK_DSIZE(dip, mp);
a354abc8 181 num_entries = sfp->count;
56b2de80 182 ino_dir_size = be64_to_cpu(dip->di_size);
58a1d356 183 offset = mp->m_dir_geo->data_first_offset;
e55d768a 184 bad_offset = *repair = 0;
2bd0ea18
NS
185
186 ASSERT(ino_dir_size <= max_size);
187
e55d768a
NS
188 /*
189 * Initialize i8 based on size of parent inode number.
190 */
8a7190bd 191 i8 = (libxfs_dir2_sf_get_parent_ino(sfp) > XFS_DIR2_MAX_SHORT_INUM);
e55d768a 192
dfc130f3 193 /*
2bd0ea18
NS
194 * check for bad entry count
195 */
660836c9 196 if (num_entries * libxfs_dir2_sf_entsize(mp, sfp, 1) +
5e656dbb 197 xfs_dir2_sf_hdr_size(0) > max_size || num_entries == 0)
2bd0ea18
NS
198 num_entries = 0xFF;
199
200 /*
201 * run through entries, stop at first bad entry, don't need
202 * to check for .. since that's encoded in its own field
203 */
d0bbcbcb 204 next_sfep = xfs_dir2_sf_firstentry(sfp);
2bd0ea18
NS
205 for (i = 0;
206 i < num_entries && ino_dir_size > (char *)next_sfep - (char *)sfp;
207 i++) {
208 tmp_sfep = NULL;
209 sfep = next_sfep;
210 junkit = 0;
211 bad_sfnamelen = 0;
e96bd2d3 212 lino = libxfs_dir2_sf_get_ino(mp, sfp, sfep);
2bd0ea18
NS
213 /*
214 * if entry points to self, junk it since only '.' or '..'
215 * should do that and shortform dirs don't contain either
216 * entry. if inode number is invalid, trash entry.
217 * if entry points to special inodes, trash it.
218 * if inode is unknown but number is valid,
219 * add it to the list of uncertain inodes. don't
220 * have to worry about an entry pointing to a
221 * deleted lost+found inode because the entry was
222 * deleted at the same time that the inode was cleared.
223 */
224 if (lino == ino) {
225 junkit = 1;
507f4e33 226 junkreason = _("current");
017e979e 227 } else if (!libxfs_verify_dir_ino(mp, lino)) {
2bd0ea18 228 junkit = 1;
507f4e33 229 junkreason = _("invalid");
2bd0ea18
NS
230 } else if (lino == mp->m_sb.sb_rbmino) {
231 junkit = 1;
507f4e33 232 junkreason = _("realtime bitmap");
2bd0ea18
NS
233 } else if (lino == mp->m_sb.sb_rsumino) {
234 junkit = 1;
507f4e33 235 junkreason = _("realtime summary");
2bd0ea18
NS
236 } else if (lino == mp->m_sb.sb_uquotino) {
237 junkit = 1;
507f4e33 238 junkreason = _("user quota");
b36eef04 239 } else if (lino == mp->m_sb.sb_gquotino) {
2bd0ea18 240 junkit = 1;
507f4e33 241 junkreason = _("group quota");
0340d706
CS
242 } else if (lino == mp->m_sb.sb_pquotino) {
243 junkit = 1;
244 junkreason = _("project quota");
1ae311d5
LC
245 } else if ((irec_p = find_inode_rec(mp,
246 XFS_INO_TO_AGNO(mp, lino),
2bd0ea18
NS
247 XFS_INO_TO_AGINO(mp, lino))) != NULL) {
248 /*
249 * if inode is marked free and we're in inode
250 * discovery mode, leave the entry alone for now.
251 * if the inode turns out to be used, we'll figure
252 * that out when we scan it. If the inode really
253 * is free, we'll hit this code again in phase 4
254 * after we've finished inode discovery and blow
255 * out the entry then.
256 */
257 ino_off = XFS_INO_TO_AGINO(mp, lino) -
258 irec_p->ino_startnum;
259 ASSERT(is_inode_confirmed(irec_p, ino_off));
260 if (is_inode_free(irec_p, ino_off) && !ino_discovery) {
261 junkit = 1;
507f4e33 262 junkreason = _("free");
2bd0ea18
NS
263 }
264 } else if (ino_discovery) {
265 /*
266 * put the inode on the uncertain list. we'll
267 * pull the inode off the list and check it later.
268 * if the inode turns out be bogus, we'll delete
269 * this entry in phase 6.
270 */
271 add_inode_uncertain(mp, lino, 0);
272 } else {
273 /*
274 * blow the entry out. we know about all
275 * undiscovered entries now (past inode discovery
276 * phase) so this is clearly a bogus entry.
277 */
278 junkit = 1;
507f4e33 279 junkreason = _("non-existent");
2bd0ea18
NS
280 }
281 namelen = sfep->namelen;
282 if (junkit)
5d1b7f0f
CH
283 do_warn(
284_("entry \"%*.*s\" in shortform directory %" PRIu64 " references %s inode %" PRIu64 "\n"),
2bd0ea18
NS
285 namelen, namelen, sfep->name, ino, junkreason,
286 lino);
1c934a25
ES
287
288 /* is dir namelen 0 or does this entry extend past dir size? */
289 if (namelen == 0) {
290 junkreason = _("is zero length");
2bd0ea18 291 bad_sfnamelen = 1;
ee6cd73e 292 } else if ((intptr_t) sfep - (intptr_t) sfp +
660836c9 293 libxfs_dir2_sf_entsize(mp, sfp, sfep->namelen)
1c934a25
ES
294 > ino_dir_size) {
295 junkreason = _("extends past end of dir");
296 bad_sfnamelen = 1;
297 }
2bd0ea18 298
1c934a25 299 if (bad_sfnamelen) {
38c66abc
ES
300 do_warn(
301_("entry #%d %s in shortform dir %" PRIu64),
302 i, junkreason, ino);
303 if (!no_modify)
304 do_warn(_(", junking %d entries\n"),
305 num_entries - i);
306 else
307 do_warn(_(", would junk %d entries\n"),
308 num_entries - i);
1c934a25 309 /*
38c66abc
ES
310 * don't process the rest of the directory,
311 * break out of processing loop
1c934a25 312 */
38c66abc 313 break;
2bd0ea18
NS
314 }
315
316 /*
317 * check for illegal chars in name.
318 * no need to check for bad length because
319 * the length value is stored in a byte
320 * so it can't be too big, it can only wrap
321 */
b8aa6f27 322 if (!libxfs_dir2_namecheck(sfep->name, namelen)) {
2bd0ea18
NS
323 /*
324 * junk entry
325 */
5d1b7f0f
CH
326 do_warn(
327_("entry contains illegal character in shortform dir %" PRIu64 "\n"),
2bd0ea18
NS
328 ino);
329 junkit = 1;
330 }
331
5e656dbb 332 if (xfs_dir2_sf_get_offset(sfep) < offset) {
5d1b7f0f
CH
333 do_warn(
334_("entry contains offset out of order in shortform dir %" PRIu64 "\n"),
2bd0ea18
NS
335 ino);
336 bad_offset = 1;
337 }
5e656dbb 338 offset = xfs_dir2_sf_get_offset(sfep) +
271a654f 339 libxfs_dir2_data_entsize(mp, namelen);
2bd0ea18
NS
340
341 /*
342 * junk the entry by copying up the rest of the
343 * fork over the current entry and decrementing
344 * the entry count. if we're in no_modify mode,
345 * just issue the warning instead. then continue
346 * the loop with the next_sfep pointer set to the
347 * correct place in the fork and other counters
348 * properly set to reflect the deletion if it
349 * happened.
350 */
351 if (junkit) {
dab9b8d6 352 memmove(name, sfep->name, namelen);
2bd0ea18
NS
353 name[namelen] = '\0';
354
355 if (!no_modify) {
660836c9 356 tmp_elen = libxfs_dir2_sf_entsize(mp, sfp,
a2ceac1f 357 sfep->namelen);
56b2de80 358 be64_add_cpu(&dip->di_size, -tmp_elen);
2bd0ea18
NS
359 ino_dir_size -= tmp_elen;
360
361 tmp_sfep = (xfs_dir2_sf_entry_t *)
ee6cd73e
CH
362 ((intptr_t) sfep + tmp_elen);
363 tmp_len = max_size - ((intptr_t) tmp_sfep
364 - (intptr_t) sfp);
2bd0ea18
NS
365
366 memmove(sfep, tmp_sfep, tmp_len);
367
a354abc8 368 sfp->count -= 1;
2bd0ea18 369 num_entries--;
ee6cd73e 370 memset((void *) ((intptr_t) sfep + tmp_len), 0,
2bd0ea18
NS
371 tmp_elen);
372
373 /*
374 * reset the tmp value to the current
375 * pointer so we'll process the entry
376 * we just moved up
377 */
378 tmp_sfep = sfep;
379
380 /*
381 * WARNING: drop the index i by one
382 * so it matches the decremented count
383 * for accurate comparisons later
384 */
385 i--;
386
387 *dino_dirty = 1;
388 *repair = 1;
389
5d1b7f0f
CH
390 do_warn(
391_("junking entry \"%s\" in directory inode %" PRIu64 "\n"),
2bd0ea18
NS
392 name, ino);
393 } else {
5d1b7f0f
CH
394 do_warn(
395_("would have junked entry \"%s\" in directory inode %" PRIu64 "\n"),
2bd0ea18
NS
396 name, ino);
397 }
398 } else if (lino > XFS_DIR2_MAX_SHORT_INUM)
399 i8++;
400 /*
401 * go onto next entry unless we've just junked an
402 * entry in which the current entry pointer points
403 * to an unprocessed entry. have to take into zero-len
404 * entries into account in no modify mode since we
405 * calculate size based on next_sfep.
406 */
407 next_sfep = (tmp_sfep == NULL)
ee6cd73e 408 ? (xfs_dir2_sf_entry_t *) ((intptr_t) sfep
a2ceac1f 409 + ((!bad_sfnamelen)
660836c9
CH
410 ? libxfs_dir2_sf_entsize(mp, sfp, sfep->namelen)
411 : libxfs_dir2_sf_entsize(mp, sfp, namelen)))
2bd0ea18
NS
412 : tmp_sfep;
413 }
414
415 /* sync up sizes and entry counts */
416
a354abc8 417 if (sfp->count != i) {
2bd0ea18 418 if (no_modify) {
5d1b7f0f
CH
419 do_warn(
420_("would have corrected entry count in directory %" PRIu64 " from %d to %d\n"),
a354abc8 421 ino, sfp->count, i);
2bd0ea18 422 } else {
5d1b7f0f 423 do_warn(
b52923f3 424_("corrected entry count in directory %" PRIu64 ", was %d, now %d\n"),
a354abc8
DC
425 ino, sfp->count, i);
426 sfp->count = i;
2bd0ea18
NS
427 *dino_dirty = 1;
428 *repair = 1;
429 }
430 }
431
a354abc8 432 if (sfp->i8count != i8) {
2bd0ea18 433 if (no_modify) {
5d1b7f0f
CH
434 do_warn(
435_("would have corrected i8 count in directory %" PRIu64 " from %d to %d\n"),
a354abc8 436 ino, sfp->i8count, i8);
2bd0ea18 437 } else {
5d1b7f0f
CH
438 do_warn(
439_("corrected i8 count in directory %" PRIu64 ", was %d, now %d\n"),
a354abc8 440 ino, sfp->i8count, i8);
2bd0ea18 441 if (i8 == 0)
494434d7 442 process_sf_dir2_fixi8(mp, sfp, &next_sfep);
2bd0ea18 443 else
a354abc8 444 sfp->i8count = i8;
2bd0ea18
NS
445 *dino_dirty = 1;
446 *repair = 1;
447 }
448 }
449
5d1b7f0f 450 if ((intptr_t)next_sfep - (intptr_t)sfp != ino_dir_size) {
2bd0ea18 451 if (no_modify) {
5d1b7f0f
CH
452 do_warn(
453_("would have corrected directory %" PRIu64 " size from %" PRId64 " to %" PRIdPTR "\n"),
454 ino, ino_dir_size,
455 (intptr_t)next_sfep - (intptr_t)sfp);
2bd0ea18 456 } else {
5d1b7f0f
CH
457 do_warn(
458_("corrected directory %" PRIu64 " size, was %" PRId64 ", now %" PRIdPTR "\n"),
459 ino, ino_dir_size,
460 (intptr_t)next_sfep - (intptr_t)sfp);
2bd0ea18 461
56b2de80 462 dip->di_size = cpu_to_be64(
ee6cd73e 463 (intptr_t)next_sfep - (intptr_t)sfp);
2bd0ea18
NS
464 *dino_dirty = 1;
465 *repair = 1;
466 }
467 }
a354abc8 468 if (offset + (sfp->count + 2) * sizeof(xfs_dir2_leaf_entry_t) +
ff105f75 469 sizeof(xfs_dir2_block_tail_t) > mp->m_dir_geo->blksize) {
5d1b7f0f 470 do_warn(_("directory %" PRIu64 " offsets too high\n"), ino);
2bd0ea18
NS
471 bad_offset = 1;
472 }
473 if (bad_offset) {
474 if (no_modify) {
5d1b7f0f
CH
475 do_warn(
476_("would have corrected entry offsets in directory %" PRIu64 "\n"),
2bd0ea18
NS
477 ino);
478 } else {
5d1b7f0f
CH
479 do_warn(
480_("corrected entry offsets in directory %" PRIu64 "\n"),
2bd0ea18 481 ino);
584f90b0 482 process_sf_dir2_fixoff(mp, dip);
2bd0ea18
NS
483 *dino_dirty = 1;
484 *repair = 1;
485 }
486 }
487
488 /*
489 * check parent (..) entry
490 */
8a7190bd 491 *parent = libxfs_dir2_sf_get_parent_ino(sfp);
1b0bfeb5
BF
492 /*
493 * If this function is called during inode discovery (phase 3), it will
494 * set a bad sf dir parent pointer to the root directory. This fixes
495 * the directory enough to pass the inode fork verifier in phase 6 when
496 * we try to reset the parent pointer to the correct value. There is no
497 * need to re-check the parent pointer during phase 4.
498 */
499 if (!ino_discovery)
500 return 0;
2bd0ea18
NS
501
502 /*
503 * if parent entry is bogus, null it out. we'll fix it later .
77b3425e
MB
504 * If the validation fails for the root inode we fix it in
505 * the next else case.
2bd0ea18 506 */
017e979e 507 if (!libxfs_verify_dir_ino(mp, *parent) && ino != mp->m_sb.sb_rootino) {
5d1b7f0f
CH
508 do_warn(
509_("bogus .. inode number (%" PRIu64 ") in directory inode %" PRIu64 ", "),
2bd0ea18
NS
510 *parent, ino);
511 *parent = NULLFSINO;
512 if (!no_modify) {
507f4e33 513 do_warn(_("clearing inode number\n"));
2bd0ea18 514
993ca3ee 515 libxfs_dir2_sf_put_parent_ino(sfp, mp->m_sb.sb_rootino);
2bd0ea18
NS
516 *dino_dirty = 1;
517 *repair = 1;
518 } else {
507f4e33 519 do_warn(_("would clear inode number\n"));
2bd0ea18
NS
520 }
521 } else if (ino == mp->m_sb.sb_rootino && ino != *parent) {
522 /*
523 * root directories must have .. == .
524 */
525 if (!no_modify) {
5d1b7f0f
CH
526 do_warn(
527_("corrected root directory %" PRIu64 " .. entry, was %" PRIu64 ", now %" PRIu64 "\n"),
2bd0ea18
NS
528 ino, *parent, ino);
529 *parent = ino;
8a7190bd 530 libxfs_dir2_sf_put_parent_ino(sfp, ino);
2bd0ea18
NS
531 *dino_dirty = 1;
532 *repair = 1;
533 } else {
5d1b7f0f
CH
534 do_warn(
535_("would have corrected root directory %" PRIu64 " .. entry from %" PRIu64" to %" PRIu64 "\n"),
2bd0ea18
NS
536 ino, *parent, ino);
537 }
538 } else if (ino == *parent && ino != mp->m_sb.sb_rootino) {
539 /*
540 * likewise, non-root directories can't have .. pointing
541 * to .
542 */
543 *parent = NULLFSINO;
5d1b7f0f
CH
544 do_warn(
545_("bad .. entry in directory inode %" PRIu64 ", points to self, "),
2bd0ea18
NS
546 ino);
547 if (!no_modify) {
507f4e33 548 do_warn(_("clearing inode number\n"));
2bd0ea18 549
993ca3ee 550 libxfs_dir2_sf_put_parent_ino(sfp, mp->m_sb.sb_rootino);
2bd0ea18
NS
551 *dino_dirty = 1;
552 *repair = 1;
553 } else {
507f4e33 554 do_warn(_("would clear inode number\n"));
2bd0ea18
NS
555 }
556 }
557
558 return(0);
559}
560
561/*
562 * Process one directory data block.
563 */
564/* ARGSUSED */
565static int
566process_dir2_data(
567 xfs_mount_t *mp,
568 xfs_ino_t ino,
569 xfs_dinode_t *dip,
570 int ino_discovery,
571 char *dirname, /* directory pathname */
572 xfs_ino_t *parent, /* out - NULLFSINO if entry not exist */
a2ceac1f 573 struct xfs_buf *bp,
2bd0ea18
NS
574 int *dot, /* out - 1 if there is a dot, else 0 */
575 int *dotdot, /* out - 1 if there's a dotdot, else 0 */
576 xfs_dablk_t da_bno,
a2ceac1f
DC
577 char *endptr,
578 int *dirty)
2bd0ea18
NS
579{
580 int badbest;
581 xfs_dir2_data_free_t *bf;
582 int clearino;
583 char *clearreason = NULL;
a354abc8 584 struct xfs_dir2_data_hdr *d;
2bd0ea18
NS
585 xfs_dir2_data_entry_t *dep;
586 xfs_dir2_data_free_t *dfp;
587 xfs_dir2_data_unused_t *dup;
588 int freeseen;
589 int i;
590 int ino_off;
591 ino_tree_node_t *irec_p;
592 int junkit;
593 int lastfree;
594 int nm_illegal;
595 char *ptr;
5e656dbb 596 xfs_ino_t ent_ino;
2bd0ea18 597
a2ceac1f 598 d = bp->b_addr;
04f6f354 599 bf = libxfs_dir2_data_bestfree_p(mp, d);
58a1d356 600 ptr = (char *)d + mp->m_dir_geo->data_entry_offset;
2bd0ea18 601 badbest = lastfree = freeseen = 0;
5e656dbb
BN
602 if (be16_to_cpu(bf[0].length) == 0) {
603 badbest |= be16_to_cpu(bf[0].offset) != 0;
2bd0ea18
NS
604 freeseen |= 1 << 0;
605 }
5e656dbb
BN
606 if (be16_to_cpu(bf[1].length) == 0) {
607 badbest |= be16_to_cpu(bf[1].offset) != 0;
2bd0ea18
NS
608 freeseen |= 1 << 1;
609 }
5e656dbb
BN
610 if (be16_to_cpu(bf[2].length) == 0) {
611 badbest |= be16_to_cpu(bf[2].offset) != 0;
2bd0ea18
NS
612 freeseen |= 1 << 2;
613 }
5e656dbb
BN
614 badbest |= be16_to_cpu(bf[0].length) < be16_to_cpu(bf[1].length);
615 badbest |= be16_to_cpu(bf[1].length) < be16_to_cpu(bf[2].length);
2bd0ea18
NS
616 while (ptr < endptr) {
617 dup = (xfs_dir2_data_unused_t *)ptr;
618 /*
619 * If it's unused, look for the space in the bestfree table.
620 * If we find it, account for that, else make sure it doesn't
621 * need to be there.
622 */
5e656dbb
BN
623 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
624 if (ptr + be16_to_cpu(dup->length) > endptr ||
625 be16_to_cpu(dup->length) == 0 ||
626 (be16_to_cpu(dup->length) & (XFS_DIR2_DATA_ALIGN - 1)))
2bd0ea18 627 break;
5e656dbb
BN
628 if (be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) !=
629 (char *)dup - (char *)d)
2bd0ea18
NS
630 break;
631 badbest |= lastfree != 0;
ff105f75 632 dfp = xfs_dir2_data_freefind(d, bf, dup);
2bd0ea18
NS
633 if (dfp) {
634 i = dfp - bf;
635 badbest |= (freeseen & (1 << i)) != 0;
636 freeseen |= 1 << i;
637 } else
5e656dbb
BN
638 badbest |= be16_to_cpu(dup->length) >
639 be16_to_cpu(bf[2].length);
640 ptr += be16_to_cpu(dup->length);
2bd0ea18
NS
641 lastfree = 1;
642 continue;
643 }
644 dep = (xfs_dir2_data_entry_t *)ptr;
271a654f 645 if (ptr + libxfs_dir2_data_entsize(mp, dep->namelen) > endptr)
2bd0ea18 646 break;
823711f2 647 if (be16_to_cpu(*libxfs_dir2_data_entry_tag_p(mp, dep)) !=
5e656dbb 648 (char *)dep - (char *)d)
2bd0ea18 649 break;
271a654f 650 ptr += libxfs_dir2_data_entsize(mp, dep->namelen);
2bd0ea18
NS
651 lastfree = 0;
652 }
653 /*
654 * Dropped out before we processed everything, give up.
655 * Phase 6 will kill this block if we don't kill the inode.
656 */
657 if (ptr != endptr) {
5d1b7f0f 658 do_warn(_("corrupt block %u in directory inode %" PRIu64 "\n"),
2bd0ea18
NS
659 da_bno, ino);
660 if (!no_modify)
507f4e33 661 do_warn(_("\twill junk block\n"));
2bd0ea18 662 else
507f4e33 663 do_warn(_("\twould junk block\n"));
2bd0ea18
NS
664 return 1;
665 }
58a1d356 666 ptr = (char *)d + mp->m_dir_geo->data_entry_offset;
2bd0ea18
NS
667 /*
668 * Process the entries now.
669 */
670 while (ptr < endptr) {
671 dup = (xfs_dir2_data_unused_t *)ptr;
5e656dbb
BN
672 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
673 ptr += be16_to_cpu(dup->length);
2bd0ea18
NS
674 continue;
675 }
676 dep = (xfs_dir2_data_entry_t *)ptr;
5e656dbb
BN
677 ent_ino = be64_to_cpu(dep->inumber);
678 clearino = 1;
679 clearreason = NULL;
2bd0ea18
NS
680 /*
681 * We may have to blow out an entry because of bad inode
682 * numbers. Do NOT touch the name until after we've computed
683 * the hashvalue and done a namecheck() on the name.
5e656dbb 684 *
4c0a98ae 685 * Conditions must either set clearino to zero or set
5e656dbb 686 * clearreason why it's being cleared.
2bd0ea18 687 */
871fbfd5 688 if (!ino_discovery && dep->name[0] == '/') {
2bd0ea18
NS
689 /*
690 * Don't do a damned thing. We already found this
691 * (or did it ourselves) during phase 3.
692 */
693 clearino = 0;
017e979e 694 } else if (!libxfs_verify_dir_ino(mp, ent_ino)) {
2bd0ea18
NS
695 /*
696 * Bad inode number. Clear the inode number and the
697 * entry will get removed later. We don't trash the
698 * directory since it's still structurally intact.
699 */
507f4e33 700 clearreason = _("invalid");
5e656dbb 701 } else if (ent_ino == mp->m_sb.sb_rbmino) {
507f4e33 702 clearreason = _("realtime bitmap");
5e656dbb 703 } else if (ent_ino == mp->m_sb.sb_rsumino) {
507f4e33 704 clearreason = _("realtime summary");
5e656dbb 705 } else if (ent_ino == mp->m_sb.sb_uquotino) {
507f4e33 706 clearreason = _("user quota");
5e656dbb 707 } else if (ent_ino == mp->m_sb.sb_gquotino) {
507f4e33 708 clearreason = _("group quota");
0340d706
CS
709 } else if (ent_ino == mp->m_sb.sb_pquotino) {
710 clearreason = _("project quota");
2bd0ea18 711 } else {
1ae311d5
LC
712 irec_p = find_inode_rec(mp,
713 XFS_INO_TO_AGNO(mp, ent_ino),
5e656dbb
BN
714 XFS_INO_TO_AGINO(mp, ent_ino));
715 if (irec_p == NULL) {
716 if (ino_discovery) {
717 add_inode_uncertain(mp, ent_ino, 0);
718 clearino = 0;
4c0a98ae 719 } else
5e656dbb
BN
720 clearreason = _("non-existent");
721 } else {
722 /*
723 * Inode recs should have only confirmed
724 * inodes in them.
725 */
726 ino_off = XFS_INO_TO_AGINO(mp, ent_ino)
727 - irec_p->ino_startnum;
728 ASSERT(is_inode_confirmed(irec_p, ino_off));
729 /*
730 * If inode is marked free and we're in inode
731 * discovery mode, leave the entry alone for
732 * now. If the inode turns out to be used,
733 * we'll figure that out when we scan it.
734 * If the inode really is free, we'll hit this
735 * code again in phase 4 after we've finished
736 * inode discovery and blow out the entry then.
737 */
738 if (!ino_discovery && is_inode_free(irec_p,
739 ino_off))
740 clearreason = _("free");
741 else
742 clearino = 0;
743 }
2bd0ea18 744 }
5e656dbb
BN
745 ASSERT((clearino == 0 && clearreason == NULL) ||
746 (clearino != 0 && clearreason != NULL));
2bd0ea18 747 if (clearino)
5d1b7f0f
CH
748 do_warn(
749_("entry \"%*.*s\" at block %d offset %" PRIdPTR " in directory inode %" PRIu64
750 " references %s inode %" PRIu64 "\n"),
2bd0ea18 751 dep->namelen, dep->namelen, dep->name,
5d1b7f0f 752 da_bno, (intptr_t)ptr - (intptr_t)d, ino,
5e656dbb 753 clearreason, ent_ino);
b8ec08a1
ES
754
755 /*
756 * We have a special dot & dotdot fixer-upper below which can
757 * sort out the proper inode number, so don't clear it.
758 */
759 if ((dep->namelen == 1 && dep->name[0] == '.') ||
760 (dep->namelen == 2 &&
761 dep->name[0] == '.' && dep->name[1] == '.')) {
762 clearino = 0;
763 clearreason = NULL;
764 }
765
2bd0ea18
NS
766 /*
767 * If the name length is 0 (illegal) make it 1 and blast
768 * the entry.
769 */
770 if (dep->namelen == 0) {
5d1b7f0f
CH
771 do_warn(
772_("entry at block %u offset %" PRIdPTR " in directory inode %" PRIu64
773 "has 0 namelength\n"),
774 da_bno, (intptr_t)ptr - (intptr_t)d, ino);
2bd0ea18
NS
775 if (!no_modify)
776 dep->namelen = 1;
777 clearino = 1;
778 }
779 /*
780 * If needed to clear the inode number, do it now.
781 */
782 if (clearino) {
783 if (!no_modify) {
5d1b7f0f
CH
784 do_warn(
785_("\tclearing inode number in entry at offset %" PRIdPTR "...\n"),
786 (intptr_t)ptr - (intptr_t)d);
871fbfd5 787 dep->name[0] = '/';
a2ceac1f 788 *dirty = 1;
2bd0ea18 789 } else {
5d1b7f0f
CH
790 do_warn(
791_("\twould clear inode number in entry at offset %" PRIdPTR "...\n"),
792 (intptr_t)ptr - (intptr_t)d);
2bd0ea18
NS
793 }
794 }
795 /*
796 * Only complain about illegal names in phase 3 (when inode
797 * discovery is turned on). Otherwise, we'd complain a lot
798 * during phase 4.
799 */
871fbfd5 800 junkit = dep->name[0] == '/';
b8aa6f27 801 nm_illegal = !libxfs_dir2_namecheck(dep->name, dep->namelen);
2bd0ea18 802 if (ino_discovery && nm_illegal) {
5d1b7f0f
CH
803 do_warn(
804_("entry at block %u offset %" PRIdPTR " in directory inode %" PRIu64 " has illegal name \"%*.*s\": "),
805 da_bno, (intptr_t)ptr - (intptr_t)d, ino,
2bd0ea18
NS
806 dep->namelen, dep->namelen, dep->name);
807 junkit = 1;
808 }
871fbfd5 809
2bd0ea18 810 /*
871fbfd5 811 * Ensure we write back bad entries for later processing
2bd0ea18 812 */
871fbfd5 813 if (!no_modify && dep->name[0] == '/') {
a2ceac1f 814 *dirty = 1;
2bd0ea18
NS
815 junkit = 0;
816 }
871fbfd5 817
2bd0ea18
NS
818 /*
819 * Special .. entry processing.
820 */
821 if (dep->namelen == 2 &&
822 dep->name[0] == '.' && dep->name[1] == '.') {
823 if (!*dotdot) {
824 (*dotdot)++;
5e656dbb 825 *parent = ent_ino;
2bd0ea18
NS
826 /*
827 * What if .. == .? Legal only in the root
828 * inode. Blow out entry and set parent to
829 * NULLFSINO otherwise.
830 */
5e656dbb
BN
831 if (ino == ent_ino &&
832 ino != mp->m_sb.sb_rootino) {
2bd0ea18 833 *parent = NULLFSINO;
5d1b7f0f
CH
834 do_warn(
835_("bad .. entry in directory inode %" PRIu64 ", points to self: "),
2bd0ea18
NS
836 ino);
837 junkit = 1;
838 }
839 /*
840 * We have to make sure that . == .. in the
841 * root inode.
842 */
5e656dbb
BN
843 else if (ino != ent_ino &&
844 ino == mp->m_sb.sb_rootino) {
5d1b7f0f
CH
845 do_warn(
846_("bad .. entry in root directory inode %" PRIu64 ", was %" PRIu64 ": "),
5e656dbb 847 ino, ent_ino);
2bd0ea18 848 if (!no_modify) {
507f4e33 849 do_warn(_("correcting\n"));
5e656dbb 850 dep->inumber = cpu_to_be64(ino);
a2ceac1f 851 *dirty = 1;
2bd0ea18 852 } else {
507f4e33 853 do_warn(_("would correct\n"));
2bd0ea18 854 }
aedcecb5 855 *parent = ino;
2bd0ea18 856 }
75547072
DW
857 /*
858 * Make sure our parent directory doesn't point
859 * off into space.
860 */
861 if (!junkit &&
862 *parent != NULLFSINO &&
863 !libxfs_verify_ino(mp, *parent)) {
864 do_warn(
865_("bad .. entry in directory inode %" PRIu64 ", was %" PRIu64 ": "),
866 ino, *parent);
867 if (!no_modify) {
868 do_warn(_("correcting\n"));
869 } else {
870 do_warn(_("would correct\n"));
871 }
872 *parent = NULLFSINO;
873 }
2bd0ea18
NS
874 }
875 /*
876 * Can't fix the directory unless we know which ..
877 * entry is the right one. Both have valid inode
878 * numbers or we wouldn't be here. So since both
879 * seem equally valid, trash this one.
880 */
881 else {
5d1b7f0f
CH
882 do_warn(
883_("multiple .. entries in directory inode %" PRIu64 ": "),
2bd0ea18
NS
884 ino);
885 junkit = 1;
886 }
887 }
888 /*
889 * Special . entry processing.
890 */
891 else if (dep->namelen == 1 && dep->name[0] == '.') {
892 if (!*dot) {
893 (*dot)++;
5e656dbb 894 if (ent_ino != ino) {
5d1b7f0f
CH
895 do_warn(
896_("bad . entry in directory inode %" PRIu64 ", was %" PRIu64 ": "),
5e656dbb 897 ino, ent_ino);
2bd0ea18 898 if (!no_modify) {
507f4e33 899 do_warn(_("correcting\n"));
5e656dbb 900 dep->inumber = cpu_to_be64(ino);
a2ceac1f 901 *dirty = 1;
2bd0ea18 902 } else {
507f4e33 903 do_warn(_("would correct\n"));
2bd0ea18
NS
904 }
905 }
906 } else {
5d1b7f0f
CH
907 do_warn(
908_("multiple . entries in directory inode %" PRIu64 ": "),
2bd0ea18
NS
909 ino);
910 junkit = 1;
911 }
912 }
913 /*
914 * All other entries -- make sure only . references self.
915 */
5e656dbb 916 else if (ent_ino == ino) {
5d1b7f0f
CH
917 do_warn(
918_("entry \"%*.*s\" in directory inode %" PRIu64 " points to self: "),
2bd0ea18
NS
919 dep->namelen, dep->namelen, dep->name, ino);
920 junkit = 1;
921 }
922 /*
923 * Clear junked entries.
924 */
925 if (junkit) {
926 if (!no_modify) {
927 dep->name[0] = '/';
a2ceac1f 928 *dirty = 1;
507f4e33 929 do_warn(_("clearing entry\n"));
2bd0ea18 930 } else {
507f4e33 931 do_warn(_("would clear entry\n"));
2bd0ea18
NS
932 }
933 }
934 /*
935 * Advance to the next entry.
936 */
271a654f 937 ptr += libxfs_dir2_data_entsize(mp, dep->namelen);
2bd0ea18
NS
938 }
939 /*
940 * Check the bestfree table.
941 */
942 if (freeseen != 7 || badbest) {
5d1b7f0f
CH
943 do_warn(
944_("bad bestfree table in block %u in directory inode %" PRIu64 ": "),
945 da_bno, ino);
2bd0ea18 946 if (!no_modify) {
507f4e33 947 do_warn(_("repairing table\n"));
d85595d0 948 libxfs_dir2_data_freescan(mp, d, &i);
a2ceac1f 949 *dirty = 1;
2bd0ea18 950 } else {
507f4e33 951 do_warn(_("would repair table\n"));
2bd0ea18
NS
952 }
953 }
954 return 0;
955}
956
957/*
958 * Process a block-format directory.
959 */
960/* ARGSUSED */
961static int
962process_block_dir2(
963 xfs_mount_t *mp,
964 xfs_ino_t ino,
965 xfs_dinode_t *dip,
966 int ino_discovery,
967 int *dino_dirty, /* out - 1 if dinode buffer dirty */
968 char *dirname, /* directory pathname */
969 xfs_ino_t *parent, /* out - NULLFSINO if entry not exist */
970 blkmap_t *blkmap,
971 int *dot, /* out - 1 if there is a dot, else 0 */
972 int *dotdot, /* out - 1 if there's a dotdot, else 0 */
973 int *repair) /* out - 1 if something was fixed */
974{
a354abc8 975 struct xfs_dir2_data_hdr *block;
2bd0ea18
NS
976 xfs_dir2_leaf_entry_t *blp;
977 bmap_ext_t *bmp;
a2ceac1f 978 struct xfs_buf *bp;
2bd0ea18
NS
979 xfs_dir2_block_tail_t *btp;
980 int nex;
981 int rval;
1e77098c 982 bmap_ext_t lbmp;
a2ceac1f 983 int dirty = 0;
2bd0ea18
NS
984
985 *repair = *dot = *dotdot = 0;
986 *parent = NULLFSINO;
ff105f75
DC
987 nex = blkmap_getn(blkmap, mp->m_dir_geo->datablk,
988 mp->m_dir_geo->fsbcount, &bmp, &lbmp);
2bd0ea18 989 if (nex == 0) {
5d1b7f0f
CH
990 do_warn(
991_("block %u for directory inode %" PRIu64 " is missing\n"),
ff105f75 992 mp->m_dir_geo->datablk, ino);
2bd0ea18
NS
993 return 1;
994 }
75c8b434 995 bp = da_read_buf(mp, nex, bmp, &xfs_dir3_block_buf_ops);
1e77098c
MV
996 if (bmp != &lbmp)
997 free(bmp);
2bd0ea18 998 if (bp == NULL) {
5d1b7f0f
CH
999 do_warn(
1000_("can't read block %u for directory inode %" PRIu64 "\n"),
ff105f75 1001 mp->m_dir_geo->datablk, ino);
2bd0ea18
NS
1002 return 1;
1003 }
be752639
DW
1004 if (bp->b_error == -EFSCORRUPTED) {
1005 do_warn(
1006_("corrupt directory block %u for inode %" PRIu64 "\n"),
1007 mp->m_dir_geo->datablk, ino);
1008 libxfs_buf_relse(bp);
1009 return 1;
1010 }
2bd0ea18
NS
1011 /*
1012 * Verify the block
1013 */
a2ceac1f 1014 block = bp->b_addr;
a354abc8
DC
1015 if (!(be32_to_cpu(block->magic) == XFS_DIR2_BLOCK_MAGIC ||
1016 be32_to_cpu(block->magic) == XFS_DIR3_BLOCK_MAGIC))
5d1b7f0f
CH
1017 do_warn(
1018_("bad directory block magic # %#x in block %u for directory inode %" PRIu64 "\n"),
ff105f75 1019 be32_to_cpu(block->magic), mp->m_dir_geo->datablk, ino);
2bd0ea18
NS
1020 /*
1021 * process the data area
1022 * this also checks & fixes the bestfree
1023 */
ff105f75 1024 btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block);
5e656dbb 1025 blp = xfs_dir2_block_leaf_p(btp);
2bd0ea18
NS
1026 /*
1027 * Don't let this go past the end of the block.
1028 */
1029 if ((char *)blp > (char *)btp)
1030 blp = (xfs_dir2_leaf_entry_t *)btp;
1031 rval = process_dir2_data(mp, ino, dip, ino_discovery, dirname, parent,
ff105f75 1032 bp, dot, dotdot, mp->m_dir_geo->datablk, (char *)blp, &dirty);
575010d5 1033 /* If block looks ok but CRC didn't match, make sure to recompute it. */
12b53197 1034 if (!rval && bp->b_error == -EFSBADCRC)
575010d5 1035 dirty = 1;
a2ceac1f 1036 if (dirty && !no_modify) {
2bd0ea18 1037 *repair = 1;
f524ae04 1038 libxfs_buf_mark_dirty(bp);
18b4f688 1039 libxfs_buf_relse(bp);
2bd0ea18 1040 } else
e02ba985 1041 libxfs_buf_relse(bp);
2bd0ea18
NS
1042 return rval;
1043}
1044
1045/*
1046 * Validates leaf contents, node format directories only.
1047 * magic number and sibling pointers checked by caller.
1048 * Returns 0 if block is ok, 1 if the block is bad.
1049 * Looking for: out of order hash values, bad stale counts.
1050 */
1051static int
1052process_leaf_block_dir2(
1053 xfs_mount_t *mp,
1054 xfs_dir2_leaf_t *leaf,
1055 xfs_dablk_t da_bno,
1056 xfs_ino_t ino,
1057 xfs_dahash_t last_hashval,
1058 xfs_dahash_t *next_hashval)
1059{
1060 int i;
1061 int stale;
65b80c98 1062 struct xfs_dir2_leaf_entry *ents;
658ac3e3 1063 struct xfs_dir3_icleaf_hdr leafhdr;
65b80c98 1064
9db68faf 1065 libxfs_dir2_leaf_hdr_from_disk(mp, &leafhdr, leaf);
a2279497 1066 ents = leafhdr.ents;
2bd0ea18 1067
658ac3e3 1068 for (i = stale = 0; i < leafhdr.count; i++) {
ff105f75 1069 if ((char *)&ents[i] >= (char *)leaf + mp->m_dir_geo->blksize) {
5d1b7f0f
CH
1070 do_warn(
1071_("bad entry count in block %u of directory inode %" PRIu64 "\n"),
2bd0ea18
NS
1072 da_bno, ino);
1073 return 1;
1074 }
65b80c98 1075 if (be32_to_cpu(ents[i].address) == XFS_DIR2_NULL_DATAPTR)
2bd0ea18 1076 stale++;
65b80c98 1077 else if (be32_to_cpu(ents[i].hashval) < last_hashval) {
5d1b7f0f
CH
1078 do_warn(
1079_("bad hash ordering in block %u of directory inode %" PRIu64 "\n"),
2bd0ea18
NS
1080 da_bno, ino);
1081 return 1;
1082 }
65b80c98 1083 *next_hashval = last_hashval = be32_to_cpu(ents[i].hashval);
2bd0ea18 1084 }
658ac3e3 1085 if (stale != leafhdr.stale) {
5d1b7f0f
CH
1086 do_warn(
1087_("bad stale count in block %u of directory inode %" PRIu64 "\n"),
2bd0ea18
NS
1088 da_bno, ino);
1089 return 1;
1090 }
1091 return 0;
1092}
1093
1094/*
1095 * Returns 0 if the directory is ok, 1 if it has to be rebuilt.
1096 */
1097static int
1098process_leaf_level_dir2(
1099 xfs_mount_t *mp,
360f4a2e 1100 da_bt_cursor_t *da_cursor,
2bd0ea18 1101 int *repair)
dfc130f3 1102{
2bd0ea18 1103 bmap_ext_t *bmp;
a2ceac1f 1104 struct xfs_buf *bp;
2bd0ea18
NS
1105 int buf_dirty;
1106 xfs_dahash_t current_hashval;
1107 xfs_dablk_t da_bno;
1108 xfs_dahash_t greatest_hashval;
1109 xfs_ino_t ino;
1110 xfs_dir2_leaf_t *leaf;
1111 int nex;
1112 xfs_dablk_t prev_bno;
1e77098c 1113 bmap_ext_t lbmp;
658ac3e3 1114 struct xfs_dir3_icleaf_hdr leafhdr;
2bd0ea18
NS
1115
1116 da_bno = da_cursor->level[0].bno;
1117 ino = da_cursor->ino;
1118 prev_bno = 0;
1119 bmp = NULL;
1120 current_hashval = 0;
9234d416 1121 greatest_hashval = 0;
2bd0ea18
NS
1122 buf_dirty = 0;
1123
1124 do {
ff105f75
DC
1125 nex = blkmap_getn(da_cursor->blkmap, da_bno,
1126 mp->m_dir_geo->fsbcount, &bmp, &lbmp);
2bd0ea18
NS
1127 /*
1128 * Directory code uses 0 as the NULL block pointer since 0
1129 * is the root block and no directory block pointer can point
1130 * to the root block of the btree.
1131 */
1132 ASSERT(da_bno != 0);
1133
1134 if (nex == 0) {
5d1b7f0f
CH
1135 do_warn(
1136_("can't map block %u for directory inode %" PRIu64 "\n"),
2bd0ea18
NS
1137 da_bno, ino);
1138 goto error_out;
1139 }
75c8b434 1140 bp = da_read_buf(mp, nex, bmp, &xfs_dir3_leafn_buf_ops);
1e77098c
MV
1141 if (bmp != &lbmp)
1142 free(bmp);
2bd0ea18
NS
1143 bmp = NULL;
1144 if (bp == NULL) {
5d1b7f0f
CH
1145 do_warn(
1146_("can't read file block %u for directory inode %" PRIu64 "\n"),
2bd0ea18
NS
1147 da_bno, ino);
1148 goto error_out;
1149 }
be752639
DW
1150 if (bp->b_error == -EFSCORRUPTED) {
1151 do_warn(
1152_("corrupt directory leafn block %u for inode %" PRIu64 "\n"),
1153 da_bno, ino);
1154 libxfs_buf_relse(bp);
1155 goto error_out;
1156 }
a2ceac1f 1157 leaf = bp->b_addr;
9db68faf 1158 libxfs_dir2_leaf_hdr_from_disk(mp, &leafhdr, leaf);
2bd0ea18
NS
1159 /*
1160 * Check magic number for leaf directory btree block.
1161 */
658ac3e3
DC
1162 if (!(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC ||
1163 leafhdr.magic == XFS_DIR3_LEAFN_MAGIC)) {
5d1b7f0f
CH
1164 do_warn(
1165_("bad directory leaf magic # %#x for directory inode %" PRIu64 " block %u\n"),
658ac3e3 1166 leafhdr.magic, ino, da_bno);
e02ba985 1167 libxfs_buf_relse(bp);
2bd0ea18
NS
1168 goto error_out;
1169 }
1170 buf_dirty = 0;
1171 /*
1172 * For each block, process the block, verify its path,
1173 * then get next block. Update cursor values along the way.
1174 */
1175 if (process_leaf_block_dir2(mp, leaf, da_bno, ino,
1176 current_hashval, &greatest_hashval)) {
e02ba985 1177 libxfs_buf_relse(bp);
2bd0ea18
NS
1178 goto error_out;
1179 }
1180 /*
1181 * Index can be set to hdr.count so match the indices of the
1182 * interior blocks -- which at the end of the block will point
1183 * to 1 after the final real entry in the block.
1184 */
1185 da_cursor->level[0].hashval = greatest_hashval;
1186 da_cursor->level[0].bp = bp;
1187 da_cursor->level[0].bno = da_bno;
658ac3e3 1188 da_cursor->level[0].index = leafhdr.count;
2bd0ea18
NS
1189 da_cursor->level[0].dirty = buf_dirty;
1190
658ac3e3 1191 if (leafhdr.back != prev_bno) {
5d1b7f0f
CH
1192 do_warn(
1193_("bad sibling back pointer for block %u in directory inode %" PRIu64 "\n"),
2bd0ea18 1194 da_bno, ino);
e02ba985 1195 libxfs_buf_relse(bp);
2bd0ea18
NS
1196 goto error_out;
1197 }
1198 prev_bno = da_bno;
658ac3e3 1199 da_bno = leafhdr.forw;
2bd0ea18 1200 if (da_bno != 0) {
360f4a2e 1201 if (verify_da_path(mp, da_cursor, 0, XFS_DATA_FORK)) {
e02ba985 1202 libxfs_buf_relse(bp);
2bd0ea18
NS
1203 goto error_out;
1204 }
1205 }
1206 current_hashval = greatest_hashval;
575010d5
JK
1207 /*
1208 * If block looks ok but CRC didn't match, make sure to
1209 * recompute it.
1210 */
12b53197 1211 if (!no_modify && bp->b_error == -EFSBADCRC)
575010d5 1212 buf_dirty = 1;
27527004 1213 ASSERT(buf_dirty == 0 || (buf_dirty && !no_modify));
2bd0ea18
NS
1214 if (buf_dirty && !no_modify) {
1215 *repair = 1;
f524ae04 1216 libxfs_buf_mark_dirty(bp);
18b4f688 1217 libxfs_buf_relse(bp);
2bd0ea18 1218 } else
e02ba985 1219 libxfs_buf_relse(bp);
2bd0ea18 1220 } while (da_bno != 0);
5cd3b070 1221 if (verify_final_da_path(mp, da_cursor, 0, XFS_DATA_FORK)) {
2bd0ea18
NS
1222 /*
1223 * Verify the final path up (right-hand-side) if still ok.
1224 */
5d1b7f0f 1225 do_warn(_("bad hash path in directory %" PRIu64 "\n"), ino);
2bd0ea18
NS
1226 goto error_out;
1227 }
1228 /*
1229 * Redundant but just for testing.
1230 */
360f4a2e 1231 release_da_cursor(mp, da_cursor, 0);
2bd0ea18
NS
1232 return 0;
1233
1234error_out:
1235 /*
1236 * Release all buffers holding interior btree blocks.
1237 */
360f4a2e 1238 err_release_da_cursor(mp, da_cursor, 0);
1e77098c 1239 if (bmp && (bmp != &lbmp))
2bd0ea18
NS
1240 free(bmp);
1241 return 1;
1242}
1243
1244/*
1245 * Return 1 if the directory's leaf/node space is corrupted and
1246 * needs to be rebuilt, 0 if it's ok.
1247 */
1248static int
1249process_node_dir2(
1250 xfs_mount_t *mp,
1251 xfs_ino_t ino,
1252 xfs_dinode_t *dip,
1253 blkmap_t *blkmap,
1254 int *repair)
1255{
1256 xfs_dablk_t bno;
360f4a2e 1257 da_bt_cursor_t da_cursor;
2bd0ea18
NS
1258
1259 /*
1260 * Try again -- traverse down left-side of tree until we hit the
1261 * left-most leaf block setting up the btree cursor along the way.
1262 * Then walk the leaf blocks left-to-right, calling a parent
1263 * verification routine each time we traverse a block.
1264 */
dab9b8d6 1265 memset(&da_cursor, 0, sizeof(da_cursor));
2bd0ea18
NS
1266 da_cursor.ino = ino;
1267 da_cursor.dip = dip;
1268 da_cursor.blkmap = blkmap;
1269
1270 /*
1271 * Now process interior node.
1272 */
360f4a2e 1273 if (traverse_int_dablock(mp, &da_cursor, &bno, XFS_DATA_FORK) == 0)
2bd0ea18
NS
1274 return 1;
1275
1276 /*
71a6af85 1277 * Skip directories with a root marked XFS_DIR2_LEAFN_MAGIC
3d2195e4
DW
1278 *
1279 * Be careful here: If any level of the da cursor was filled out then
1280 * the directory has a da btree containing an invalid before pointer to
1281 * dblock 0, and we should move on to rebuilding the directory. If no
1282 * levels in the da cursor got filled out, then we just have a single
1283 * leafn block and we're done.
2bd0ea18
NS
1284 */
1285 if (bno == 0) {
3d2195e4
DW
1286 if (da_cursor.active > 0) {
1287 err_release_da_cursor(mp, &da_cursor, 0);
1288 return 1;
1289 } else {
1290 release_da_cursor(mp, &da_cursor, 0);
1291 return 0;
1292 }
2bd0ea18
NS
1293 } else {
1294 /*
1295 * Now pass cursor and bno into leaf-block processing routine.
dfc130f3 1296 * The leaf dir level routine checks the interior paths up to
2bd0ea18
NS
1297 * the root including the final right-most path.
1298 */
1299 return process_leaf_level_dir2(mp, &da_cursor, repair);
1300 }
1301}
1302
1303/*
1304 * Process leaf and node directories.
1305 * Process the data blocks then, if it's a node directory, check
1306 * the consistency of those blocks.
1307 */
1308static int
1309process_leaf_node_dir2(
1310 xfs_mount_t *mp,
1311 xfs_ino_t ino,
1312 xfs_dinode_t *dip,
1313 int ino_discovery,
1314 char *dirname, /* directory pathname */
1315 xfs_ino_t *parent, /* out - NULLFSINO if entry not exist */
1316 blkmap_t *blkmap,
1317 int *dot, /* out - 1 if there is a dot, else 0 */
1318 int *dotdot, /* out - 1 if there's a dotdot, else 0 */
1319 int *repair, /* out - 1 if something was fixed */
1320 int isnode) /* node directory not leaf */
1321{
1322 bmap_ext_t *bmp;
a2ceac1f 1323 struct xfs_buf *bp;
a354abc8 1324 struct xfs_dir2_data_hdr *data;
5a35bf2c 1325 xfs_fileoff_t dbno;
2bd0ea18
NS
1326 int good;
1327 int i;
5a35bf2c 1328 xfs_fileoff_t ndbno;
2bd0ea18
NS
1329 int nex;
1330 int t;
1e77098c 1331 bmap_ext_t lbmp;
a2ceac1f 1332 int dirty = 0;
2bd0ea18
NS
1333
1334 *repair = *dot = *dotdot = good = 0;
1335 *parent = NULLFSINO;
5a35bf2c 1336 ndbno = NULLFILEOFF;
ff105f75
DC
1337 while ((dbno = blkmap_next_off(blkmap, ndbno, &t)) < mp->m_dir_geo->leafblk) {
1338 nex = blkmap_getn(blkmap, dbno, mp->m_dir_geo->fsbcount, &bmp, &lbmp);
9fe1cc86
ES
1339 /* Advance through map to last dfs block in this dir block */
1340 ndbno = dbno;
ff105f75 1341 while (ndbno < dbno + mp->m_dir_geo->fsbcount - 1) {
9fe1cc86
ES
1342 ndbno = blkmap_next_off(blkmap, ndbno, &t);
1343 }
2bd0ea18 1344 if (nex == 0) {
5d1b7f0f
CH
1345 do_warn(
1346_("block %" PRIu64 " for directory inode %" PRIu64 " is missing\n"),
2bd0ea18
NS
1347 dbno, ino);
1348 continue;
1349 }
75c8b434 1350 bp = da_read_buf(mp, nex, bmp, &xfs_dir3_data_buf_ops);
1e77098c
MV
1351 if (bmp != &lbmp)
1352 free(bmp);
2bd0ea18 1353 if (bp == NULL) {
5d1b7f0f
CH
1354 do_warn(
1355_("can't read block %" PRIu64 " for directory inode %" PRIu64 "\n"),
2bd0ea18
NS
1356 dbno, ino);
1357 continue;
1358 }
be752639
DW
1359 if (bp->b_error == -EFSCORRUPTED) {
1360 do_warn(
7aed36f9 1361_("corrupt directory data block %" PRIu64 " for inode %" PRIu64 "\n"),
be752639
DW
1362 dbno, ino);
1363 libxfs_buf_relse(bp);
1364 continue;
1365 }
a2ceac1f 1366 data = bp->b_addr;
a354abc8
DC
1367 if (!(be32_to_cpu(data->magic) == XFS_DIR2_DATA_MAGIC ||
1368 be32_to_cpu(data->magic) == XFS_DIR3_DATA_MAGIC))
5d1b7f0f
CH
1369 do_warn(
1370_("bad directory block magic # %#x in block %" PRIu64 " for directory inode %" PRIu64 "\n"),
a354abc8 1371 be32_to_cpu(data->magic), dbno, ino);
2bd0ea18
NS
1372 i = process_dir2_data(mp, ino, dip, ino_discovery, dirname,
1373 parent, bp, dot, dotdot, (xfs_dablk_t)dbno,
ff105f75 1374 (char *)data + mp->m_dir_geo->blksize, &dirty);
575010d5 1375 if (i == 0) {
2bd0ea18 1376 good++;
575010d5 1377 /* Maybe just CRC is wrong. Make sure we correct it. */
12b53197 1378 if (bp->b_error == -EFSBADCRC)
575010d5
JK
1379 dirty = 1;
1380 }
a2ceac1f 1381 if (dirty && !no_modify) {
2bd0ea18 1382 *repair = 1;
f524ae04 1383 libxfs_buf_mark_dirty(bp);
18b4f688 1384 libxfs_buf_relse(bp);
2bd0ea18 1385 } else
e02ba985 1386 libxfs_buf_relse(bp);
2bd0ea18
NS
1387 }
1388 if (good == 0)
1389 return 1;
1390 if (!isnode)
1391 return 0;
1392 if (dir2_is_badino(ino))
1393 return 0;
1394
1395 if (process_node_dir2(mp, ino, dip, blkmap, repair))
1396 dir2_add_badlist(ino);
1397 return 0;
1398
1399}
1400
1401/*
1402 * Returns 1 if things are bad (directory needs to be junked)
1403 * and 0 if things are ok. If ino_discovery is 1, add unknown
1404 * inodes to uncertain inode list.
1405 */
1406int
1407process_dir2(
1408 xfs_mount_t *mp,
1409 xfs_ino_t ino,
1410 xfs_dinode_t *dip,
1411 int ino_discovery,
1412 int *dino_dirty,
1413 char *dirname,
1414 xfs_ino_t *parent,
1415 blkmap_t *blkmap)
1416{
1417 int dot;
1418 int dotdot;
5a35bf2c 1419 xfs_fileoff_t last;
2bd0ea18
NS
1420 int repair;
1421 int res;
1422
1423 *parent = NULLFSINO;
1424 dot = dotdot = 0;
1425 last = 0;
1426
1427 /*
1428 * branch off depending on the type of inode. This routine
1429 * is only called ONCE so all the subordinate routines will
1430 * fix '.' and junk '..' if they're bogus.
1431 */
1432 if (blkmap)
1433 last = blkmap_last_off(blkmap);
56b2de80
DC
1434 if (be64_to_cpu(dip->di_size) <= XFS_DFORK_DSIZE(dip, mp) &&
1435 dip->di_format == XFS_DINODE_FMT_LOCAL) {
2bd0ea18
NS
1436 dot = dotdot = 1;
1437 res = process_sf_dir2(mp, ino, dip, ino_discovery, dino_dirty,
1438 dirname, parent, &repair);
ff105f75 1439 } else if (last == mp->m_dir_geo->fsbcount &&
56b2de80
DC
1440 (dip->di_format == XFS_DINODE_FMT_EXTENTS ||
1441 dip->di_format == XFS_DINODE_FMT_BTREE)) {
2bd0ea18
NS
1442 res = process_block_dir2(mp, ino, dip, ino_discovery,
1443 dino_dirty, dirname, parent, blkmap, &dot, &dotdot,
1444 &repair);
ff105f75 1445 } else if (last >= mp->m_dir_geo->leafblk + mp->m_dir_geo->fsbcount &&
56b2de80
DC
1446 (dip->di_format == XFS_DINODE_FMT_EXTENTS ||
1447 dip->di_format == XFS_DINODE_FMT_BTREE)) {
2bd0ea18
NS
1448 res = process_leaf_node_dir2(mp, ino, dip, ino_discovery,
1449 dirname, parent, blkmap, &dot, &dotdot, &repair,
ff105f75 1450 last > mp->m_dir_geo->leafblk + mp->m_dir_geo->fsbcount);
2bd0ea18 1451 } else {
5d1b7f0f 1452 do_warn(_("bad size/format for directory %" PRIu64 "\n"), ino);
2bd0ea18
NS
1453 return 1;
1454 }
1455 /*
1456 * bad . entries in all directories will be fixed up in phase 6
1457 */
1458 if (dot == 0) {
5d1b7f0f 1459 do_warn(_("no . entry for directory %" PRIu64 "\n"), ino);
2bd0ea18
NS
1460 }
1461
1462 /*
1463 * shortform dirs always have a .. entry. .. for all longform
1464 * directories will get fixed in phase 6. .. for other shortform
1465 * dirs also get fixed there. .. for a shortform root was
1466 * fixed in place since we know what it should be
1467 */
1468 if (dotdot == 0 && ino != mp->m_sb.sb_rootino) {
5d1b7f0f 1469 do_warn(_("no .. entry for directory %" PRIu64 "\n"), ino);
2bd0ea18 1470 } else if (dotdot == 0 && ino == mp->m_sb.sb_rootino) {
5d1b7f0f 1471 do_warn(_("no .. entry for root directory %" PRIu64 "\n"), ino);
2bd0ea18
NS
1472 need_root_dotdot = 1;
1473 }
dfc130f3 1474
27527004
NS
1475 ASSERT((ino != mp->m_sb.sb_rootino && ino != *parent) ||
1476 (ino == mp->m_sb.sb_rootino &&
1477 (ino == *parent || need_root_dotdot == 1)));
2bd0ea18
NS
1478
1479 return res;
1480}