]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - repair/phase6.c
xfs_repair: fix missing dir buffer corruption checks
[thirdparty/xfsprogs-dev.git] / repair / phase6.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0
2bd0ea18 2/*
da23017d
NS
3 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
4 * All Rights Reserved.
2bd0ea18
NS
5 */
6
6b803e5a 7#include "libxfs.h"
1164bde5
DC
8#include "threads.h"
9#include "prefetch.h"
2bd0ea18
NS
10#include "avl.h"
11#include "globals.h"
12#include "agheader.h"
13#include "incore.h"
2bd0ea18 14#include "dir2.h"
2bd0ea18
NS
15#include "protos.h"
16#include "err_protos.h"
17#include "dinode.h"
06fbdda9 18#include "progress.h"
2bd0ea18
NS
19#include "versions.h"
20
6c39a3cb
BN
21static struct cred zerocr;
22static struct fsxattr zerofsx;
23static xfs_ino_t orphanage_ino;
2bd0ea18 24
1acc5385
ES
25static struct xfs_name xfs_name_dot = {(unsigned char *)".",
26 1,
27 XFS_DIR3_FT_DIR};
5e656dbb 28
3452f451
DW
29/*
30 * When we're checking directory inodes, we're allowed to set a directory's
31 * dotdot entry to zero to signal that the parent needs to be reconnected
32 * during phase 6. If we're handling a shortform directory the ifork
33 * verifiers will fail, so temporarily patch out this canary so that we can
34 * verify the rest of the fork and move on to fixing the dir.
35 */
36static xfs_failaddr_t
37phase6_verify_dir(
38 struct xfs_inode *ip)
39{
40 struct xfs_mount *mp = ip->i_mount;
3452f451
DW
41 struct xfs_ifork *ifp;
42 struct xfs_dir2_sf_hdr *sfp;
43 xfs_failaddr_t fa;
44 xfs_ino_t old_parent;
45 bool parent_bypass = false;
46 int size;
47
3452f451
DW
48 ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
49 sfp = (struct xfs_dir2_sf_hdr *)ifp->if_u1.if_data;
50 size = ifp->if_bytes;
51
52 /*
53 * If this is a shortform directory, phase4 may have set the parent
54 * inode to zero to indicate that it must be fixed. Temporarily
55 * set a valid parent so that the directory verifier will pass.
56 */
57 if (size > offsetof(struct xfs_dir2_sf_hdr, parent) &&
58 size >= xfs_dir2_sf_hdr_size(sfp->i8count)) {
8a7190bd 59 old_parent = libxfs_dir2_sf_get_parent_ino(sfp);
3452f451 60 if (old_parent == 0) {
8a7190bd 61 libxfs_dir2_sf_put_parent_ino(sfp, mp->m_sb.sb_rootino);
3452f451
DW
62 parent_bypass = true;
63 }
64 }
65
66 fa = libxfs_default_ifork_ops.verify_dir(ip);
67
68 /* Put it back. */
69 if (parent_bypass)
8a7190bd 70 libxfs_dir2_sf_put_parent_ino(sfp, old_parent);
3452f451
DW
71
72 return fa;
73}
74
75static struct xfs_ifork_ops phase6_ifork_ops = {
76 .verify_attr = xfs_attr_shortform_verify,
77 .verify_dir = phase6_verify_dir,
78 .verify_symlink = xfs_symlink_shortform_verify,
79};
80
575ca697
BN
81/*
82 * Data structures used to keep track of directories where the ".."
83 * entries are updated. These must be rebuilt after the initial pass
84 */
85typedef struct dotdot_update {
1177f669 86 struct list_head list;
575ca697
BN
87 ino_tree_node_t *irec;
88 xfs_agnumber_t agno;
89 int ino_offset;
90} dotdot_update_t;
91
1177f669 92static LIST_HEAD(dotdot_update_list);
575ca697
BN
93static int dotdot_update;
94
95static void
96add_dotdot_update(
97 xfs_agnumber_t agno,
98 ino_tree_node_t *irec,
99 int ino_offset)
100{
101 dotdot_update_t *dir = malloc(sizeof(dotdot_update_t));
102
103 if (!dir)
5d1b7f0f 104 do_error(_("malloc failed add_dotdot_update (%zu bytes)\n"),
575ca697
BN
105 sizeof(dotdot_update_t));
106
1177f669 107 INIT_LIST_HEAD(&dir->list);
575ca697
BN
108 dir->irec = irec;
109 dir->agno = agno;
110 dir->ino_offset = ino_offset;
111
1177f669 112 list_add(&dir->list, &dotdot_update_list);
575ca697
BN
113}
114
2bd0ea18
NS
115/*
116 * Data structures and routines to keep track of directory entries
33165ec3
BN
117 * and whether their leaf entry has been seen. Also used for name
118 * duplicate checking and rebuilding step if required.
2bd0ea18
NS
119 */
120typedef struct dir_hash_ent {
33165ec3
BN
121 struct dir_hash_ent *nextbyaddr; /* next in addr bucket */
122 struct dir_hash_ent *nextbyhash; /* next in name bucket */
123 struct dir_hash_ent *nextbyorder; /* next in order added */
124 xfs_dahash_t hashval; /* hash value of name */
14f8b681 125 uint32_t address; /* offset of data entry */
33165ec3
BN
126 xfs_ino_t inum; /* inode num of entry */
127 short junkit; /* name starts with / */
128 short seen; /* have seen leaf entry */
5e656dbb 129 struct xfs_name name;
2bd0ea18
NS
130} dir_hash_ent_t;
131
132typedef struct dir_hash_tab {
33165ec3
BN
133 int size; /* size of hash tables */
134 int names_duped; /* 1 = ent names malloced */
135 dir_hash_ent_t *first; /* ptr to first added entry */
136 dir_hash_ent_t *last; /* ptr to last added entry */
137 dir_hash_ent_t **byhash; /* ptr to name hash buckets */
138 dir_hash_ent_t **byaddr; /* ptr to addr hash buckets */
2bd0ea18 139} dir_hash_tab_t;
33165ec3 140
2bd0ea18 141#define DIR_HASH_TAB_SIZE(n) \
33165ec3 142 (sizeof(dir_hash_tab_t) + (sizeof(dir_hash_ent_t *) * (n) * 2))
2bd0ea18
NS
143#define DIR_HASH_FUNC(t,a) ((a) % (t)->size)
144
145/*
146 * Track the contents of the freespace table in a directory.
147 */
148typedef struct freetab {
9d7d6241
NS
149 int naents; /* expected number of data blocks */
150 int nents; /* number of data blocks processed */
2bd0ea18
NS
151 struct freetab_ent {
152 xfs_dir2_data_off_t v;
153 short s;
154 } ents[1];
155} freetab_t;
156#define FREETAB_SIZE(n) \
157 (offsetof(freetab_t, ents) + (sizeof(struct freetab_ent) * (n)))
158
159#define DIR_HASH_CK_OK 0
160#define DIR_HASH_CK_DUPLEAF 1
161#define DIR_HASH_CK_BADHASH 2
162#define DIR_HASH_CK_NODATA 3
163#define DIR_HASH_CK_NOLEAF 4
164#define DIR_HASH_CK_BADSTALE 5
507f4e33 165#define DIR_HASH_CK_TOTAL 6
2bd0ea18 166
8e7e14be
DC
167/*
168 * Need to handle CRC and validation errors specially here. If there is a
169 * validator error, re-read without the verifier so that we get a buffer we can
170 * check and repair. Re-attach the ops to the buffer after the read so that when
171 * it is rewritten the CRC is recalculated.
172 *
173 * If the buffer was not read, we return an error. If the buffer was read but
174 * had a CRC or corruption error, we reread it without the verifier and if it is
175 * read successfully we increment *crc_error and return 0. Otherwise we
176 * return the read error.
177 */
178static int
179dir_read_buf(
180 struct xfs_inode *ip,
181 xfs_dablk_t bno,
8e7e14be
DC
182 struct xfs_buf **bpp,
183 const struct xfs_buf_ops *ops,
184 int *crc_error)
185{
186 int error;
187 int error2;
188
db8e6401 189 error = -libxfs_da_read_buf(NULL, ip, bno, 0, bpp, XFS_DATA_FORK, ops);
8e7e14be
DC
190
191 if (error != EFSBADCRC && error != EFSCORRUPTED)
192 return error;
193
db8e6401
DW
194 error2 = -libxfs_da_read_buf(NULL, ip, bno, 0, bpp, XFS_DATA_FORK,
195 NULL);
8e7e14be
DC
196 if (error2)
197 return error2;
198
199 (*crc_error)++;
200 (*bpp)->b_ops = ops;
201 return 0;
202}
203
33165ec3
BN
204/*
205 * Returns 0 if the name already exists (ie. a duplicate)
206 */
207static int
2bd0ea18 208dir_hash_add(
51ca7008 209 xfs_mount_t *mp,
2bd0ea18 210 dir_hash_tab_t *hashtab,
14f8b681 211 uint32_t addr,
33165ec3
BN
212 xfs_ino_t inum,
213 int namelen,
aaca101b 214 unsigned char *name,
14f8b681 215 uint8_t ftype)
2bd0ea18 216{
33165ec3
BN
217 xfs_dahash_t hash = 0;
218 int byaddr;
219 int byhash = 0;
2bd0ea18 220 dir_hash_ent_t *p;
33165ec3
BN
221 int dup;
222 short junk;
5e656dbb 223 struct xfs_name xname;
0f012a4c 224
33165ec3 225 ASSERT(!hashtab->names_duped);
0f012a4c 226
5e656dbb
BN
227 xname.name = name;
228 xname.len = namelen;
aaca101b 229 xname.type = ftype;
5e656dbb 230
33165ec3
BN
231 junk = name[0] == '/';
232 byaddr = DIR_HASH_FUNC(hashtab, addr);
233 dup = 0;
2bd0ea18 234
33165ec3 235 if (!junk) {
e169cc9b 236 hash = libxfs_dir2_hashname(mp, &xname);
33165ec3
BN
237 byhash = DIR_HASH_FUNC(hashtab, hash);
238
0f012a4c 239 /*
33165ec3
BN
240 * search hash bucket for existing name.
241 */
242 for (p = hashtab->byhash[byhash]; p; p = p->nextbyhash) {
5e656dbb
BN
243 if (p->hashval == hash && p->name.len == namelen) {
244 if (memcmp(p->name.name, name, namelen) == 0) {
33165ec3
BN
245 dup = 1;
246 junk = 1;
247 break;
248 }
249 }
250 }
251 }
0f012a4c 252
507f4e33 253 if ((p = malloc(sizeof(*p))) == NULL)
5d1b7f0f 254 do_error(_("malloc failed in dir_hash_add (%zu bytes)\n"),
2bd0ea18 255 sizeof(*p));
0f012a4c 256
33165ec3
BN
257 p->nextbyaddr = hashtab->byaddr[byaddr];
258 hashtab->byaddr[byaddr] = p;
0f012a4c 259 if (hashtab->last)
33165ec3
BN
260 hashtab->last->nextbyorder = p;
261 else
262 hashtab->first = p;
263 p->nextbyorder = NULL;
264 hashtab->last = p;
0f012a4c 265
33165ec3
BN
266 if (!(p->junkit = junk)) {
267 p->hashval = hash;
268 p->nextbyhash = hashtab->byhash[byhash];
269 hashtab->byhash[byhash] = p;
270 }
271 p->address = addr;
272 p->inum = inum;
2bd0ea18 273 p->seen = 0;
5e656dbb 274 p->name = xname;
0f012a4c 275
33165ec3 276 return !dup;
2bd0ea18
NS
277}
278
33165ec3 279/*
0f012a4c 280 * checks to see if any data entries are not in the leaf blocks
33165ec3 281 */
2bd0ea18
NS
282static int
283dir_hash_unseen(
284 dir_hash_tab_t *hashtab)
285{
286 int i;
287 dir_hash_ent_t *p;
288
289 for (i = 0; i < hashtab->size; i++) {
33165ec3 290 for (p = hashtab->byaddr[i]; p; p = p->nextbyaddr) {
2bd0ea18
NS
291 if (p->seen == 0)
292 return 1;
293 }
294 }
295 return 0;
296}
297
298static int
299dir_hash_check(
300 dir_hash_tab_t *hashtab,
301 xfs_inode_t *ip,
302 int seeval)
303{
507f4e33
NS
304 static char *seevalstr[DIR_HASH_CK_TOTAL];
305 static int done;
306
307 if (!done) {
308 seevalstr[DIR_HASH_CK_OK] = _("ok");
309 seevalstr[DIR_HASH_CK_DUPLEAF] = _("duplicate leaf");
310 seevalstr[DIR_HASH_CK_BADHASH] = _("hash value mismatch");
311 seevalstr[DIR_HASH_CK_NODATA] = _("no data entry");
312 seevalstr[DIR_HASH_CK_NOLEAF] = _("no leaf entry");
313 seevalstr[DIR_HASH_CK_BADSTALE] = _("bad stale count");
314 done = 1;
315 }
2bd0ea18
NS
316
317 if (seeval == DIR_HASH_CK_OK && dir_hash_unseen(hashtab))
318 seeval = DIR_HASH_CK_NOLEAF;
319 if (seeval == DIR_HASH_CK_OK)
320 return 0;
5d1b7f0f 321 do_warn(_("bad hash table for directory inode %" PRIu64 " (%s): "),
507f4e33 322 ip->i_ino, seevalstr[seeval]);
2bd0ea18 323 if (!no_modify)
507f4e33 324 do_warn(_("rebuilding\n"));
2bd0ea18 325 else
507f4e33 326 do_warn(_("would rebuild\n"));
2bd0ea18
NS
327 return 1;
328}
329
330static void
331dir_hash_done(
332 dir_hash_tab_t *hashtab)
333{
334 int i;
335 dir_hash_ent_t *n;
336 dir_hash_ent_t *p;
337
338 for (i = 0; i < hashtab->size; i++) {
33165ec3
BN
339 for (p = hashtab->byaddr[i]; p; p = n) {
340 n = p->nextbyaddr;
341 if (hashtab->names_duped)
5e656dbb 342 free((void *)p->name.name);
2bd0ea18
NS
343 free(p);
344 }
345 }
346 free(hashtab);
347}
348
349static dir_hash_tab_t *
350dir_hash_init(
351 xfs_fsize_t size)
352{
353 dir_hash_tab_t *hashtab;
354 int hsize;
355
356 hsize = size / (16 * 4);
2556c98b
BN
357 if (hsize > 65536)
358 hsize = 63336;
2bd0ea18
NS
359 else if (hsize < 16)
360 hsize = 16;
507f4e33
NS
361 if ((hashtab = calloc(DIR_HASH_TAB_SIZE(hsize), 1)) == NULL)
362 do_error(_("calloc failed in dir_hash_init\n"));
2bd0ea18 363 hashtab->size = hsize;
0f012a4c 364 hashtab->byhash = (dir_hash_ent_t**)((char *)hashtab +
33165ec3 365 sizeof(dir_hash_tab_t));
0f012a4c 366 hashtab->byaddr = (dir_hash_ent_t**)((char *)hashtab +
33165ec3 367 sizeof(dir_hash_tab_t) + sizeof(dir_hash_ent_t*) * hsize);
2bd0ea18
NS
368 return hashtab;
369}
370
371static int
372dir_hash_see(
373 dir_hash_tab_t *hashtab,
374 xfs_dahash_t hash,
375 xfs_dir2_dataptr_t addr)
376{
377 int i;
378 dir_hash_ent_t *p;
379
380 i = DIR_HASH_FUNC(hashtab, addr);
33165ec3
BN
381 for (p = hashtab->byaddr[i]; p; p = p->nextbyaddr) {
382 if (p->address != addr)
2bd0ea18
NS
383 continue;
384 if (p->seen)
385 return DIR_HASH_CK_DUPLEAF;
33165ec3 386 if (p->junkit == 0 && p->hashval != hash)
2bd0ea18
NS
387 return DIR_HASH_CK_BADHASH;
388 p->seen = 1;
389 return DIR_HASH_CK_OK;
390 }
391 return DIR_HASH_CK_NODATA;
392}
393
aaca101b
DC
394static void
395dir_hash_update_ftype(
396 dir_hash_tab_t *hashtab,
397 xfs_dir2_dataptr_t addr,
14f8b681 398 uint8_t ftype)
aaca101b
DC
399{
400 int i;
401 dir_hash_ent_t *p;
402
403 i = DIR_HASH_FUNC(hashtab, addr);
404 for (p = hashtab->byaddr[i]; p; p = p->nextbyaddr) {
405 if (p->address != addr)
406 continue;
407 p->name.type = ftype;
408 }
409}
410
33165ec3
BN
411/*
412 * checks to make sure leafs match a data entry, and that the stale
413 * count is valid.
414 */
2bd0ea18
NS
415static int
416dir_hash_see_all(
417 dir_hash_tab_t *hashtab,
418 xfs_dir2_leaf_entry_t *ents,
419 int count,
420 int stale)
421{
422 int i;
423 int j;
424 int rval;
425
426 for (i = j = 0; i < count; i++) {
5e656dbb 427 if (be32_to_cpu(ents[i].address) == XFS_DIR2_NULL_DATAPTR) {
2bd0ea18
NS
428 j++;
429 continue;
430 }
5e656dbb
BN
431 rval = dir_hash_see(hashtab, be32_to_cpu(ents[i].hashval),
432 be32_to_cpu(ents[i].address));
2bd0ea18
NS
433 if (rval != DIR_HASH_CK_OK)
434 return rval;
435 }
436 return j == stale ? DIR_HASH_CK_OK : DIR_HASH_CK_BADSTALE;
437}
438
64c54486 439/*
33165ec3
BN
440 * Convert name pointers into locally allocated memory.
441 * This must only be done after all the entries have been added.
64c54486 442 */
33165ec3
BN
443static void
444dir_hash_dup_names(dir_hash_tab_t *hashtab)
64c54486 445{
56b2de80 446 unsigned char *name;
33165ec3 447 dir_hash_ent_t *p;
0f012a4c 448
33165ec3
BN
449 if (hashtab->names_duped)
450 return;
0f012a4c 451
33165ec3 452 for (p = hashtab->first; p; p = p->nextbyorder) {
5e656dbb
BN
453 name = malloc(p->name.len);
454 memcpy(name, p->name.name, p->name.len);
455 p->name.name = name;
64c54486 456 }
33165ec3 457 hashtab->names_duped = 1;
64c54486
BN
458}
459
2bd0ea18 460/*
5e656dbb
BN
461 * Given a block number in a fork, return the next valid block number
462 * (not a hole).
463 * If this is the last block number then NULLFILEOFF is returned.
464 *
465 * This was originally in the kernel, but only used in xfs_repair.
466 */
2bd0ea18 467static int
5e656dbb
BN
468bmap_next_offset(
469 xfs_trans_t *tp, /* transaction pointer */
470 xfs_inode_t *ip, /* incore inode */
471 xfs_fileoff_t *bnop, /* current block */
472 int whichfork) /* data or attr fork */
2bd0ea18 473{
5e656dbb 474 xfs_fileoff_t bno; /* current block */
5e656dbb
BN
475 int error; /* error return value */
476 xfs_bmbt_irec_t got; /* current extent value */
e07055b8 477 struct xfs_ifork *ifp; /* inode fork pointer */
9788e059 478 struct xfs_iext_cursor icur;
5e656dbb
BN
479
480 if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
481 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
482 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL)
483 return EIO;
484 if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
485 *bnop = NULLFILEOFF;
486 return 0;
487 }
488 ifp = XFS_IFORK_PTR(ip, whichfork);
489 if (!(ifp->if_flags & XFS_IFEXTENTS) &&
e2f60652 490 (error = -libxfs_iread_extents(tp, ip, whichfork)))
5e656dbb
BN
491 return error;
492 bno = *bnop + 1;
9788e059 493 if (!libxfs_iext_lookup_extent(ip, ifp, bno, &icur, &got))
5e656dbb 494 *bnop = NULLFILEOFF;
2bd0ea18 495 else
5e656dbb
BN
496 *bnop = got.br_startoff < bno ? bno : got.br_startoff;
497 return 0;
2bd0ea18
NS
498}
499
500
501static void
502res_failed(
503 int err)
504{
505 if (err == ENOSPC) {
507f4e33 506 do_error(_("ran out of disk space!\n"));
2bd0ea18 507 } else
507f4e33 508 do_error(_("xfs_trans_reserve returned %d\n"), err);
2bd0ea18
NS
509}
510
00ff2b10 511static void
2bd0ea18
NS
512mk_rbmino(xfs_mount_t *mp)
513{
514 xfs_trans_t *tp;
515 xfs_inode_t *ip;
516 xfs_bmbt_irec_t *ep;
2bd0ea18
NS
517 int i;
518 int nmap;
2bd0ea18 519 int error;
5a35bf2c 520 xfs_fileoff_t bno;
2bd0ea18 521 xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP];
41ce5f36 522 int times;
225e4bb2 523 uint blocks;
2bd0ea18
NS
524
525 /*
526 * first set up inode
527 */
225e4bb2 528 i = -libxfs_trans_alloc_rollable(mp, 10, &tp);
48ea6cb9 529 if (i)
2bd0ea18
NS
530 res_failed(i);
531
e2dd0e1c
DW
532 error = -libxfs_iget(mp, tp, mp->m_sb.sb_rbmino, 0, &ip,
533 &xfs_default_ifork_ops);
2bd0ea18 534 if (error) {
507f4e33
NS
535 do_error(
536 _("couldn't iget realtime bitmap inode -- error - %d\n"),
2bd0ea18
NS
537 error);
538 }
539
138659f1 540 memset(&ip->i_d, 0, sizeof(ip->i_d));
2bd0ea18 541
e37bf53c 542 VFS_I(ip)->i_mode = S_IFREG;
2bd0ea18
NS
543 ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
544 ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
545
bcbe04c1 546 set_nlink(VFS_I(ip), 1); /* account for sb ptr */
2bd0ea18 547
41ce5f36 548 times = XFS_ICHGTIME_CHG | XFS_ICHGTIME_MOD;
fd82a87e 549 if (xfs_sb_version_has_v3inode(&mp->m_sb)) {
9abcc5cd 550 VFS_I(ip)->i_version = 1;
41ce5f36 551 ip->i_d.di_flags2 = 0;
41ce5f36
DC
552 times |= XFS_ICHGTIME_CREATE;
553 }
554 libxfs_trans_ichgtime(tp, ip, times);
555
2bd0ea18
NS
556 /*
557 * now the ifork
558 */
559 ip->i_df.if_flags = XFS_IFEXTENTS;
9685aa3e 560 ip->i_df.if_bytes = 0;
b37d753d 561 ip->i_df.if_u1.if_root = NULL;
2bd0ea18
NS
562
563 ip->i_d.di_size = mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize;
564
565 /*
566 * commit changes
567 */
e2dd0e1c 568 libxfs_trans_ijoin(tp, ip, 0);
2bd0ea18 569 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
f2279d8d
DW
570 error = -libxfs_trans_commit(tp);
571 if (error)
572 do_error(_("%s: commit failed, error %d\n"), __func__, error);
2bd0ea18
NS
573
574 /*
575 * then allocate blocks for file and fill with zeroes (stolen
576 * from mkfs)
577 */
225e4bb2
DW
578 blocks = mp->m_sb.sb_rbmblocks +
579 XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1;
580 error = -libxfs_trans_alloc_rollable(mp, blocks, &tp);
48ea6cb9 581 if (error)
2bd0ea18
NS
582 res_failed(error);
583
584 libxfs_trans_ijoin(tp, ip, 0);
585 bno = 0;
2bd0ea18
NS
586 while (bno < mp->m_sb.sb_rbmblocks) {
587 nmap = XFS_BMAP_MAX_NMAP;
12b53197 588 error = -libxfs_bmapi_write(tp, ip, bno,
2bd0ea18 589 (xfs_extlen_t)(mp->m_sb.sb_rbmblocks - bno),
b39f9fcb 590 0, mp->m_sb.sb_rbmblocks, map, &nmap);
2bd0ea18 591 if (error) {
507f4e33
NS
592 do_error(
593 _("couldn't allocate realtime bitmap, error = %d\n"),
2bd0ea18
NS
594 error);
595 }
596 for (i = 0, ep = map; i < nmap; i++, ep++) {
75c8b434 597 libxfs_device_zero(mp->m_ddev_targp,
2bd0ea18
NS
598 XFS_FSB_TO_DADDR(mp, ep->br_startblock),
599 XFS_FSB_TO_BB(mp, ep->br_blockcount));
600 bno += ep->br_blockcount;
601 }
602 }
f2279d8d
DW
603 error = -libxfs_trans_commit(tp);
604 if (error) {
605 do_error(
606 _("allocation of the realtime bitmap failed, error = %d\n"),
607 error);
608 }
31845e4c 609 libxfs_irele(ip);
2bd0ea18
NS
610}
611
8b8a6b02 612static int
2bd0ea18
NS
613fill_rbmino(xfs_mount_t *mp)
614{
615 xfs_buf_t *bp;
616 xfs_trans_t *tp;
617 xfs_inode_t *ip;
618 xfs_rtword_t *bmp;
2bd0ea18
NS
619 int nmap;
620 int error;
5a35bf2c 621 xfs_fileoff_t bno;
2bd0ea18
NS
622 xfs_bmbt_irec_t map;
623
624 bmp = btmcompute;
625 bno = 0;
626
225e4bb2 627 error = -libxfs_trans_alloc_rollable(mp, 10, &tp);
48ea6cb9 628 if (error)
2bd0ea18
NS
629 res_failed(error);
630
e2dd0e1c
DW
631 error = -libxfs_iget(mp, tp, mp->m_sb.sb_rbmino, 0, &ip,
632 &xfs_default_ifork_ops);
2bd0ea18 633 if (error) {
507f4e33
NS
634 do_error(
635 _("couldn't iget realtime bitmap inode -- error - %d\n"),
2bd0ea18
NS
636 error);
637 }
638
639 while (bno < mp->m_sb.sb_rbmblocks) {
640 /*
641 * fill the file one block at a time
642 */
643 nmap = 1;
b39f9fcb 644 error = -libxfs_bmapi_write(tp, ip, bno, 1, 0, 1, &map, &nmap);
2bd0ea18
NS
645 if (error || nmap != 1) {
646 do_error(
5d1b7f0f 647 _("couldn't map realtime bitmap block %" PRIu64 ", error = %d\n"),
2bd0ea18
NS
648 bno, error);
649 }
650
651 ASSERT(map.br_startblock != HOLESTARTBLOCK);
652
12b53197 653 error = -libxfs_trans_read_buf(
2bd0ea18 654 mp, tp, mp->m_dev,
dfc130f3 655 XFS_FSB_TO_DADDR(mp, map.br_startblock),
a2ceac1f 656 XFS_FSB_TO_BB(mp, 1), 1, &bp, NULL);
2bd0ea18
NS
657
658 if (error) {
659 do_warn(
5d1b7f0f 660_("can't access block %" PRIu64 " (fsbno %" PRIu64 ") of realtime bitmap inode %" PRIu64 "\n"),
2bd0ea18
NS
661 bno, map.br_startblock, mp->m_sb.sb_rbmino);
662 return(1);
663 }
664
04338619 665 memmove(bp->b_addr, bmp, mp->m_sb.sb_blocksize);
2bd0ea18
NS
666
667 libxfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
668
ee6cd73e 669 bmp = (xfs_rtword_t *)((intptr_t) bmp + mp->m_sb.sb_blocksize);
2bd0ea18
NS
670 bno++;
671 }
672
fbbb184b 673 libxfs_trans_ijoin(tp, ip, 0);
f2279d8d
DW
674 error = -libxfs_trans_commit(tp);
675 if (error)
676 do_error(_("%s: commit failed, error %d\n"), __func__, error);
31845e4c 677 libxfs_irele(ip);
2bd0ea18
NS
678 return(0);
679}
680
8b8a6b02 681static int
2bd0ea18
NS
682fill_rsumino(xfs_mount_t *mp)
683{
684 xfs_buf_t *bp;
685 xfs_trans_t *tp;
686 xfs_inode_t *ip;
687 xfs_suminfo_t *smp;
2bd0ea18
NS
688 int nmap;
689 int error;
5a35bf2c
DC
690 xfs_fileoff_t bno;
691 xfs_fileoff_t end_bno;
2bd0ea18
NS
692 xfs_bmbt_irec_t map;
693
694 smp = sumcompute;
695 bno = 0;
696 end_bno = mp->m_rsumsize >> mp->m_sb.sb_blocklog;
697
225e4bb2 698 error = -libxfs_trans_alloc_rollable(mp, 10, &tp);
48ea6cb9 699 if (error)
2bd0ea18
NS
700 res_failed(error);
701
e2dd0e1c
DW
702 error = -libxfs_iget(mp, tp, mp->m_sb.sb_rsumino, 0, &ip,
703 &xfs_default_ifork_ops);
2bd0ea18 704 if (error) {
507f4e33
NS
705 do_error(
706 _("couldn't iget realtime summary inode -- error - %d\n"),
2bd0ea18
NS
707 error);
708 }
709
710 while (bno < end_bno) {
711 /*
712 * fill the file one block at a time
713 */
714 nmap = 1;
b39f9fcb 715 error = -libxfs_bmapi_write(tp, ip, bno, 1, 0, 1, &map, &nmap);
2bd0ea18
NS
716 if (error || nmap != 1) {
717 do_error(
5d1b7f0f 718 _("couldn't map realtime summary inode block %" PRIu64 ", error = %d\n"),
2bd0ea18
NS
719 bno, error);
720 }
721
722 ASSERT(map.br_startblock != HOLESTARTBLOCK);
723
12b53197 724 error = -libxfs_trans_read_buf(
2bd0ea18 725 mp, tp, mp->m_dev,
dfc130f3 726 XFS_FSB_TO_DADDR(mp, map.br_startblock),
a2ceac1f 727 XFS_FSB_TO_BB(mp, 1), 1, &bp, NULL);
2bd0ea18
NS
728
729 if (error) {
730 do_warn(
5d1b7f0f 731_("can't access block %" PRIu64 " (fsbno %" PRIu64 ") of realtime summary inode %" PRIu64 "\n"),
2bd0ea18 732 bno, map.br_startblock, mp->m_sb.sb_rsumino);
31845e4c 733 libxfs_irele(ip);
2bd0ea18
NS
734 return(1);
735 }
736
04338619 737 memmove(bp->b_addr, smp, mp->m_sb.sb_blocksize);
2bd0ea18
NS
738
739 libxfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
740
ee6cd73e 741 smp = (xfs_suminfo_t *)((intptr_t)smp + mp->m_sb.sb_blocksize);
2bd0ea18
NS
742 bno++;
743 }
744
fbbb184b 745 libxfs_trans_ijoin(tp, ip, 0);
f2279d8d
DW
746 error = -libxfs_trans_commit(tp);
747 if (error)
748 do_error(_("%s: commit failed, error %d\n"), __func__, error);
31845e4c 749 libxfs_irele(ip);
2bd0ea18
NS
750 return(0);
751}
752
8b8a6b02 753static void
2bd0ea18
NS
754mk_rsumino(xfs_mount_t *mp)
755{
756 xfs_trans_t *tp;
757 xfs_inode_t *ip;
758 xfs_bmbt_irec_t *ep;
2bd0ea18
NS
759 int i;
760 int nmap;
2bd0ea18
NS
761 int error;
762 int nsumblocks;
5a35bf2c 763 xfs_fileoff_t bno;
2bd0ea18 764 xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP];
41ce5f36 765 int times;
225e4bb2 766 uint blocks;
2bd0ea18
NS
767
768 /*
769 * first set up inode
770 */
9074815c 771 i = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 10, 0, 0, &tp);
48ea6cb9 772 if (i)
2bd0ea18
NS
773 res_failed(i);
774
e2dd0e1c
DW
775 error = -libxfs_iget(mp, tp, mp->m_sb.sb_rsumino, 0, &ip,
776 &xfs_default_ifork_ops);
2bd0ea18 777 if (error) {
507f4e33
NS
778 do_error(
779 _("couldn't iget realtime summary inode -- error - %d\n"),
2bd0ea18
NS
780 error);
781 }
782
138659f1 783 memset(&ip->i_d, 0, sizeof(ip->i_d));
2bd0ea18 784
e37bf53c 785 VFS_I(ip)->i_mode = S_IFREG;
2bd0ea18
NS
786 ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
787 ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
788
bcbe04c1 789 set_nlink(VFS_I(ip), 1); /* account for sb ptr */
2bd0ea18 790
41ce5f36 791 times = XFS_ICHGTIME_CHG | XFS_ICHGTIME_MOD;
fd82a87e 792 if (xfs_sb_version_has_v3inode(&mp->m_sb)) {
9abcc5cd 793 VFS_I(ip)->i_version = 1;
41ce5f36 794 ip->i_d.di_flags2 = 0;
41ce5f36
DC
795 times |= XFS_ICHGTIME_CREATE;
796 }
797 libxfs_trans_ichgtime(tp, ip, times);
798
2bd0ea18
NS
799 /*
800 * now the ifork
801 */
802 ip->i_df.if_flags = XFS_IFEXTENTS;
9685aa3e 803 ip->i_df.if_bytes = 0;
b37d753d 804 ip->i_df.if_u1.if_root = NULL;
2bd0ea18
NS
805
806 ip->i_d.di_size = mp->m_rsumsize;
807
808 /*
809 * commit changes
810 */
e2dd0e1c 811 libxfs_trans_ijoin(tp, ip, 0);
2bd0ea18 812 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
f2279d8d
DW
813 error = -libxfs_trans_commit(tp);
814 if (error)
815 do_error(_("%s: commit failed, error %d\n"), __func__, error);
2bd0ea18
NS
816
817 /*
818 * then allocate blocks for file and fill with zeroes (stolen
819 * from mkfs)
820 */
2bd0ea18 821 nsumblocks = mp->m_rsumsize >> mp->m_sb.sb_blocklog;
225e4bb2
DW
822 blocks = nsumblocks + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1;
823 error = -libxfs_trans_alloc_rollable(mp, blocks, &tp);
48ea6cb9 824 if (error)
2bd0ea18
NS
825 res_failed(error);
826
827 libxfs_trans_ijoin(tp, ip, 0);
828 bno = 0;
2bd0ea18
NS
829 while (bno < nsumblocks) {
830 nmap = XFS_BMAP_MAX_NMAP;
12b53197 831 error = -libxfs_bmapi_write(tp, ip, bno,
2bd0ea18 832 (xfs_extlen_t)(nsumblocks - bno),
b39f9fcb 833 0, nsumblocks, map, &nmap);
2bd0ea18
NS
834 if (error) {
835 do_error(
507f4e33 836 _("couldn't allocate realtime summary inode, error = %d\n"),
2bd0ea18
NS
837 error);
838 }
839 for (i = 0, ep = map; i < nmap; i++, ep++) {
75c8b434 840 libxfs_device_zero(mp->m_ddev_targp,
2bd0ea18
NS
841 XFS_FSB_TO_DADDR(mp, ep->br_startblock),
842 XFS_FSB_TO_BB(mp, ep->br_blockcount));
2bd0ea18
NS
843 bno += ep->br_blockcount;
844 }
845 }
f2279d8d
DW
846 error = -libxfs_trans_commit(tp);
847 if (error) {
848 do_error(
849 _("allocation of the realtime summary ino failed, error = %d\n"),
850 error);
851 }
31845e4c 852 libxfs_irele(ip);
2bd0ea18
NS
853}
854
855/*
856 * makes a new root directory.
857 */
8b8a6b02 858static void
2bd0ea18
NS
859mk_root_dir(xfs_mount_t *mp)
860{
861 xfs_trans_t *tp;
862 xfs_inode_t *ip;
863 int i;
864 int error;
865 const mode_t mode = 0755;
69ec88b5 866 ino_tree_node_t *irec;
41ce5f36 867 int times;
2bd0ea18 868
2bd0ea18 869 ip = NULL;
9074815c 870 i = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 10, 0, 0, &tp);
48ea6cb9 871 if (i)
2bd0ea18
NS
872 res_failed(i);
873
e2dd0e1c
DW
874 error = -libxfs_iget(mp, tp, mp->m_sb.sb_rootino, 0, &ip,
875 &xfs_default_ifork_ops);
2bd0ea18 876 if (error) {
507f4e33 877 do_error(_("could not iget root inode -- error - %d\n"), error);
2bd0ea18
NS
878 }
879
880 /*
881 * take care of the core -- initialization from xfs_ialloc()
882 */
138659f1 883 memset(&ip->i_d, 0, sizeof(ip->i_d));
2bd0ea18 884
e37bf53c 885 VFS_I(ip)->i_mode = mode|S_IFDIR;
2bd0ea18
NS
886 ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
887 ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
888
1da4e1f0 889 set_nlink(VFS_I(ip), 2); /* account for . and .. */
2bd0ea18 890
41ce5f36 891 times = XFS_ICHGTIME_CHG | XFS_ICHGTIME_MOD;
fd82a87e 892 if (xfs_sb_version_has_v3inode(&mp->m_sb)) {
9abcc5cd 893 VFS_I(ip)->i_version = 1;
41ce5f36 894 ip->i_d.di_flags2 = 0;
41ce5f36
DC
895 times |= XFS_ICHGTIME_CREATE;
896 }
897 libxfs_trans_ichgtime(tp, ip, times);
e2dd0e1c 898 libxfs_trans_ijoin(tp, ip, 0);
2bd0ea18
NS
899 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
900
901 /*
902 * now the ifork
903 */
904 ip->i_df.if_flags = XFS_IFEXTENTS;
9685aa3e 905 ip->i_df.if_bytes = 0;
b37d753d 906 ip->i_df.if_u1.if_root = NULL;
2bd0ea18 907
2bd0ea18
NS
908 /*
909 * initialize the directory
910 */
5e656dbb 911 libxfs_dir_init(tp, ip, ip);
2bd0ea18 912
f2279d8d
DW
913 error = -libxfs_trans_commit(tp);
914 if (error)
915 do_error(_("%s: commit failed, error %d\n"), __func__, error);
916
31845e4c 917 libxfs_irele(ip);
69ec88b5 918
1ae311d5 919 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino),
69ec88b5
BN
920 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino));
921 set_inode_isadir(irec, XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino) -
922 irec->ino_startnum);
2bd0ea18
NS
923}
924
925/*
926 * orphanage name == lost+found
927 */
8b8a6b02 928static xfs_ino_t
2bd0ea18
NS
929mk_orphanage(xfs_mount_t *mp)
930{
931 xfs_ino_t ino;
932 xfs_trans_t *tp;
933 xfs_inode_t *ip;
934 xfs_inode_t *pip;
198b747f
CM
935 ino_tree_node_t *irec;
936 int ino_offset = 0;
2bd0ea18 937 int i;
2bd0ea18 938 int error;
2bd0ea18 939 const int mode = 0755;
2bd0ea18 940 int nres;
5e656dbb
BN
941 struct xfs_name xname;
942
6c39a3cb
BN
943 /*
944 * check for an existing lost+found first, if it exists, return
ff1f79a7 945 * its inode. Otherwise, we can create it. Bad lost+found inodes
6c39a3cb
BN
946 * would have been cleared in phase3 and phase4.
947 */
948
12ac6e04
DW
949 i = -libxfs_iget(mp, NULL, mp->m_sb.sb_rootino, 0, &pip,
950 &xfs_default_ifork_ops);
951 if (i)
6c39a3cb
BN
952 do_error(_("%d - couldn't iget root inode to obtain %s\n"),
953 i, ORPHANAGE);
954
56b2de80 955 xname.name = (unsigned char *)ORPHANAGE;
5e656dbb 956 xname.len = strlen(ORPHANAGE);
68774b90
ES
957 xname.type = XFS_DIR3_FT_DIR;
958
5e656dbb 959 if (libxfs_dir_lookup(NULL, pip, &xname, &ino, NULL) == 0)
6c39a3cb
BN
960 return ino;
961
962 /*
963 * could not be found, create it
964 */
5e656dbb 965 nres = XFS_MKDIR_SPACE_RES(mp, xname.len);
9074815c 966 i = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_mkdir, nres, 0, 0, &tp);
48ea6cb9 967 if (i)
2bd0ea18
NS
968 res_failed(i);
969
970 /*
971 * use iget/ijoin instead of trans_iget because the ialloc
972 * wrapper can commit the transaction and start a new one
973 */
12ac6e04
DW
974/* i = -libxfs_iget(mp, NULL, mp->m_sb.sb_rootino, 0, &pip,
975 &xfs_default_ifork_ops);
976 if (i)
507f4e33 977 do_error(_("%d - couldn't iget root inode to make %s\n"),
6c39a3cb 978 i, ORPHANAGE);*/
2bd0ea18 979
12b53197 980 error = -libxfs_inode_alloc(&tp, pip, mode|S_IFDIR,
9f064b7e 981 1, 0, &zerocr, &zerofsx, &ip);
2bd0ea18 982 if (error) {
507f4e33 983 do_error(_("%s inode allocation failed %d\n"),
2bd0ea18
NS
984 ORPHANAGE, error);
985 }
bcbe04c1 986 inc_nlink(VFS_I(ip)); /* account for . */
198b747f
CM
987 ino = ip->i_ino;
988
989 irec = find_inode_rec(mp,
990 XFS_INO_TO_AGNO(mp, ino),
991 XFS_INO_TO_AGINO(mp, ino));
3ac87fbf
MT
992
993 if (irec == NULL) {
994 /*
995 * This inode is allocated from a newly created inode
996 * chunk and therefore did not exist when inode chunks
997 * were processed in phase3. Add this group of inodes to
998 * the entry avl tree as if they were discovered in phase3.
999 */
1000 irec = set_inode_free_alloc(mp, XFS_INO_TO_AGNO(mp, ino),
1001 XFS_INO_TO_AGINO(mp, ino));
1002 alloc_ex_data(irec);
1003
1004 for (i = 0; i < XFS_INODES_PER_CHUNK; i++)
1005 set_inode_free(irec, i);
1006 }
1007
198b747f
CM
1008 ino_offset = get_inode_offset(mp, ino, irec);
1009
1010 /*
1011 * Mark the inode allocated to lost+found as used in the AVL tree
1012 * so it is not skipped in phase 7
1013 */
1014 set_inode_used(irec, ino_offset);
1015 add_inode_ref(irec, ino_offset);
fe4bd71b 1016 add_inode_reached(irec, ino_offset);
2bd0ea18
NS
1017
1018 /*
1019 * now that we know the transaction will stay around,
1020 * add the root inode to it
1021 */
1022 libxfs_trans_ijoin(tp, pip, 0);
1023
1024 /*
1025 * create the actual entry
1026 */
015bc82e 1027 error = -libxfs_dir_createname(tp, pip, &xname, ip->i_ino, nres);
f8149110 1028 if (error)
6c39a3cb
BN
1029 do_error(
1030 _("can't make %s, createname error %d\n"),
2bd0ea18 1031 ORPHANAGE, error);
2bd0ea18 1032
dfc130f3 1033 /*
2bd0ea18 1034 * bump up the link count in the root directory to account
fe4bd71b
DW
1035 * for .. in the new directory, and update the irec copy of the
1036 * on-disk nlink so we don't fail the link count check later.
2bd0ea18 1037 */
bcbe04c1 1038 inc_nlink(VFS_I(pip));
fe4bd71b
DW
1039 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino),
1040 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino));
1041 add_inode_ref(irec, 0);
1042 set_inode_disk_nlinks(irec, 0, get_inode_disk_nlinks(irec, 0) + 1);
198b747f 1043
2bd0ea18 1044 libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE);
5e656dbb 1045 libxfs_dir_init(tp, ip, pip);
2bd0ea18 1046 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
f2279d8d
DW
1047 error = -libxfs_trans_commit(tp);
1048 if (error) {
1049 do_error(_("%s directory creation failed -- bmapf error %d\n"),
1050 ORPHANAGE, error);
1051 }
31845e4c
DW
1052 libxfs_irele(ip);
1053 libxfs_irele(pip);
2bd0ea18 1054
2bd0ea18
NS
1055 return(ino);
1056}
1057
1058/*
6c39a3cb 1059 * move a file to the orphange.
2bd0ea18 1060 */
6c39a3cb
BN
1061static void
1062mv_orphanage(
1063 xfs_mount_t *mp,
1064 xfs_ino_t ino, /* inode # to be moved */
1065 int isa_dir) /* 1 if inode is a directory */
2bd0ea18 1066{
2556c98b 1067 xfs_inode_t *orphanage_ip;
6c39a3cb
BN
1068 xfs_ino_t entry_ino_num;
1069 xfs_inode_t *ino_p;
1070 xfs_trans_t *tp;
6c39a3cb 1071 int err;
56b2de80 1072 unsigned char fname[MAXPATHLEN + 1];
6c39a3cb
BN
1073 int nres;
1074 int incr;
1075 ino_tree_node_t *irec;
1076 int ino_offset = 0;
5e656dbb
BN
1077 struct xfs_name xname;
1078
5e656dbb 1079 xname.name = fname;
56b2de80 1080 xname.len = snprintf((char *)fname, sizeof(fname), "%llu",
5e656dbb 1081 (unsigned long long)ino);
2bd0ea18 1082
12ac6e04
DW
1083 err = -libxfs_iget(mp, NULL, orphanage_ino, 0, &orphanage_ip,
1084 &xfs_default_ifork_ops);
2556c98b
BN
1085 if (err)
1086 do_error(_("%d - couldn't iget orphanage inode\n"), err);
6c39a3cb
BN
1087 /*
1088 * Make sure the filename is unique in the lost+found
1089 */
1090 incr = 0;
5e656dbb
BN
1091 while (libxfs_dir_lookup(NULL, orphanage_ip, &xname, &entry_ino_num,
1092 NULL) == 0)
56b2de80 1093 xname.len = snprintf((char *)fname, sizeof(fname), "%llu.%d",
5e656dbb 1094 (unsigned long long)ino, ++incr);
2bd0ea18 1095
f8cd7da8
ES
1096 /* Orphans may not have a proper parent, so use custom ops here */
1097 err = -libxfs_iget(mp, NULL, ino, 0, &ino_p, &phase6_ifork_ops);
12ac6e04 1098 if (err)
507f4e33 1099 do_error(_("%d - couldn't iget disconnected inode\n"), err);
2bd0ea18 1100
532d03d5 1101 xname.type = libxfs_mode_to_ftype(VFS_I(ino_p)->i_mode);
937ef315 1102
2bd0ea18 1103 if (isa_dir) {
1ae311d5 1104 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, orphanage_ino),
6c39a3cb
BN
1105 XFS_INO_TO_AGINO(mp, orphanage_ino));
1106 if (irec)
1107 ino_offset = XFS_INO_TO_AGINO(mp, orphanage_ino) -
1108 irec->ino_startnum;
1109 nres = XFS_DIRENTER_SPACE_RES(mp, fnamelen) +
2bd0ea18 1110 XFS_DIRENTER_SPACE_RES(mp, 2);
e5c4ab5e 1111 err = -libxfs_dir_lookup(NULL, ino_p, &xfs_name_dotdot,
5e656dbb 1112 &entry_ino_num, NULL);
6c39a3cb 1113 if (err) {
2bd0ea18
NS
1114 ASSERT(err == ENOENT);
1115
9074815c
CH
1116 err = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_rename,
1117 nres, 0, 0, &tp);
48ea6cb9 1118 if (err)
2bd0ea18 1119 do_error(
507f4e33 1120 _("space reservation failed (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1121 err);
1122
6c39a3cb 1123 libxfs_trans_ijoin(tp, orphanage_ip, 0);
2bd0ea18
NS
1124 libxfs_trans_ijoin(tp, ino_p, 0);
1125
12b53197 1126 err = -libxfs_dir_createname(tp, orphanage_ip, &xname,
015bc82e 1127 ino, nres);
5e656dbb 1128 if (err)
2bd0ea18 1129 do_error(
507f4e33 1130 _("name create failed in %s (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1131 ORPHANAGE, err);
1132
6c39a3cb
BN
1133 if (irec)
1134 add_inode_ref(irec, ino_offset);
1135 else
bcbe04c1 1136 inc_nlink(VFS_I(orphanage_ip));
6c39a3cb 1137 libxfs_trans_log_inode(tp, orphanage_ip, XFS_ILOG_CORE);
2bd0ea18 1138
12b53197 1139 err = -libxfs_dir_createname(tp, ino_p, &xfs_name_dotdot,
015bc82e 1140 orphanage_ino, nres);
5e656dbb 1141 if (err)
2bd0ea18 1142 do_error(
507f4e33 1143 _("creation of .. entry failed (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1144 err);
1145
bcbe04c1 1146 inc_nlink(VFS_I(ino_p));
2bd0ea18 1147 libxfs_trans_log_inode(tp, ino_p, XFS_ILOG_CORE);
f2279d8d
DW
1148 err = -libxfs_trans_commit(tp);
1149 if (err)
1150 do_error(
1151 _("creation of .. entry failed (%d)\n"), err);
2bd0ea18 1152 } else {
9074815c
CH
1153 err = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_rename,
1154 nres, 0, 0, &tp);
48ea6cb9 1155 if (err)
2bd0ea18 1156 do_error(
507f4e33 1157 _("space reservation failed (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1158 err);
1159
6c39a3cb 1160 libxfs_trans_ijoin(tp, orphanage_ip, 0);
2bd0ea18
NS
1161 libxfs_trans_ijoin(tp, ino_p, 0);
1162
2bd0ea18 1163
12b53197 1164 err = -libxfs_dir_createname(tp, orphanage_ip, &xname,
015bc82e 1165 ino, nres);
5e656dbb 1166 if (err)
2bd0ea18 1167 do_error(
507f4e33 1168 _("name create failed in %s (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1169 ORPHANAGE, err);
1170
6c39a3cb
BN
1171 if (irec)
1172 add_inode_ref(irec, ino_offset);
1173 else
bcbe04c1 1174 inc_nlink(VFS_I(orphanage_ip));
6c39a3cb 1175 libxfs_trans_log_inode(tp, orphanage_ip, XFS_ILOG_CORE);
2bd0ea18
NS
1176
1177 /*
1178 * don't replace .. value if it already points
1179 * to us. that'll pop a libxfs/kernel ASSERT.
1180 */
6c39a3cb 1181 if (entry_ino_num != orphanage_ino) {
12b53197 1182 err = -libxfs_dir_replace(tp, ino_p,
5e656dbb 1183 &xfs_name_dotdot, orphanage_ino,
015bc82e 1184 nres);
5e656dbb 1185 if (err)
2bd0ea18 1186 do_error(
507f4e33 1187 _("name replace op failed (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1188 err);
1189 }
1190
f2279d8d
DW
1191 err = -libxfs_trans_commit(tp);
1192 if (err)
1193 do_error(
1194 _("orphanage name replace op failed (%d)\n"), err);
2bd0ea18 1195 }
6c39a3cb 1196
2bd0ea18
NS
1197 } else {
1198 /*
1199 * use the remove log reservation as that's
1200 * more accurate. we're only creating the
1201 * links, we're not doing the inode allocation
1202 * also accounted for in the create
1203 */
5e656dbb 1204 nres = XFS_DIRENTER_SPACE_RES(mp, xname.len);
9074815c
CH
1205 err = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove,
1206 nres, 0, 0, &tp);
5e656dbb 1207 if (err)
2bd0ea18 1208 do_error(
507f4e33 1209 _("space reservation failed (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1210 err);
1211
6c39a3cb 1212 libxfs_trans_ijoin(tp, orphanage_ip, 0);
2bd0ea18
NS
1213 libxfs_trans_ijoin(tp, ino_p, 0);
1214
12b53197 1215 err = -libxfs_dir_createname(tp, orphanage_ip, &xname, ino,
015bc82e 1216 nres);
5e656dbb 1217 if (err)
2bd0ea18 1218 do_error(
507f4e33 1219 _("name create failed in %s (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1220 ORPHANAGE, err);
1221 ASSERT(err == 0);
1222
bcbe04c1 1223 set_nlink(VFS_I(ino_p), 1);
2bd0ea18 1224 libxfs_trans_log_inode(tp, ino_p, XFS_ILOG_CORE);
f2279d8d
DW
1225 err = -libxfs_trans_commit(tp);
1226 if (err)
1227 do_error(
1228 _("orphanage name create failed (%d)\n"), err);
2bd0ea18 1229 }
31845e4c
DW
1230 libxfs_irele(ino_p);
1231 libxfs_irele(orphanage_ip);
2bd0ea18
NS
1232}
1233
6c39a3cb
BN
1234static int
1235entry_junked(
1236 const char *msg,
1237 const char *iname,
1238 xfs_ino_t ino1,
1239 xfs_ino_t ino2)
1240{
1241 do_warn(msg, iname, ino1, ino2);
1242 if (!no_modify) {
1243 if (verbose)
1244 do_warn(_(", marking entry to be junked\n"));
9a048535
DC
1245 else
1246 do_warn("\n");
1247 } else
1248 do_warn(_(", would junk entry\n"));
1249 return !no_modify;
2bd0ea18
NS
1250}
1251
f9c559f4
DW
1252/* Find and invalidate all the directory's buffers. */
1253static int
1254dir_binval(
1255 struct xfs_trans *tp,
1256 struct xfs_inode *ip,
1257 int whichfork)
1258{
1259 struct xfs_iext_cursor icur;
1260 struct xfs_bmbt_irec rec;
1261 struct xfs_ifork *ifp;
1262 struct xfs_da_geometry *geo;
1263 struct xfs_buf *bp;
3f6bf952 1264 xfs_dablk_t dabno;
f9c559f4
DW
1265 int error = 0;
1266
1267 if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS &&
1268 ip->i_d.di_format != XFS_DINODE_FMT_BTREE)
1269 return 0;
1270
1271 geo = tp->t_mountp->m_dir_geo;
1272 ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
1273 for_each_xfs_iext(ifp, &icur, &rec) {
3f6bf952
DW
1274 for (dabno = roundup(rec.br_startoff, geo->fsbcount);
1275 dabno < rec.br_startoff + rec.br_blockcount;
1276 dabno += geo->fsbcount) {
f9c559f4 1277 bp = NULL;
c1d19744 1278 error = -libxfs_da_get_buf(tp, ip, dabno, &bp,
f9c559f4
DW
1279 whichfork);
1280 if (error)
1281 return error;
1282 if (!bp)
1283 continue;
1284 libxfs_trans_binval(tp, bp);
1285 libxfs_trans_brelse(tp, bp);
1286 }
1287 }
1288
1289 return error;
1290}
1291
33165ec3
BN
1292/*
1293 * Unexpected failure during the rebuild will leave the entries in
1294 * lost+found on the next run
1295 */
1296
0f012a4c 1297static void
33165ec3 1298longform_dir2_rebuild(
6fa00c33
BN
1299 xfs_mount_t *mp,
1300 xfs_ino_t ino,
1301 xfs_inode_t *ip,
1302 ino_tree_node_t *irec,
1303 int ino_offset,
1304 dir_hash_tab_t *hashtab)
33165ec3
BN
1305{
1306 int error;
1307 int nres;
1308 xfs_trans_t *tp;
1309 xfs_fileoff_t lastblock;
2556c98b 1310 xfs_inode_t pip;
33165ec3 1311 dir_hash_ent_t *p;
ea7be342 1312 int done = 0;
0f012a4c
BN
1313
1314 /*
33165ec3
BN
1315 * trash directory completely and rebuild from scratch using the
1316 * name/inode pairs in the hash table
1317 */
0f012a4c 1318
5d1b7f0f 1319 do_warn(_("rebuilding directory inode %" PRIu64 "\n"), ino);
0f012a4c
BN
1320
1321 /*
6fa00c33
BN
1322 * first attempt to locate the parent inode, if it can't be
1323 * found, set it to the root inode and it'll be moved to the
1324 * orphanage later (the inode number here needs to be valid
5e656dbb 1325 * for the libxfs_dir_init() call).
33165ec3 1326 */
6fa00c33 1327 pip.i_ino = get_inode_parent(irec, ino_offset);
01914f06 1328 if (pip.i_ino == NULLFSINO ||
e2f60652 1329 libxfs_dir_ino_validate(mp, pip.i_ino))
6fa00c33 1330 pip.i_ino = mp->m_sb.sb_rootino;
33165ec3 1331
33165ec3 1332 nres = XFS_REMOVE_SPACE_RES(mp);
9074815c 1333 error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, nres, 0, 0, &tp);
33165ec3
BN
1334 if (error)
1335 res_failed(error);
1336 libxfs_trans_ijoin(tp, ip, 0);
0f012a4c 1337
f9c559f4
DW
1338 error = dir_binval(tp, ip, XFS_DATA_FORK);
1339 if (error)
af06261f
DW
1340 do_error(_("error %d invalidating directory %llu blocks\n"),
1341 error, (unsigned long long)ip->i_ino);
f9c559f4 1342
12b53197 1343 if ((error = -libxfs_bmap_last_offset(ip, &lastblock, XFS_DATA_FORK)))
0f012a4c 1344 do_error(_("xfs_bmap_last_offset failed -- error - %d\n"),
33165ec3 1345 error);
0f012a4c 1346
33165ec3 1347 /* free all data, leaf, node and freespace blocks */
ea7be342
ES
1348 while (!done) {
1349 error = -libxfs_bunmapi(tp, ip, 0, lastblock, XFS_BMAPI_METADATA,
1350 0, &done);
1351 if (error) {
1352 do_warn(_("xfs_bunmapi failed -- error - %d\n"), error);
1353 goto out_bmap_cancel;
1354 }
1355 error = -libxfs_defer_finish(&tp);
1356 if (error) {
1357 do_warn(("defer_finish failed -- error - %d\n"), error);
1358 goto out_bmap_cancel;
1359 }
1360 /*
1361 * Close out trans and start the next one in the chain.
1362 */
1363 error = -libxfs_trans_roll_inode(&tp, ip);
1364 if (error)
1365 goto out_bmap_cancel;
1366 }
33165ec3 1367
e2f60652 1368 error = -libxfs_dir_init(tp, ip, &pip);
01914f06
DW
1369 if (error) {
1370 do_warn(_("xfs_dir_init failed -- error - %d\n"), error);
1371 goto out_bmap_cancel;
1372 }
0f012a4c 1373
f2279d8d
DW
1374 error = -libxfs_trans_commit(tp);
1375 if (error)
1376 do_error(
1377 _("dir init failed (%d)\n"), error);
0f012a4c 1378
1f60de28
ES
1379 if (ino == mp->m_sb.sb_rootino)
1380 need_root_dotdot = 0;
1381
33165ec3
BN
1382 /* go through the hash list and re-add the inodes */
1383
1384 for (p = hashtab->first; p; p = p->nextbyorder) {
0f012a4c 1385
5e656dbb
BN
1386 if (p->name.name[0] == '/' || (p->name.name[0] == '.' &&
1387 (p->name.len == 1 || (p->name.len == 2 &&
1388 p->name.name[1] == '.'))))
33165ec3 1389 continue;
0f012a4c 1390
5e656dbb 1391 nres = XFS_CREATE_SPACE_RES(mp, p->name.len);
9074815c
CH
1392 error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_create,
1393 nres, 0, 0, &tp);
14e36e34
LZ
1394 if (error)
1395 res_failed(error);
33165ec3
BN
1396
1397 libxfs_trans_ijoin(tp, ip, 0);
33165ec3 1398
12b53197 1399 error = -libxfs_dir_createname(tp, ip, &p->name, p->inum,
015bc82e 1400 nres);
5e656dbb 1401 if (error) {
33165ec3 1402 do_warn(
5d1b7f0f 1403_("name create failed in ino %" PRIu64 " (%d), filesystem may be out of space\n"),
33165ec3 1404 ino, error);
14e36e34 1405 goto out_bmap_cancel;
33165ec3
BN
1406 }
1407
f2279d8d
DW
1408 error = -libxfs_trans_commit(tp);
1409 if (error)
1410 do_error(
1411_("name create failed (%d) during rebuild\n"), error);
33165ec3 1412 }
14e36e34
LZ
1413
1414 return;
1415
1416out_bmap_cancel:
3d7434fe 1417 libxfs_trans_cancel(tp);
14e36e34 1418 return;
33165ec3
BN
1419}
1420
1421
2bd0ea18
NS
1422/*
1423 * Kill a block in a version 2 inode.
1424 * Makes its own transaction.
1425 */
1426static void
1427dir2_kill_block(
1428 xfs_mount_t *mp,
1429 xfs_inode_t *ip,
1430 xfs_dablk_t da_bno,
a2ceac1f 1431 struct xfs_buf *bp)
2bd0ea18
NS
1432{
1433 xfs_da_args_t args;
2bd0ea18 1434 int error;
2bd0ea18
NS
1435 int nres;
1436 xfs_trans_t *tp;
1437
2bd0ea18 1438 nres = XFS_REMOVE_SPACE_RES(mp);
9074815c 1439 error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, nres, 0, 0, &tp);
2bd0ea18
NS
1440 if (error)
1441 res_failed(error);
1442 libxfs_trans_ijoin(tp, ip, 0);
a2ceac1f 1443 libxfs_trans_bjoin(tp, bp);
dab9b8d6 1444 memset(&args, 0, sizeof(args));
2bd0ea18
NS
1445 args.dp = ip;
1446 args.trans = tp;
2bd0ea18 1447 args.whichfork = XFS_DATA_FORK;
fe0591e7 1448 args.geo = mp->m_dir_geo;
ff105f75 1449 if (da_bno >= mp->m_dir_geo->leafblk && da_bno < mp->m_dir_geo->freeblk)
12b53197 1450 error = -libxfs_da_shrink_inode(&args, da_bno, bp);
2bd0ea18 1451 else
12b53197 1452 error = -libxfs_dir2_shrink_inode(&args,
ff105f75 1453 xfs_dir2_da_to_db(mp->m_dir_geo, da_bno), bp);
2bd0ea18 1454 if (error)
5d1b7f0f 1455 do_error(_("shrink_inode failed inode %" PRIu64 " block %u\n"),
2bd0ea18 1456 ip->i_ino, da_bno);
f2279d8d
DW
1457 error = -libxfs_trans_commit(tp);
1458 if (error)
1459 do_error(
1460_("directory shrink failed (%d)\n"), error);
2bd0ea18
NS
1461}
1462
1463/*
1464 * process a data block, also checks for .. entry
1465 * and corrects it to match what we think .. should be
1466 */
1467static void
1468longform_dir2_entry_check_data(
1469 xfs_mount_t *mp,
1470 xfs_inode_t *ip,
1471 int *num_illegal,
1472 int *need_dot,
2bd0ea18
NS
1473 ino_tree_node_t *current_irec,
1474 int current_ino_offset,
a2ceac1f 1475 struct xfs_buf **bpp,
2bd0ea18
NS
1476 dir_hash_tab_t *hashtab,
1477 freetab_t **freetabp,
1478 xfs_dablk_t da_bno,
1479 int isblock)
1480{
1481 xfs_dir2_dataptr_t addr;
1482 xfs_dir2_leaf_entry_t *blp;
a2ceac1f 1483 struct xfs_buf *bp;
2bd0ea18 1484 xfs_dir2_block_tail_t *btp;
a354abc8 1485 struct xfs_dir2_data_hdr *d;
2bd0ea18
NS
1486 xfs_dir2_db_t db;
1487 xfs_dir2_data_entry_t *dep;
1488 xfs_dir2_data_unused_t *dup;
d2006f04 1489 struct xfs_dir2_data_free *bf;
2bd0ea18
NS
1490 char *endptr;
1491 int error;
2bd0ea18
NS
1492 char fname[MAXNAMELEN + 1];
1493 freetab_t *freetab;
1494 int i;
1495 int ino_offset;
33165ec3 1496 xfs_ino_t inum;
2bd0ea18
NS
1497 ino_tree_node_t *irec;
1498 int junkit;
1499 int lastfree;
1500 int len;
1501 int nbad;
1502 int needlog;
1503 int needscan;
1504 xfs_ino_t parent;
1505 char *ptr;
1506 xfs_trans_t *tp;
1507 int wantmagic;
ff105f75
DC
1508 struct xfs_da_args da = {
1509 .dp = ip,
a5459506 1510 .geo = mp->m_dir_geo,
ff105f75
DC
1511 };
1512
2bd0ea18
NS
1513
1514 bp = *bpp;
a2ceac1f 1515 d = bp->b_addr;
58a1d356 1516 ptr = (char *)d + mp->m_dir_geo->data_entry_offset;
2bd0ea18
NS
1517 nbad = 0;
1518 needscan = needlog = 0;
9d7d6241 1519 junkit = 0;
2bd0ea18
NS
1520 freetab = *freetabp;
1521 if (isblock) {
ff105f75 1522 btp = xfs_dir2_block_tail_p(mp->m_dir_geo, d);
5e656dbb 1523 blp = xfs_dir2_block_leaf_p(btp);
2bd0ea18
NS
1524 endptr = (char *)blp;
1525 if (endptr > (char *)btp)
1526 endptr = (char *)btp;
658ac3e3
DC
1527 if (xfs_sb_version_hascrc(&mp->m_sb))
1528 wantmagic = XFS_DIR3_BLOCK_MAGIC;
1529 else
1530 wantmagic = XFS_DIR2_BLOCK_MAGIC;
2bd0ea18 1531 } else {
ff105f75 1532 endptr = (char *)d + mp->m_dir_geo->blksize;
658ac3e3
DC
1533 if (xfs_sb_version_hascrc(&mp->m_sb))
1534 wantmagic = XFS_DIR3_DATA_MAGIC;
1535 else
1536 wantmagic = XFS_DIR2_DATA_MAGIC;
2bd0ea18 1537 }
ff105f75 1538 db = xfs_dir2_da_to_db(mp->m_dir_geo, da_bno);
9d7d6241
NS
1539
1540 /* check for data block beyond expected end */
2bd0ea18
NS
1541 if (freetab->naents <= db) {
1542 struct freetab_ent e;
1543
1544 *freetabp = freetab = realloc(freetab, FREETAB_SIZE(db + 1));
1545 if (!freetab) {
15e3986b
DC
1546 do_error(_("realloc failed in %s (%zu bytes)\n"),
1547 __func__, FREETAB_SIZE(db + 1));
2bd0ea18
NS
1548 }
1549 e.v = NULLDATAOFF;
1550 e.s = 0;
1551 for (i = freetab->naents; i < db; i++)
1552 freetab->ents[i] = e;
1553 freetab->naents = db + 1;
1554 }
9d7d6241
NS
1555
1556 /* check the data block */
2bd0ea18 1557 while (ptr < endptr) {
9d7d6241
NS
1558
1559 /* check for freespace */
2bd0ea18 1560 dup = (xfs_dir2_data_unused_t *)ptr;
5e656dbb 1561 if (XFS_DIR2_DATA_FREE_TAG == be16_to_cpu(dup->freetag)) {
9d7d6241
NS
1562
1563 /* check for invalid freespace length */
5e656dbb
BN
1564 if (ptr + be16_to_cpu(dup->length) > endptr ||
1565 be16_to_cpu(dup->length) == 0 ||
1566 (be16_to_cpu(dup->length) &
1567 (XFS_DIR2_DATA_ALIGN - 1)))
2bd0ea18 1568 break;
9d7d6241
NS
1569
1570 /* check for invalid tag */
5e656dbb
BN
1571 if (be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) !=
1572 (char *)dup - (char *)d)
2bd0ea18 1573 break;
9d7d6241
NS
1574
1575 /* check for block with no data entries */
58a1d356 1576 if ((ptr == (char *)d + mp->m_dir_geo->data_entry_offset) &&
658ac3e3 1577 (ptr + be16_to_cpu(dup->length) >= endptr)) {
9d7d6241
NS
1578 junkit = 1;
1579 *num_illegal += 1;
1580 break;
1581 }
1582
1583 /* continue at the end of the freespace */
5e656dbb 1584 ptr += be16_to_cpu(dup->length);
2bd0ea18
NS
1585 if (ptr >= endptr)
1586 break;
1587 }
9d7d6241
NS
1588
1589 /* validate data entry size */
2bd0ea18 1590 dep = (xfs_dir2_data_entry_t *)ptr;
271a654f 1591 if (ptr + libxfs_dir2_data_entsize(mp, dep->namelen) > endptr)
2bd0ea18 1592 break;
823711f2 1593 if (be16_to_cpu(*libxfs_dir2_data_entry_tag_p(mp, dep)) !=
5e656dbb 1594 (char *)dep - (char *)d)
2bd0ea18 1595 break;
271a654f 1596 ptr += libxfs_dir2_data_entsize(mp, dep->namelen);
2bd0ea18 1597 }
9d7d6241
NS
1598
1599 /* did we find an empty or corrupt block? */
2bd0ea18 1600 if (ptr != endptr) {
9d7d6241 1601 if (junkit) {
507f4e33 1602 do_warn(
5d1b7f0f 1603 _("empty data block %u in directory inode %" PRIu64 ": "),
9d7d6241
NS
1604 da_bno, ip->i_ino);
1605 } else {
5d1b7f0f
CH
1606 do_warn(_
1607 ("corrupt block %u in directory inode %" PRIu64 ": "),
9d7d6241
NS
1608 da_bno, ip->i_ino);
1609 }
2bd0ea18 1610 if (!no_modify) {
507f4e33 1611 do_warn(_("junking block\n"));
2bd0ea18
NS
1612 dir2_kill_block(mp, ip, da_bno, bp);
1613 } else {
507f4e33 1614 do_warn(_("would junk block\n"));
e02ba985 1615 libxfs_buf_relse(bp);
2bd0ea18
NS
1616 }
1617 freetab->ents[db].v = NULLDATAOFF;
1618 *bpp = NULL;
1619 return;
1620 }
9d7d6241
NS
1621
1622 /* update number of data blocks processed */
1623 if (freetab->nents < db + 1)
1624 freetab->nents = db + 1;
1625
9074815c 1626 error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, 0, 0, 0, &tp);
2bd0ea18
NS
1627 if (error)
1628 res_failed(error);
ff105f75 1629 da.trans = tp;
2bd0ea18 1630 libxfs_trans_ijoin(tp, ip, 0);
a2ceac1f
DC
1631 libxfs_trans_bjoin(tp, bp);
1632 libxfs_trans_bhold(tp, bp);
a354abc8 1633 if (be32_to_cpu(d->magic) != wantmagic) {
5d1b7f0f
CH
1634 do_warn(
1635 _("bad directory block magic # %#x for directory inode %" PRIu64 " block %d: "),
a354abc8 1636 be32_to_cpu(d->magic), ip->i_ino, da_bno);
2bd0ea18 1637 if (!no_modify) {
507f4e33 1638 do_warn(_("fixing magic # to %#x\n"), wantmagic);
a354abc8 1639 d->magic = cpu_to_be32(wantmagic);
2bd0ea18
NS
1640 needlog = 1;
1641 } else
507f4e33 1642 do_warn(_("would fix magic # to %#x\n"), wantmagic);
2bd0ea18
NS
1643 }
1644 lastfree = 0;
58a1d356 1645 ptr = (char *)d + mp->m_dir_geo->data_entry_offset;
2bd0ea18
NS
1646 /*
1647 * look at each entry. reference inode pointed to by each
1648 * entry in the incore inode tree.
1649 * if not a directory, set reached flag, increment link count
1650 * if a directory and reached, mark entry as to be deleted.
1651 * if a directory, check to see if recorded parent
1652 * matches current inode #,
1653 * if so, then set reached flag, increment link count
1654 * of current and child dir inodes, push the child
1655 * directory inode onto the directory stack.
1656 * if current inode != parent, then mark entry to be deleted.
1657 */
1658 while (ptr < endptr) {
1659 dup = (xfs_dir2_data_unused_t *)ptr;
5e656dbb 1660 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
2bd0ea18 1661 if (lastfree) {
5d1b7f0f
CH
1662 do_warn(
1663 _("directory inode %" PRIu64 " block %u has consecutive free entries: "),
2bd0ea18
NS
1664 ip->i_ino, da_bno);
1665 if (!no_modify) {
ff105f75 1666
507f4e33 1667 do_warn(_("joining together\n"));
5e656dbb 1668 len = be16_to_cpu(dup->length);
ff105f75 1669 libxfs_dir2_data_use_free(&da, bp, dup,
2bd0ea18
NS
1670 ptr - (char *)d, len, &needlog,
1671 &needscan);
ff105f75 1672 libxfs_dir2_data_make_free(&da, bp,
2bd0ea18
NS
1673 ptr - (char *)d, len, &needlog,
1674 &needscan);
1675 } else
507f4e33 1676 do_warn(_("would join together\n"));
2bd0ea18 1677 }
5e656dbb 1678 ptr += be16_to_cpu(dup->length);
2bd0ea18
NS
1679 lastfree = 1;
1680 continue;
1681 }
ff105f75
DC
1682 addr = xfs_dir2_db_off_to_dataptr(mp->m_dir_geo, db,
1683 ptr - (char *)d);
2bd0ea18 1684 dep = (xfs_dir2_data_entry_t *)ptr;
271a654f 1685 ptr += libxfs_dir2_data_entsize(mp, dep->namelen);
5e656dbb 1686 inum = be64_to_cpu(dep->inumber);
2bd0ea18 1687 lastfree = 0;
2bd0ea18
NS
1688 /*
1689 * skip bogus entries (leading '/'). they'll be deleted
c7f277c9
NS
1690 * later. must still log it, else we leak references to
1691 * buffers.
2bd0ea18
NS
1692 */
1693 if (dep->name[0] == '/') {
1694 nbad++;
c7f277c9 1695 if (!no_modify)
ff105f75 1696 libxfs_dir2_data_log_entry(&da, bp, dep);
2bd0ea18
NS
1697 continue;
1698 }
2556c98b 1699
dab9b8d6 1700 memmove(fname, dep->name, dep->namelen);
2bd0ea18 1701 fname[dep->namelen] = '\0';
33165ec3 1702 ASSERT(inum != NULLFSINO);
6c39a3cb 1703
1ae311d5 1704 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, inum),
6c39a3cb
BN
1705 XFS_INO_TO_AGINO(mp, inum));
1706 if (irec == NULL) {
1707 nbad++;
5d1b7f0f
CH
1708 if (entry_junked(
1709 _("entry \"%s\" in directory inode %" PRIu64 " points to non-existent inode %" PRIu64 ""),
6c39a3cb
BN
1710 fname, ip->i_ino, inum)) {
1711 dep->name[0] = '/';
ff105f75 1712 libxfs_dir2_data_log_entry(&da, bp, dep);
6c39a3cb
BN
1713 }
1714 continue;
1715 }
1716 ino_offset = XFS_INO_TO_AGINO(mp, inum) - irec->ino_startnum;
1717
1718 /*
1719 * if it's a free inode, blow out the entry.
1720 * by now, any inode that we think is free
1721 * really is free.
1722 */
1723 if (is_inode_free(irec, ino_offset)) {
1724 nbad++;
5d1b7f0f 1725 if (entry_junked(
b52923f3 1726 _("entry \"%s\" in directory inode %" PRIu64 " points to free inode %" PRIu64),
6c39a3cb
BN
1727 fname, ip->i_ino, inum)) {
1728 dep->name[0] = '/';
ff105f75 1729 libxfs_dir2_data_log_entry(&da, bp, dep);
6c39a3cb
BN
1730 }
1731 continue;
1732 }
1733
1734 /*
1735 * check if this inode is lost+found dir in the root
1736 */
1737 if (inum == mp->m_sb.sb_rootino && strcmp(fname, ORPHANAGE) == 0) {
1738 /*
1739 * if it's not a directory, trash it
1740 */
1741 if (!inode_isadir(irec, ino_offset)) {
1742 nbad++;
5d1b7f0f
CH
1743 if (entry_junked(
1744 _("%s (ino %" PRIu64 ") in root (%" PRIu64 ") is not a directory"),
6c39a3cb
BN
1745 ORPHANAGE, inum, ip->i_ino)) {
1746 dep->name[0] = '/';
ff105f75 1747 libxfs_dir2_data_log_entry(&da, bp, dep);
6c39a3cb
BN
1748 }
1749 continue;
1750 }
1751 /*
1752 * if this is a dup, it will be picked up below,
1753 * otherwise, mark it as the orphanage for later.
1754 */
1755 if (!orphanage_ino)
1756 orphanage_ino = inum;
1757 }
aaca101b 1758
6c39a3cb
BN
1759 /*
1760 * check for duplicate names in directory.
1761 */
51ca7008 1762 if (!dir_hash_add(mp, hashtab, addr, inum, dep->namelen,
28e6e614 1763 dep->name, libxfs_dir2_data_get_ftype(mp, dep))) {
6c39a3cb 1764 nbad++;
5d1b7f0f
CH
1765 if (entry_junked(
1766 _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"),
6c39a3cb
BN
1767 fname, inum, ip->i_ino)) {
1768 dep->name[0] = '/';
ff105f75 1769 libxfs_dir2_data_log_entry(&da, bp, dep);
6c39a3cb
BN
1770 }
1771 if (inum == orphanage_ino)
1772 orphanage_ino = 0;
1773 continue;
1774 }
1775
575ca697
BN
1776 /*
1777 * if just scanning to rebuild a directory due to a ".."
1778 * update, just continue
1779 */
1780 if (dotdot_update)
1781 continue;
1782
2bd0ea18
NS
1783 /*
1784 * skip the '..' entry since it's checked when the
1785 * directory is reached by something else. if it never
1786 * gets reached, it'll be moved to the orphanage and we'll
6fa00c33
BN
1787 * take care of it then. If it doesn't exist at all, the
1788 * directory needs to be rebuilt first before being added
1789 * to the orphanage.
2bd0ea18
NS
1790 */
1791 if (dep->namelen == 2 && dep->name[0] == '.' &&
6fa00c33
BN
1792 dep->name[1] == '.') {
1793 if (da_bno != 0) {
1794 /* ".." should be in the first block */
1795 nbad++;
5d1b7f0f
CH
1796 if (entry_junked(
1797 _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is not in the the first block"), fname,
6fa00c33
BN
1798 inum, ip->i_ino)) {
1799 dep->name[0] = '/';
ff105f75 1800 libxfs_dir2_data_log_entry(&da, bp, dep);
6fa00c33
BN
1801 }
1802 }
2bd0ea18 1803 continue;
6fa00c33 1804 }
017e979e 1805 ASSERT(no_modify || libxfs_verify_dir_ino(mp, inum));
2bd0ea18
NS
1806 /*
1807 * special case the . entry. we know there's only one
1808 * '.' and only '.' points to itself because bogus entries
1809 * got trashed in phase 3 if there were > 1.
1810 * bump up link count for '.' but don't set reached
1811 * until we're actually reached by another directory
1812 * '..' is already accounted for or will be taken care
1813 * of when directory is moved to orphanage.
1814 */
33165ec3 1815 if (ip->i_ino == inum) {
369c0b5f
DW
1816 ASSERT(no_modify ||
1817 (dep->name[0] == '.' && dep->namelen == 1));
2bd0ea18 1818 add_inode_ref(current_irec, current_ino_offset);
658ac3e3 1819 if (da_bno != 0 ||
58a1d356 1820 dep != (void *)d + mp->m_dir_geo->data_entry_offset) {
6fa00c33
BN
1821 /* "." should be the first entry */
1822 nbad++;
5d1b7f0f
CH
1823 if (entry_junked(
1824 _("entry \"%s\" in dir %" PRIu64 " is not the first entry"),
6fa00c33
BN
1825 fname, inum, ip->i_ino)) {
1826 dep->name[0] = '/';
ff105f75 1827 libxfs_dir2_data_log_entry(&da, bp, dep);
6fa00c33
BN
1828 }
1829 }
2bd0ea18
NS
1830 *need_dot = 0;
1831 continue;
1832 }
2bd0ea18
NS
1833 /*
1834 * skip entries with bogus inumbers if we're in no modify mode
1835 */
017e979e 1836 if (no_modify && !libxfs_verify_dir_ino(mp, inum))
2bd0ea18 1837 continue;
aaca101b
DC
1838
1839 /* validate ftype field if supported */
1840 if (xfs_sb_version_hasftype(&mp->m_sb)) {
14f8b681
DW
1841 uint8_t dir_ftype;
1842 uint8_t ino_ftype;
aaca101b 1843
28e6e614 1844 dir_ftype = libxfs_dir2_data_get_ftype(mp, dep);
aaca101b
DC
1845 ino_ftype = get_inode_ftype(irec, ino_offset);
1846
1847 if (dir_ftype != ino_ftype) {
1848 if (no_modify) {
1849 do_warn(
1850 _("would fix ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"),
1851 dir_ftype, ino_ftype,
1852 ip->i_ino, inum);
1853 } else {
1854 do_warn(
1855 _("fixing ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"),
1856 dir_ftype, ino_ftype,
1857 ip->i_ino, inum);
28e6e614 1858 libxfs_dir2_data_put_ftype(mp, dep, ino_ftype);
ff105f75 1859 libxfs_dir2_data_log_entry(&da, bp, dep);
aaca101b
DC
1860 dir_hash_update_ftype(hashtab, addr,
1861 ino_ftype);
1862 }
1863 }
1864 }
1865
2bd0ea18
NS
1866 /*
1867 * check easy case first, regular inode, just bump
1868 * the link count and continue
1869 */
1870 if (!inode_isadir(irec, ino_offset)) {
1871 add_inode_reached(irec, ino_offset);
1872 continue;
1873 }
1874 parent = get_inode_parent(irec, ino_offset);
1875 ASSERT(parent != 0);
6c39a3cb 1876 junkit = 0;
2bd0ea18
NS
1877 /*
1878 * bump up the link counts in parent and child
1879 * directory but if the link doesn't agree with
1880 * the .. in the child, blow out the entry.
1881 * if the directory has already been reached,
1882 * blow away the entry also.
1883 */
1884 if (is_inode_reached(irec, ino_offset)) {
1885 junkit = 1;
507f4e33 1886 do_warn(
5d1b7f0f 1887_("entry \"%s\" in dir %" PRIu64" points to an already connected directory inode %" PRIu64 "\n"),
33165ec3 1888 fname, ip->i_ino, inum);
2bd0ea18
NS
1889 } else if (parent == ip->i_ino) {
1890 add_inode_reached(irec, ino_offset);
1891 add_inode_ref(current_irec, current_ino_offset);
6fa00c33
BN
1892 } else if (parent == NULLFSINO) {
1893 /* ".." was missing, but this entry refers to it,
1894 so, set it as the parent and mark for rebuild */
5d1b7f0f
CH
1895 do_warn(
1896 _("entry \"%s\" in dir ino %" PRIu64 " doesn't have a .. entry, will set it in ino %" PRIu64 ".\n"),
6fa00c33
BN
1897 fname, ip->i_ino, inum);
1898 set_inode_parent(irec, ino_offset, ip->i_ino);
1899 add_inode_reached(irec, ino_offset);
1900 add_inode_ref(current_irec, current_ino_offset);
575ca697
BN
1901 add_dotdot_update(XFS_INO_TO_AGNO(mp, inum), irec,
1902 ino_offset);
2bd0ea18
NS
1903 } else {
1904 junkit = 1;
507f4e33 1905 do_warn(
5d1b7f0f 1906_("entry \"%s\" in dir inode %" PRIu64 " inconsistent with .. value (%" PRIu64 ") in ino %" PRIu64 "\n"),
33165ec3 1907 fname, ip->i_ino, parent, inum);
2bd0ea18
NS
1908 }
1909 if (junkit) {
6c39a3cb
BN
1910 if (inum == orphanage_ino)
1911 orphanage_ino = 0;
2bd0ea18
NS
1912 nbad++;
1913 if (!no_modify) {
1914 dep->name[0] = '/';
ff105f75 1915 libxfs_dir2_data_log_entry(&da, bp, dep);
6c39a3cb 1916 if (verbose)
507f4e33
NS
1917 do_warn(
1918 _("\twill clear entry \"%s\"\n"),
2bd0ea18
NS
1919 fname);
1920 } else {
507f4e33
NS
1921 do_warn(_("\twould clear entry \"%s\"\n"),
1922 fname);
2bd0ea18
NS
1923 }
1924 }
1925 }
1926 *num_illegal += nbad;
1927 if (needscan)
d85595d0 1928 libxfs_dir2_data_freescan(mp, d, &i);
2bd0ea18 1929 if (needlog)
ff105f75 1930 libxfs_dir2_data_log_header(&da, bp);
f2279d8d
DW
1931 error = -libxfs_trans_commit(tp);
1932 if (error)
1933 do_error(
1934_("directory block fixing failed (%d)\n"), error);
d2006f04
DC
1935
1936 /* record the largest free space in the freetab for later checking */
04f6f354 1937 bf = libxfs_dir2_data_bestfree_p(mp, d);
d2006f04 1938 freetab->ents[db].v = be16_to_cpu(bf[0].length);
2bd0ea18
NS
1939 freetab->ents[db].s = 0;
1940}
1941
0519f662
DW
1942/* check v5 metadata */
1943static int
1944__check_dir3_header(
1945 struct xfs_mount *mp,
1946 struct xfs_buf *bp,
1947 xfs_ino_t ino,
1948 __be64 owner,
1949 __be64 blkno,
1950 uuid_t *uuid)
1951{
1952
1953 /* verify owner */
1954 if (be64_to_cpu(owner) != ino) {
1955 do_warn(
1956_("expected owner inode %" PRIu64 ", got %llu, directory block %" PRIu64 "\n"),
51073f86 1957 ino, (unsigned long long)be64_to_cpu(owner), bp->b_bn);
0519f662
DW
1958 return 1;
1959 }
1960 /* verify block number */
1961 if (be64_to_cpu(blkno) != bp->b_bn) {
1962 do_warn(
1963_("expected block %" PRIu64 ", got %llu, directory inode %" PRIu64 "\n"),
51073f86 1964 bp->b_bn, (unsigned long long)be64_to_cpu(blkno), ino);
0519f662
DW
1965 return 1;
1966 }
1967 /* verify uuid */
f31982ae 1968 if (platform_uuid_compare(uuid, &mp->m_sb.sb_meta_uuid) != 0) {
0519f662
DW
1969 do_warn(
1970_("wrong FS UUID, directory inode %" PRIu64 " block %" PRIu64 "\n"),
1971 ino, bp->b_bn);
1972 return 1;
1973 }
1974
1975 return 0;
1976}
1977
1978static int
1979check_da3_header(
1980 struct xfs_mount *mp,
1981 struct xfs_buf *bp,
1982 xfs_ino_t ino)
1983{
1984 struct xfs_da3_blkinfo *info = bp->b_addr;
1985
1986 return __check_dir3_header(mp, bp, ino, info->owner, info->blkno,
1987 &info->uuid);
1988}
1989
1990static int
1991check_dir3_header(
1992 struct xfs_mount *mp,
1993 struct xfs_buf *bp,
1994 xfs_ino_t ino)
1995{
1996 struct xfs_dir3_blk_hdr *info = bp->b_addr;
1997
1998 return __check_dir3_header(mp, bp, ino, info->owner, info->blkno,
1999 &info->uuid);
2000}
2001
2bd0ea18
NS
2002/*
2003 * Check contents of leaf-form block.
2004 */
2556c98b 2005static int
2bd0ea18
NS
2006longform_dir2_check_leaf(
2007 xfs_mount_t *mp,
2008 xfs_inode_t *ip,
2009 dir_hash_tab_t *hashtab,
2010 freetab_t *freetab)
2011{
2012 int badtail;
5e656dbb 2013 __be16 *bestsp;
a2ceac1f 2014 struct xfs_buf *bp;
2bd0ea18
NS
2015 xfs_dablk_t da_bno;
2016 int i;
2017 xfs_dir2_leaf_t *leaf;
2018 xfs_dir2_leaf_tail_t *ltp;
2019 int seeval;
65b80c98 2020 struct xfs_dir2_leaf_entry *ents;
658ac3e3 2021 struct xfs_dir3_icleaf_hdr leafhdr;
8e7e14be
DC
2022 int error;
2023 int fixit = 0;
2bd0ea18 2024
ff105f75 2025 da_bno = mp->m_dir_geo->leafblk;
db8e6401 2026 error = dir_read_buf(ip, da_bno, &bp, &xfs_dir3_leaf1_buf_ops, &fixit);
ba1c6776
DW
2027 if (error == EFSBADCRC || error == EFSCORRUPTED || fixit) {
2028 do_warn(
2029 _("leaf block %u for directory inode %" PRIu64 " bad CRC\n"),
2030 da_bno, ip->i_ino);
2031 return 1;
2032 } else if (error) {
5d1b7f0f 2033 do_error(
8e7e14be
DC
2034 _("can't read block %u for directory inode %" PRIu64 ", error %d\n"),
2035 da_bno, ip->i_ino, error);
2bd0ea18
NS
2036 /* NOTREACHED */
2037 }
8e7e14be 2038
a2ceac1f 2039 leaf = bp->b_addr;
9db68faf 2040 libxfs_dir2_leaf_hdr_from_disk(mp, &leafhdr, leaf);
a2279497 2041 ents = leafhdr.ents;
ff105f75 2042 ltp = xfs_dir2_leaf_tail_p(mp->m_dir_geo, leaf);
5e656dbb 2043 bestsp = xfs_dir2_leaf_bests_p(ltp);
658ac3e3
DC
2044 if (!(leafhdr.magic == XFS_DIR2_LEAF1_MAGIC ||
2045 leafhdr.magic == XFS_DIR3_LEAF1_MAGIC) ||
2046 leafhdr.forw || leafhdr.back ||
5eb1ac90 2047 leafhdr.count < leafhdr.stale ||
d106a3e0 2048 leafhdr.count > mp->m_dir_geo->leaf_max_ents ||
658ac3e3 2049 (char *)&ents[leafhdr.count] > (char *)bestsp) {
507f4e33 2050 do_warn(
5d1b7f0f 2051 _("leaf block %u for directory inode %" PRIu64 " bad header\n"),
2bd0ea18 2052 da_bno, ip->i_ino);
e02ba985 2053 libxfs_buf_relse(bp);
2bd0ea18
NS
2054 return 1;
2055 }
0519f662
DW
2056
2057 if (leafhdr.magic == XFS_DIR3_LEAF1_MAGIC) {
2058 error = check_da3_header(mp, bp, ip->i_ino);
2059 if (error) {
e02ba985 2060 libxfs_buf_relse(bp);
0519f662
DW
2061 return error;
2062 }
2063 }
2064
658ac3e3 2065 seeval = dir_hash_see_all(hashtab, ents, leafhdr.count, leafhdr.stale);
2bd0ea18 2066 if (dir_hash_check(hashtab, ip, seeval)) {
e02ba985 2067 libxfs_buf_relse(bp);
2bd0ea18
NS
2068 return 1;
2069 }
5e656dbb
BN
2070 badtail = freetab->nents != be32_to_cpu(ltp->bestcount);
2071 for (i = 0; !badtail && i < be32_to_cpu(ltp->bestcount); i++) {
2bd0ea18 2072 freetab->ents[i].s = 1;
5e656dbb 2073 badtail = freetab->ents[i].v != be16_to_cpu(bestsp[i]);
2bd0ea18
NS
2074 }
2075 if (badtail) {
5d1b7f0f
CH
2076 do_warn(
2077 _("leaf block %u for directory inode %" PRIu64 " bad tail\n"),
2bd0ea18 2078 da_bno, ip->i_ino);
e02ba985 2079 libxfs_buf_relse(bp);
2bd0ea18
NS
2080 return 1;
2081 }
e02ba985 2082 libxfs_buf_relse(bp);
8e7e14be 2083 return fixit;
2bd0ea18
NS
2084}
2085
2086/*
2087 * Check contents of the node blocks (leaves)
2088 * Looks for matching hash values for the data entries.
2089 */
2556c98b 2090static int
2bd0ea18
NS
2091longform_dir2_check_node(
2092 xfs_mount_t *mp,
2093 xfs_inode_t *ip,
2094 dir_hash_tab_t *hashtab,
2095 freetab_t *freetab)
2096{
a2ceac1f 2097 struct xfs_buf *bp;
2bd0ea18
NS
2098 xfs_dablk_t da_bno;
2099 xfs_dir2_db_t fdb;
2100 xfs_dir2_free_t *free;
2101 int i;
2102 xfs_dir2_leaf_t *leaf;
2103 xfs_fileoff_t next_da_bno;
2104 int seeval = 0;
2105 int used;
65b80c98 2106 struct xfs_dir2_leaf_entry *ents;
658ac3e3
DC
2107 struct xfs_dir3_icleaf_hdr leafhdr;
2108 struct xfs_dir3_icfree_hdr freehdr;
2109 __be16 *bests;
8e7e14be
DC
2110 int error;
2111 int fixit = 0;
0f012a4c 2112
ff105f75
DC
2113 for (da_bno = mp->m_dir_geo->leafblk, next_da_bno = 0;
2114 next_da_bno != NULLFILEOFF && da_bno < mp->m_dir_geo->freeblk;
5e656dbb 2115 da_bno = (xfs_dablk_t)next_da_bno) {
ff105f75 2116 next_da_bno = da_bno + mp->m_dir_geo->fsbcount - 1;
5e656dbb 2117 if (bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK))
2bd0ea18 2118 break;
9b981421
DC
2119
2120 /*
2121 * we need to use the da3 node verifier here as it handles the
2122 * fact that reading the leaf hash tree blocks can return either
2123 * leaf or node blocks and calls the correct verifier. If we get
2124 * a node block, then we'll skip it below based on a magic
2125 * number check.
2126 */
db8e6401
DW
2127 error = dir_read_buf(ip, da_bno, &bp, &xfs_da3_node_buf_ops,
2128 &fixit);
8e7e14be 2129 if (error) {
33165ec3 2130 do_warn(
8e7e14be
DC
2131 _("can't read leaf block %u for directory inode %" PRIu64 ", error %d\n"),
2132 da_bno, ip->i_ino, error);
33165ec3 2133 return 1;
2bd0ea18 2134 }
a2ceac1f 2135 leaf = bp->b_addr;
9db68faf 2136 libxfs_dir2_leaf_hdr_from_disk(mp, &leafhdr, leaf);
a2279497 2137 ents = leafhdr.ents;
658ac3e3 2138 if (!(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC ||
0519f662
DW
2139 leafhdr.magic == XFS_DIR3_LEAFN_MAGIC ||
2140 leafhdr.magic == XFS_DA_NODE_MAGIC ||
2141 leafhdr.magic == XFS_DA3_NODE_MAGIC)) {
5d1b7f0f
CH
2142 do_warn(
2143 _("unknown magic number %#x for block %u in directory inode %" PRIu64 "\n"),
658ac3e3 2144 leafhdr.magic, da_bno, ip->i_ino);
e02ba985 2145 libxfs_buf_relse(bp);
2bd0ea18
NS
2146 return 1;
2147 }
8e7e14be 2148
0519f662
DW
2149 /* check v5 metadata */
2150 if (leafhdr.magic == XFS_DIR3_LEAFN_MAGIC ||
2151 leafhdr.magic == XFS_DA3_NODE_MAGIC) {
2152 error = check_da3_header(mp, bp, ip->i_ino);
2153 if (error) {
e02ba985 2154 libxfs_buf_relse(bp);
0519f662
DW
2155 return error;
2156 }
2157 }
2158
2159 /* ignore nodes */
2160 if (leafhdr.magic == XFS_DA_NODE_MAGIC ||
2161 leafhdr.magic == XFS_DA3_NODE_MAGIC) {
e02ba985 2162 libxfs_buf_relse(bp);
0519f662
DW
2163 continue;
2164 }
2165
8e7e14be
DC
2166 /*
2167 * If there's a validator error, we need to ensure that we got
2168 * the right ops on the buffer for when we write it back out.
2169 */
2170 bp->b_ops = &xfs_dir3_leafn_buf_ops;
d106a3e0 2171 if (leafhdr.count > mp->m_dir_geo->leaf_max_ents ||
658ac3e3 2172 leafhdr.count < leafhdr.stale) {
5d1b7f0f
CH
2173 do_warn(
2174 _("leaf block %u for directory inode %" PRIu64 " bad header\n"),
2bd0ea18 2175 da_bno, ip->i_ino);
e02ba985 2176 libxfs_buf_relse(bp);
2bd0ea18
NS
2177 return 1;
2178 }
65b80c98 2179 seeval = dir_hash_see_all(hashtab, ents,
658ac3e3 2180 leafhdr.count, leafhdr.stale);
e02ba985 2181 libxfs_buf_relse(bp);
0f012a4c 2182 if (seeval != DIR_HASH_CK_OK)
2bd0ea18
NS
2183 return 1;
2184 }
0f012a4c 2185 if (dir_hash_check(hashtab, ip, seeval))
2bd0ea18 2186 return 1;
0f012a4c 2187
ff105f75 2188 for (da_bno = mp->m_dir_geo->freeblk, next_da_bno = 0;
2bd0ea18
NS
2189 next_da_bno != NULLFILEOFF;
2190 da_bno = (xfs_dablk_t)next_da_bno) {
ff105f75 2191 next_da_bno = da_bno + mp->m_dir_geo->fsbcount - 1;
5e656dbb 2192 if (bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK))
2bd0ea18 2193 break;
8e7e14be 2194
db8e6401
DW
2195 error = dir_read_buf(ip, da_bno, &bp, &xfs_dir3_free_buf_ops,
2196 &fixit);
8e7e14be 2197 if (error) {
33165ec3 2198 do_warn(
8e7e14be
DC
2199 _("can't read freespace block %u for directory inode %" PRIu64 ", error %d\n"),
2200 da_bno, ip->i_ino, error);
33165ec3 2201 return 1;
2bd0ea18 2202 }
a2ceac1f 2203 free = bp->b_addr;
61e2142e 2204 libxfs_dir2_free_hdr_from_disk(mp, &freehdr, free);
cb5d1930 2205 bests = freehdr.bests;
ff105f75 2206 fdb = xfs_dir2_da_to_db(mp->m_dir_geo, da_bno);
658ac3e3
DC
2207 if (!(freehdr.magic == XFS_DIR2_FREE_MAGIC ||
2208 freehdr.magic == XFS_DIR3_FREE_MAGIC) ||
ff105f75
DC
2209 freehdr.firstdb !=
2210 (fdb - xfs_dir2_byte_to_db(mp->m_dir_geo, XFS_DIR2_FREE_OFFSET)) *
ae3cd5b1 2211 mp->m_dir_geo->free_max_bests ||
ff105f75 2212 freehdr.nvalid < freehdr.nused) {
5d1b7f0f
CH
2213 do_warn(
2214 _("free block %u for directory inode %" PRIu64 " bad header\n"),
2bd0ea18 2215 da_bno, ip->i_ino);
e02ba985 2216 libxfs_buf_relse(bp);
2bd0ea18
NS
2217 return 1;
2218 }
0519f662
DW
2219
2220 if (freehdr.magic == XFS_DIR3_FREE_MAGIC) {
2221 error = check_dir3_header(mp, bp, ip->i_ino);
2222 if (error) {
e02ba985 2223 libxfs_buf_relse(bp);
0519f662
DW
2224 return error;
2225 }
2226 }
658ac3e3
DC
2227 for (i = used = 0; i < freehdr.nvalid; i++) {
2228 if (i + freehdr.firstdb >= freetab->nents ||
2229 freetab->ents[i + freehdr.firstdb].v !=
2230 be16_to_cpu(bests[i])) {
507f4e33 2231 do_warn(
5d1b7f0f 2232 _("free block %u entry %i for directory ino %" PRIu64 " bad\n"),
2bd0ea18 2233 da_bno, i, ip->i_ino);
e02ba985 2234 libxfs_buf_relse(bp);
2bd0ea18
NS
2235 return 1;
2236 }
658ac3e3
DC
2237 used += be16_to_cpu(bests[i]) != NULLDATAOFF;
2238 freetab->ents[i + freehdr.firstdb].s = 1;
2bd0ea18 2239 }
658ac3e3 2240 if (used != freehdr.nused) {
5d1b7f0f
CH
2241 do_warn(
2242 _("free block %u for directory inode %" PRIu64 " bad nused\n"),
2bd0ea18 2243 da_bno, ip->i_ino);
e02ba985 2244 libxfs_buf_relse(bp);
2bd0ea18
NS
2245 return 1;
2246 }
e02ba985 2247 libxfs_buf_relse(bp);
2bd0ea18
NS
2248 }
2249 for (i = 0; i < freetab->nents; i++) {
4b6a2d8e
NS
2250 if ((freetab->ents[i].s == 0) &&
2251 (freetab->ents[i].v != NULLDATAOFF)) {
5d1b7f0f
CH
2252 do_warn(
2253 _("missing freetab entry %u for directory inode %" PRIu64 "\n"),
2bd0ea18
NS
2254 i, ip->i_ino);
2255 return 1;
2256 }
2257 }
8e7e14be 2258 return fixit;
2bd0ea18
NS
2259}
2260
2261/*
33165ec3
BN
2262 * If a directory is corrupt, we need to read in as many entries as possible,
2263 * destroy the entry and create a new one with recovered name/inode pairs.
2264 * (ie. get libxfs to do all the grunt work)
2bd0ea18 2265 */
2556c98b 2266static void
2bd0ea18
NS
2267longform_dir2_entry_check(xfs_mount_t *mp,
2268 xfs_ino_t ino,
2269 xfs_inode_t *ip,
2270 int *num_illegal,
2271 int *need_dot,
2bd0ea18 2272 ino_tree_node_t *irec,
64c54486 2273 int ino_offset,
33165ec3 2274 dir_hash_tab_t *hashtab)
2bd0ea18 2275{
a2ceac1f 2276 struct xfs_buf **bplist;
2bd0ea18
NS
2277 xfs_dablk_t da_bno;
2278 freetab_t *freetab;
95dff16b 2279 int num_bps;
2bd0ea18
NS
2280 int i;
2281 int isblock;
2282 int isleaf;
2283 xfs_fileoff_t next_da_bno;
2284 int seeval;
b5fa9e86 2285 int fixit = 0;
95dff16b 2286 xfs_dir2_db_t db;
ff105f75 2287 struct xfs_da_args args;
2bd0ea18
NS
2288
2289 *need_dot = 1;
ff105f75 2290 freetab = malloc(FREETAB_SIZE(ip->i_d.di_size / mp->m_dir_geo->blksize));
2bd0ea18 2291 if (!freetab) {
15e3986b
DC
2292 do_error(_("malloc failed in %s (%" PRId64 " bytes)\n"),
2293 __func__,
ff105f75 2294 FREETAB_SIZE(ip->i_d.di_size / mp->m_dir_geo->blksize));
2bd0ea18
NS
2295 exit(1);
2296 }
ff105f75 2297 freetab->naents = ip->i_d.di_size / mp->m_dir_geo->blksize;
2bd0ea18
NS
2298 freetab->nents = 0;
2299 for (i = 0; i < freetab->naents; i++) {
2300 freetab->ents[i].v = NULLDATAOFF;
2301 freetab->ents[i].s = 0;
2302 }
95dff16b 2303 num_bps = freetab->naents;
a2ceac1f 2304 bplist = calloc(num_bps, sizeof(struct xfs_buf*));
15e3986b
DC
2305 if (!bplist)
2306 do_error(_("calloc failed in %s (%zu bytes)\n"),
2307 __func__, num_bps * sizeof(struct xfs_buf*));
2308
9d7d6241 2309 /* is this a block, leaf, or node directory? */
ff105f75
DC
2310 args.dp = ip;
2311 args.geo = mp->m_dir_geo;
2312 libxfs_dir2_isblock(&args, &isblock);
2313 libxfs_dir2_isleaf(&args, &isleaf);
9d7d6241 2314
33165ec3 2315 /* check directory "data" blocks (ie. name/inode pairs) */
2bd0ea18 2316 for (da_bno = 0, next_da_bno = 0;
ff105f75 2317 next_da_bno != NULLFILEOFF && da_bno < mp->m_dir_geo->leafblk;
2bd0ea18 2318 da_bno = (xfs_dablk_t)next_da_bno) {
b5fa9e86 2319 const struct xfs_buf_ops *ops;
8e7e14be 2320 int error;
0519f662 2321 struct xfs_dir2_data_hdr *d;
b5fa9e86 2322
ff105f75 2323 next_da_bno = da_bno + mp->m_dir_geo->fsbcount - 1;
15e3986b
DC
2324 if (bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK)) {
2325 /*
2326 * if this is the first block, there isn't anything we
2327 * can recover so we just trash it.
2328 */
2329 if (da_bno == 0) {
2330 fixit++;
2331 goto out_fix;
2332 }
2bd0ea18 2333 break;
15e3986b
DC
2334 }
2335
ff105f75 2336 db = xfs_dir2_da_to_db(mp->m_dir_geo, da_bno);
95dff16b 2337 if (db >= num_bps) {
1624c340
ES
2338 int last_size = num_bps;
2339
95dff16b
BN
2340 /* more data blocks than expected */
2341 num_bps = db + 1;
a2ceac1f 2342 bplist = realloc(bplist, num_bps * sizeof(struct xfs_buf*));
0f012a4c 2343 if (!bplist)
15e3986b
DC
2344 do_error(_("realloc failed in %s (%zu bytes)\n"),
2345 __func__,
a2ceac1f 2346 num_bps * sizeof(struct xfs_buf*));
1624c340
ES
2347 /* Initialize the new elements */
2348 for (i = last_size; i < num_bps; i++)
2349 bplist[i] = NULL;
95dff16b 2350 }
b5fa9e86
DC
2351
2352 if (isblock)
2353 ops = &xfs_dir3_block_buf_ops;
2354 else
2355 ops = &xfs_dir3_data_buf_ops;
8e7e14be 2356
db8e6401 2357 error = dir_read_buf(ip, da_bno, &bplist[db], ops, &fixit);
8e7e14be 2358 if (error) {
5d1b7f0f 2359 do_warn(
8e7e14be
DC
2360 _("can't read data block %u for directory inode %" PRIu64 " error %d\n"),
2361 da_bno, ino, error);
95dff16b 2362 *num_illegal += 1;
b5fa9e86
DC
2363
2364 /*
2365 * we try to read all "data" blocks, but if we are in
2366 * block form and we fail, there isn't anything else to
2367 * read, and nothing we can do but trash it.
2368 */
2369 if (isblock) {
2370 fixit++;
2371 goto out_fix;
2372 }
2373 continue;
2bd0ea18 2374 }
0519f662
DW
2375
2376 /* check v5 metadata */
2377 d = bplist[db]->b_addr;
2378 if (be32_to_cpu(d->magic) == XFS_DIR3_BLOCK_MAGIC ||
2379 be32_to_cpu(d->magic) == XFS_DIR3_DATA_MAGIC) {
2380 struct xfs_buf *bp = bplist[db];
2381
2382 error = check_dir3_header(mp, bp, ino);
2383 if (error) {
2384 fixit++;
2385 continue;
2386 }
2387 }
2388
2bd0ea18 2389 longform_dir2_entry_check_data(mp, ip, num_illegal, need_dot,
2556c98b 2390 irec, ino_offset, &bplist[db], hashtab,
33165ec3 2391 &freetab, da_bno, isblock);
2bd0ea18 2392 }
8e7e14be 2393 fixit |= (*num_illegal != 0) || dir2_is_badino(ino) || *need_dot;
9d7d6241 2394
575ca697
BN
2395 if (!dotdot_update) {
2396 /* check btree and freespace */
2397 if (isblock) {
a354abc8 2398 struct xfs_dir2_data_hdr *block;
575ca697
BN
2399 xfs_dir2_block_tail_t *btp;
2400 xfs_dir2_leaf_entry_t *blp;
2401
a2ceac1f 2402 block = bplist[0]->b_addr;
ff105f75 2403 btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block);
5e656dbb 2404 blp = xfs_dir2_block_leaf_p(btp);
575ca697
BN
2405 seeval = dir_hash_see_all(hashtab, blp,
2406 be32_to_cpu(btp->count),
2407 be32_to_cpu(btp->stale));
2408 if (dir_hash_check(hashtab, ip, seeval))
2409 fixit |= 1;
2410 } else if (isleaf) {
2411 fixit |= longform_dir2_check_leaf(mp, ip, hashtab,
2412 freetab);
2413 } else {
2414 fixit |= longform_dir2_check_node(mp, ip, hashtab,
2415 freetab);
2416 }
2bd0ea18 2417 }
b5fa9e86 2418out_fix:
575ca697 2419 if (!no_modify && (fixit || dotdot_update)) {
33165ec3 2420 dir_hash_dup_names(hashtab);
90dd8310 2421 for (i = 0; i < num_bps; i++)
33165ec3 2422 if (bplist[i])
e02ba985 2423 libxfs_buf_relse(bplist[i]);
6fa00c33 2424 longform_dir2_rebuild(mp, ino, ip, irec, ino_offset, hashtab);
33165ec3 2425 *num_illegal = 0;
6fa00c33 2426 *need_dot = 0;
33165ec3 2427 } else {
90dd8310 2428 for (i = 0; i < num_bps; i++)
33165ec3 2429 if (bplist[i])
e02ba985 2430 libxfs_buf_relse(bplist[i]);
33165ec3 2431 }
0f012a4c 2432
95dff16b 2433 free(bplist);
2bd0ea18
NS
2434 free(freetab);
2435}
2436
2bd0ea18
NS
2437/*
2438 * shortform directory v2 processing routines -- entry verification and
2439 * bad entry deletion (pruning).
2440 */
aaca101b
DC
2441static struct xfs_dir2_sf_entry *
2442shortform_dir2_junk(
2443 struct xfs_mount *mp,
2444 struct xfs_dir2_sf_hdr *sfp,
2445 struct xfs_dir2_sf_entry *sfep,
2446 xfs_ino_t lino,
2447 int *max_size,
2448 int *index,
2449 int *bytes_deleted,
2450 int *ino_dirty)
2451{
2452 struct xfs_dir2_sf_entry *next_sfep;
2453 int next_len;
2454 int next_elen;
2455
2456 if (lino == orphanage_ino)
2457 orphanage_ino = 0;
2458
660836c9
CH
2459 next_elen = libxfs_dir2_sf_entsize(mp, sfp, sfep->namelen);
2460 next_sfep = libxfs_dir2_sf_nextentry(mp, sfp, sfep);
aaca101b
DC
2461
2462 /*
2463 * if we are just checking, simply return the pointer to the next entry
2464 * here so that the checking loop can continue.
2465 */
2466 if (no_modify) {
2467 do_warn(_("would junk entry\n"));
2468 return next_sfep;
2469 }
2470
2471 /*
2472 * now move all the remaining entries down over the junked entry and
2473 * clear the newly unused bytes at the tail of the directory region.
2474 */
ee6cd73e 2475 next_len = *max_size - ((intptr_t)next_sfep - (intptr_t)sfp);
aaca101b
DC
2476 *max_size -= next_elen;
2477 *bytes_deleted += next_elen;
2478
2479 memmove(sfep, next_sfep, next_len);
ee6cd73e 2480 memset((void *)((intptr_t)sfep + next_len), 0, next_elen);
aaca101b
DC
2481 sfp->count -= 1;
2482 *ino_dirty = 1;
2483
2484 /*
2485 * WARNING: drop the index i by one so it matches the decremented count
2486 * for accurate comparisons in the loop test
2487 */
2488 (*index)--;
2489
2490 if (verbose)
2491 do_warn(_("junking entry\n"));
2492 else
2493 do_warn("\n");
2494 return sfep;
2495}
2496
2556c98b 2497static void
2bd0ea18
NS
2498shortform_dir2_entry_check(xfs_mount_t *mp,
2499 xfs_ino_t ino,
2500 xfs_inode_t *ip,
2501 int *ino_dirty,
2bd0ea18 2502 ino_tree_node_t *current_irec,
64c54486 2503 int current_ino_offset,
33165ec3 2504 dir_hash_tab_t *hashtab)
2bd0ea18
NS
2505{
2506 xfs_ino_t lino;
2507 xfs_ino_t parent;
a354abc8 2508 struct xfs_dir2_sf_hdr *sfp;
aaca101b
DC
2509 struct xfs_dir2_sf_entry *sfep;
2510 struct xfs_dir2_sf_entry *next_sfep;
2511 struct xfs_ifork *ifp;
2512 struct ino_tree_node *irec;
2bd0ea18
NS
2513 int max_size;
2514 int ino_offset;
2515 int i;
2bd0ea18
NS
2516 int bad_sfnamelen;
2517 int namelen;
2518 int bytes_deleted;
2519 char fname[MAXNAMELEN + 1];
2520 int i8;
2521
2522 ifp = &ip->i_df;
a354abc8 2523 sfp = (struct xfs_dir2_sf_hdr *) ifp->if_u1.if_data;
2bd0ea18 2524 *ino_dirty = 0;
e55d768a 2525 bytes_deleted = 0;
2bd0ea18
NS
2526
2527 max_size = ifp->if_bytes;
2528 ASSERT(ip->i_d.di_size <= ifp->if_bytes);
2529
575ca697
BN
2530 /*
2531 * if just rebuild a directory due to a "..", update and return
2532 */
2533 if (dotdot_update) {
2534 parent = get_inode_parent(current_irec, current_ino_offset);
2535 if (no_modify) {
5d1b7f0f
CH
2536 do_warn(
2537 _("would set .. in sf dir inode %" PRIu64 " to %" PRIu64 "\n"),
575ca697
BN
2538 ino, parent);
2539 } else {
5d1b7f0f
CH
2540 do_warn(
2541 _("setting .. in sf dir inode %" PRIu64 " to %" PRIu64 "\n"),
575ca697 2542 ino, parent);
8a7190bd 2543 libxfs_dir2_sf_put_parent_ino(sfp, parent);
575ca697
BN
2544 *ino_dirty = 1;
2545 }
2546 return;
2547 }
2548
2bd0ea18
NS
2549 /*
2550 * no '.' entry in shortform dirs, just bump up ref count by 1
2551 * '..' was already (or will be) accounted for and checked when
2552 * the directory is reached or will be taken care of when the
2553 * directory is moved to orphanage.
2554 */
2555 add_inode_ref(current_irec, current_ino_offset);
2556
e55d768a
NS
2557 /*
2558 * Initialise i8 counter -- the parent inode number counts as well.
2559 */
8a7190bd 2560 i8 = libxfs_dir2_sf_get_parent_ino(sfp) > XFS_DIR2_MAX_SHORT_INUM;
e55d768a 2561
2bd0ea18
NS
2562 /*
2563 * now run through entries, stop at first bad entry, don't need
2564 * to skip over '..' since that's encoded in its own field and
2565 * no need to worry about '.' since it doesn't exist.
2566 */
a354abc8 2567 sfep = next_sfep = xfs_dir2_sf_firstentry(sfp);
2bd0ea18 2568
a354abc8 2569 for (i = 0; i < sfp->count && max_size >
ee6cd73e 2570 (intptr_t)next_sfep - (intptr_t)sfp;
2bd0ea18 2571 sfep = next_sfep, i++) {
2bd0ea18 2572 bad_sfnamelen = 0;
2bd0ea18 2573
e96bd2d3 2574 lino = libxfs_dir2_sf_get_ino(mp, sfp, sfep);
2bd0ea18
NS
2575
2576 namelen = sfep->namelen;
2577
2578 ASSERT(no_modify || namelen > 0);
2579
2580 if (no_modify && namelen == 0) {
2581 /*
2582 * if we're really lucky, this is
2583 * the last entry in which case we
2584 * can use the dir size to set the
2585 * namelen value. otherwise, forget
2586 * it because we're not going to be
2587 * able to find the next entry.
2588 */
2589 bad_sfnamelen = 1;
2590
a354abc8 2591 if (i == sfp->count - 1) {
2bd0ea18 2592 namelen = ip->i_d.di_size -
ee6cd73e
CH
2593 ((intptr_t) &sfep->name[0] -
2594 (intptr_t) sfp);
2bd0ea18
NS
2595 } else {
2596 /*
2597 * don't process the rest of the directory,
2598 * break out of processing loop
2599 */
2600 break;
2601 }
ee6cd73e 2602 } else if (no_modify && (intptr_t) sfep - (intptr_t) sfp +
660836c9 2603 + libxfs_dir2_sf_entsize(mp, sfp, sfep->namelen)
2bd0ea18
NS
2604 > ip->i_d.di_size) {
2605 bad_sfnamelen = 1;
2606
a354abc8 2607 if (i == sfp->count - 1) {
2bd0ea18 2608 namelen = ip->i_d.di_size -
ee6cd73e
CH
2609 ((intptr_t) &sfep->name[0] -
2610 (intptr_t) sfp);
2bd0ea18
NS
2611 } else {
2612 /*
2613 * don't process the rest of the directory,
2614 * break out of processing loop
2615 */
2616 break;
2617 }
2618 }
2619
dab9b8d6 2620 memmove(fname, sfep->name, sfep->namelen);
2bd0ea18
NS
2621 fname[sfep->namelen] = '\0';
2622
2623 ASSERT(no_modify || (lino != NULLFSINO && lino != 0));
017e979e 2624 ASSERT(no_modify || libxfs_verify_dir_ino(mp, lino));
2bd0ea18 2625
e55d768a
NS
2626 /*
2627 * Also skip entries with bogus inode numbers if we're
2628 * in no modify mode.
2629 */
2630
017e979e 2631 if (no_modify && !libxfs_verify_dir_ino(mp, lino)) {
660836c9 2632 next_sfep = libxfs_dir2_sf_nextentry(mp, sfp, sfep);
2bd0ea18
NS
2633 continue;
2634 }
2635
1ae311d5 2636 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, lino),
2bd0ea18
NS
2637 XFS_INO_TO_AGINO(mp, lino));
2638
6c39a3cb 2639 if (irec == NULL) {
5d1b7f0f
CH
2640 do_warn(
2641 _("entry \"%s\" in shortform directory %" PRIu64 " references non-existent inode %" PRIu64 "\n"),
2bd0ea18 2642 fname, ino, lino);
aaca101b
DC
2643 next_sfep = shortform_dir2_junk(mp, sfp, sfep, lino,
2644 &max_size, &i, &bytes_deleted,
2645 ino_dirty);
2646 continue;
2bd0ea18
NS
2647 }
2648
2bd0ea18
NS
2649 ino_offset = XFS_INO_TO_AGINO(mp, lino) - irec->ino_startnum;
2650
2651 /*
2652 * if it's a free inode, blow out the entry.
2653 * by now, any inode that we think is free
2654 * really is free.
2655 */
2656 if (is_inode_free(irec, ino_offset)) {
5d1b7f0f
CH
2657 do_warn(
2658 _("entry \"%s\" in shortform directory inode %" PRIu64 " points to free inode %" PRIu64 "\n"),
6c39a3cb 2659 fname, ino, lino);
aaca101b
DC
2660 next_sfep = shortform_dir2_junk(mp, sfp, sfep, lino,
2661 &max_size, &i, &bytes_deleted,
2662 ino_dirty);
2663 continue;
6c39a3cb
BN
2664 }
2665 /*
2666 * check if this inode is lost+found dir in the root
2667 */
2668 if (ino == mp->m_sb.sb_rootino && strcmp(fname, ORPHANAGE) == 0) {
2bd0ea18 2669 /*
6c39a3cb 2670 * if it's not a directory, trash it
2bd0ea18 2671 */
6c39a3cb 2672 if (!inode_isadir(irec, ino_offset)) {
5d1b7f0f
CH
2673 do_warn(
2674 _("%s (ino %" PRIu64 ") in root (%" PRIu64 ") is not a directory"),
2675 ORPHANAGE, lino, ino);
aaca101b
DC
2676 next_sfep = shortform_dir2_junk(mp, sfp, sfep,
2677 lino, &max_size, &i,
2678 &bytes_deleted, ino_dirty);
2679 continue;
2bd0ea18 2680 }
64c54486 2681 /*
6c39a3cb
BN
2682 * if this is a dup, it will be picked up below,
2683 * otherwise, mark it as the orphanage for later.
0f012a4c 2684 */
6c39a3cb
BN
2685 if (!orphanage_ino)
2686 orphanage_ino = lino;
2687 }
2688 /*
2689 * check for duplicate names in directory.
2690 */
51ca7008 2691 if (!dir_hash_add(mp, hashtab, (xfs_dir2_dataptr_t)
a354abc8 2692 (sfep - xfs_dir2_sf_firstentry(sfp)),
aaca101b 2693 lino, sfep->namelen, sfep->name,
d49d4ff5 2694 libxfs_dir2_sf_get_ftype(mp, sfep))) {
5d1b7f0f
CH
2695 do_warn(
2696_("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"),
2697 fname, lino, ino);
aaca101b
DC
2698 next_sfep = shortform_dir2_junk(mp, sfp, sfep, lino,
2699 &max_size, &i, &bytes_deleted,
2700 ino_dirty);
2701 continue;
6c39a3cb 2702 }
575ca697 2703
6c39a3cb 2704 if (!inode_isadir(irec, ino_offset)) {
2bd0ea18
NS
2705 /*
2706 * check easy case first, regular inode, just bump
e55d768a 2707 * the link count
2bd0ea18
NS
2708 */
2709 add_inode_reached(irec, ino_offset);
2bd0ea18
NS
2710 } else {
2711 parent = get_inode_parent(irec, ino_offset);
2712
2713 /*
2714 * bump up the link counts in parent and child.
2715 * directory but if the link doesn't agree with
2716 * the .. in the child, blow out the entry
2717 */
2718 if (is_inode_reached(irec, ino_offset)) {
5d1b7f0f
CH
2719 do_warn(
2720 _("entry \"%s\" in directory inode %" PRIu64
2721 " references already connected inode %" PRIu64 ".\n"),
2bd0ea18 2722 fname, ino, lino);
aaca101b
DC
2723 next_sfep = shortform_dir2_junk(mp, sfp, sfep,
2724 lino, &max_size, &i,
2725 &bytes_deleted, ino_dirty);
2726 continue;
2bd0ea18
NS
2727 } else if (parent == ino) {
2728 add_inode_reached(irec, ino_offset);
2729 add_inode_ref(current_irec, current_ino_offset);
6fa00c33
BN
2730 } else if (parent == NULLFSINO) {
2731 /* ".." was missing, but this entry refers to it,
2732 so, set it as the parent and mark for rebuild */
5d1b7f0f
CH
2733 do_warn(
2734 _("entry \"%s\" in dir ino %" PRIu64 " doesn't have a .. entry, will set it in ino %" PRIu64 ".\n"),
6fa00c33
BN
2735 fname, ino, lino);
2736 set_inode_parent(irec, ino_offset, ino);
2737 add_inode_reached(irec, ino_offset);
2738 add_inode_ref(current_irec, current_ino_offset);
575ca697
BN
2739 add_dotdot_update(XFS_INO_TO_AGNO(mp, lino),
2740 irec, ino_offset);
2bd0ea18 2741 } else {
5d1b7f0f
CH
2742 do_warn(
2743 _("entry \"%s\" in directory inode %" PRIu64
2744 " not consistent with .. value (%" PRIu64
2745 ") in inode %" PRIu64 ",\n"),
2bd0ea18 2746 fname, ino, parent, lino);
aaca101b
DC
2747 next_sfep = shortform_dir2_junk(mp, sfp, sfep,
2748 lino, &max_size, &i,
2749 &bytes_deleted, ino_dirty);
2750 continue;
2bd0ea18
NS
2751 }
2752 }
2753
aaca101b
DC
2754 /* validate ftype field if supported */
2755 if (xfs_sb_version_hasftype(&mp->m_sb)) {
14f8b681
DW
2756 uint8_t dir_ftype;
2757 uint8_t ino_ftype;
2bd0ea18 2758
d49d4ff5 2759 dir_ftype = libxfs_dir2_sf_get_ftype(mp, sfep);
aaca101b 2760 ino_ftype = get_inode_ftype(irec, ino_offset);
2bd0ea18 2761
aaca101b
DC
2762 if (dir_ftype != ino_ftype) {
2763 if (no_modify) {
2764 do_warn(
2765 _("would fix ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"),
2766 dir_ftype, ino_ftype,
2767 ino, lino);
2768 } else {
2769 do_warn(
2770 _("fixing ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"),
2771 dir_ftype, ino_ftype,
2772 ino, lino);
d49d4ff5 2773 libxfs_dir2_sf_put_ftype(mp, sfep,
aaca101b
DC
2774 ino_ftype);
2775 dir_hash_update_ftype(hashtab,
2776 (xfs_dir2_dataptr_t)(sfep - xfs_dir2_sf_firstentry(sfp)),
2777 ino_ftype);
2778 *ino_dirty = 1;
2779 }
2bd0ea18 2780 }
aaca101b
DC
2781 }
2782
2783 if (lino > XFS_DIR2_MAX_SHORT_INUM)
2bd0ea18
NS
2784 i8++;
2785
2786 /*
aaca101b
DC
2787 * go onto next entry - we have to take entries with bad namelen
2788 * into account in no modify mode since we calculate size based
2789 * on next_sfep.
2bd0ea18
NS
2790 */
2791 ASSERT(no_modify || bad_sfnamelen == 0);
ee6cd73e 2792 next_sfep = (struct xfs_dir2_sf_entry *)((intptr_t)sfep +
aaca101b 2793 (bad_sfnamelen
660836c9
CH
2794 ? libxfs_dir2_sf_entsize(mp, sfp, namelen)
2795 : libxfs_dir2_sf_entsize(mp, sfp, sfep->namelen)));
2bd0ea18
NS
2796 }
2797
a354abc8 2798 if (sfp->i8count != i8) {
2bd0ea18 2799 if (no_modify) {
5d1b7f0f
CH
2800 do_warn(_("would fix i8count in inode %" PRIu64 "\n"),
2801 ino);
2bd0ea18
NS
2802 } else {
2803 if (i8 == 0) {
aaca101b
DC
2804 struct xfs_dir2_sf_entry *tmp_sfep;
2805
2bd0ea18 2806 tmp_sfep = next_sfep;
494434d7 2807 process_sf_dir2_fixi8(mp, sfp, &tmp_sfep);
2bd0ea18 2808 bytes_deleted +=
ee6cd73e
CH
2809 (intptr_t)next_sfep -
2810 (intptr_t)tmp_sfep;
2bd0ea18
NS
2811 next_sfep = tmp_sfep;
2812 } else
a354abc8 2813 sfp->i8count = i8;
2bd0ea18 2814 *ino_dirty = 1;
5d1b7f0f
CH
2815 do_warn(_("fixing i8count in inode %" PRIu64 "\n"),
2816 ino);
2bd0ea18
NS
2817 }
2818 }
2819
2820 /*
2821 * sync up sizes if required
2822 */
aaca101b 2823 if (*ino_dirty && bytes_deleted > 0) {
2bd0ea18
NS
2824 ASSERT(!no_modify);
2825 libxfs_idata_realloc(ip, -bytes_deleted, XFS_DATA_FORK);
2826 ip->i_d.di_size -= bytes_deleted;
2827 }
2828
2829 if (ip->i_d.di_size != ip->i_df.if_bytes) {
2830 ASSERT(ip->i_df.if_bytes == (xfs_fsize_t)
ee6cd73e 2831 ((intptr_t) next_sfep - (intptr_t) sfp));
2bd0ea18 2832 ip->i_d.di_size = (xfs_fsize_t)
ee6cd73e 2833 ((intptr_t) next_sfep - (intptr_t) sfp);
5d1b7f0f
CH
2834 do_warn(
2835 _("setting size to %" PRId64 " bytes to reflect junked entries\n"),
2bd0ea18
NS
2836 ip->i_d.di_size);
2837 *ino_dirty = 1;
2838 }
2839}
2840
2841/*
2556c98b 2842 * processes all reachable inodes in directories
2bd0ea18 2843 */
2556c98b
BN
2844static void
2845process_dir_inode(
2846 xfs_mount_t *mp,
575ca697 2847 xfs_agnumber_t agno,
2556c98b
BN
2848 ino_tree_node_t *irec,
2849 int ino_offset)
2bd0ea18 2850{
575ca697 2851 xfs_ino_t ino;
2bd0ea18
NS
2852 xfs_inode_t *ip;
2853 xfs_trans_t *tp;
33165ec3 2854 dir_hash_tab_t *hashtab;
0b66d459 2855 int need_dot;
2bd0ea18
NS
2856 int dirty, num_illegal, error, nres;
2857
575ca697
BN
2858 ino = XFS_AGINO_TO_INO(mp, agno, irec->ino_startnum + ino_offset);
2859
2bd0ea18 2860 /*
2bd0ea18
NS
2861 * open up directory inode, check all entries,
2862 * then call prune_dir_entries to remove all
2863 * remaining illegal directory entries.
2864 */
2865
f4ef1178 2866 ASSERT(!is_inode_refchecked(irec, ino_offset) || dotdot_update);
2bd0ea18 2867
3452f451 2868 error = -libxfs_iget(mp, NULL, ino, 0, &ip, &phase6_ifork_ops);
2556c98b
BN
2869 if (error) {
2870 if (!no_modify)
5d1b7f0f
CH
2871 do_error(
2872 _("couldn't map inode %" PRIu64 ", err = %d\n"),
2556c98b
BN
2873 ino, error);
2874 else {
5d1b7f0f
CH
2875 do_warn(
2876 _("couldn't map inode %" PRIu64 ", err = %d\n"),
2556c98b 2877 ino, error);
2bd0ea18 2878 /*
2556c98b
BN
2879 * see below for what we're doing if this
2880 * is root. Why do we need to do this here?
2881 * to ensure that the root doesn't show up
2882 * as being disconnected in the no_modify case.
2bd0ea18 2883 */
2556c98b
BN
2884 if (mp->m_sb.sb_rootino == ino) {
2885 add_inode_reached(irec, 0);
2886 add_inode_ref(irec, 0);
2887 }
2bd0ea18
NS
2888 }
2889
f4ef1178 2890 add_inode_refchecked(irec, 0);
2556c98b
BN
2891 return;
2892 }
2bd0ea18 2893
2556c98b 2894 need_dot = dirty = num_illegal = 0;
64c54486 2895
2556c98b 2896 if (mp->m_sb.sb_rootino == ino) {
2bd0ea18 2897 /*
2556c98b
BN
2898 * mark root inode reached and bump up
2899 * link count for root inode to account
2900 * for '..' entry since the root inode is
2901 * never reached by a parent. we know
2902 * that root's '..' is always good --
2903 * guaranteed by phase 3 and/or below.
2bd0ea18 2904 */
2556c98b
BN
2905 add_inode_reached(irec, ino_offset);
2906 }
2907
f4ef1178 2908 add_inode_refchecked(irec, ino_offset);
2556c98b
BN
2909
2910 hashtab = dir_hash_init(ip->i_d.di_size);
2911
2912 /*
2913 * look for bogus entries
2914 */
2915 switch (ip->i_d.di_format) {
2bd0ea18
NS
2916 case XFS_DINODE_FMT_EXTENTS:
2917 case XFS_DINODE_FMT_BTREE:
2918 /*
2919 * also check for missing '.' in longform dirs.
2920 * missing .. entries are added if required when
2921 * the directory is connected to lost+found. but
2922 * we need to create '.' entries here.
2923 */
9a048535
DC
2924 longform_dir2_entry_check(mp, ino, ip,
2925 &num_illegal, &need_dot,
2926 irec, ino_offset,
2927 hashtab);
2bd0ea18 2928 break;
2556c98b 2929
2bd0ea18 2930 case XFS_DINODE_FMT_LOCAL:
2bd0ea18
NS
2931 /*
2932 * using the remove reservation is overkill
2933 * since at most we'll only need to log the
2934 * inode but it's easier than wedging a
2935 * new define in ourselves.
2936 */
2937 nres = no_modify ? 0 : XFS_REMOVE_SPACE_RES(mp);
9074815c
CH
2938 error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove,
2939 nres, 0, 0, &tp);
2bd0ea18
NS
2940 if (error)
2941 res_failed(error);
2942
2943 libxfs_trans_ijoin(tp, ip, 0);
2bd0ea18 2944
9a048535
DC
2945 shortform_dir2_entry_check(mp, ino, ip, &dirty,
2946 irec, ino_offset,
2947 hashtab);
2bd0ea18 2948
27527004 2949 ASSERT(dirty == 0 || (dirty && !no_modify));
2bd0ea18
NS
2950 if (dirty) {
2951 libxfs_trans_log_inode(tp, ip,
2952 XFS_ILOG_CORE | XFS_ILOG_DDATA);
f2279d8d
DW
2953 error = -libxfs_trans_commit(tp);
2954 if (error)
af06261f
DW
2955 do_error(
2956_("error %d fixing shortform directory %llu\n"),
2957 error,
2958 (unsigned long long)ip->i_ino);
2bd0ea18 2959 } else {
3d7434fe 2960 libxfs_trans_cancel(tp);
2bd0ea18
NS
2961 }
2962 break;
2556c98b 2963
2bd0ea18
NS
2964 default:
2965 break;
2556c98b
BN
2966 }
2967 dir_hash_done(hashtab);
2bd0ea18 2968
2556c98b
BN
2969 /*
2970 * if we have to create a .. for /, do it now *before*
2971 * we delete the bogus entries, otherwise the directory
2972 * could transform into a shortform dir which would
2973 * probably cause the simulation to choke. Even
2974 * if the illegal entries get shifted around, it's ok
2975 * because the entries are structurally intact and in
2976 * in hash-value order so the simulation won't get confused
2977 * if it has to move them around.
2978 */
2979 if (!no_modify && need_root_dotdot && ino == mp->m_sb.sb_rootino) {
2980 ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_LOCAL);
2bd0ea18 2981
2556c98b 2982 do_warn(_("recreating root directory .. entry\n"));
2bd0ea18 2983
2556c98b 2984 nres = XFS_MKDIR_SPACE_RES(mp, 2);
9074815c
CH
2985 error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_mkdir,
2986 nres, 0, 0, &tp);
2556c98b
BN
2987 if (error)
2988 res_failed(error);
2bd0ea18 2989
2556c98b 2990 libxfs_trans_ijoin(tp, ip, 0);
2bd0ea18 2991
12b53197 2992 error = -libxfs_dir_createname(tp, ip, &xfs_name_dotdot,
015bc82e 2993 ip->i_ino, nres);
2556c98b 2994 if (error)
5d1b7f0f
CH
2995 do_error(
2996 _("can't make \"..\" entry in root inode %" PRIu64 ", createname error %d\n"), ino, error);
2bd0ea18 2997
2556c98b 2998 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
f2279d8d
DW
2999 error = -libxfs_trans_commit(tp);
3000 if (error)
3001 do_error(
3002 _("root inode \"..\" entry recreation failed (%d)\n"), error);
2bd0ea18 3003
2556c98b
BN
3004 need_root_dotdot = 0;
3005 } else if (need_root_dotdot && ino == mp->m_sb.sb_rootino) {
3006 do_warn(_("would recreate root directory .. entry\n"));
3007 }
2bd0ea18 3008
2556c98b
BN
3009 /*
3010 * if we need to create the '.' entry, do so only if
ff1f79a7 3011 * the directory is a longform dir. if it's been
2556c98b
BN
3012 * turned into a shortform dir, then the inode is ok
3013 * since shortform dirs have no '.' entry and the inode
3014 * has already been committed by prune_lf_dir_entry().
3015 */
3016 if (need_dot) {
2bd0ea18 3017 /*
2556c98b
BN
3018 * bump up our link count but don't
3019 * bump up the inode link count. chances
3020 * are good that even though we lost '.'
3021 * the inode link counts reflect '.' so
3022 * leave the inode link count alone and if
3023 * it turns out to be wrong, we'll catch
3024 * that in phase 7.
2bd0ea18 3025 */
2556c98b
BN
3026 add_inode_ref(irec, ino_offset);
3027
3028 if (no_modify) {
5d1b7f0f
CH
3029 do_warn(
3030 _("would create missing \".\" entry in dir ino %" PRIu64 "\n"),
2556c98b
BN
3031 ino);
3032 } else if (ip->i_d.di_format != XFS_DINODE_FMT_LOCAL) {
2bd0ea18 3033 /*
2556c98b 3034 * need to create . entry in longform dir.
2bd0ea18 3035 */
5d1b7f0f
CH
3036 do_warn(
3037 _("creating missing \".\" entry in dir ino %" PRIu64 "\n"), ino);
2bd0ea18 3038
2556c98b 3039 nres = XFS_MKDIR_SPACE_RES(mp, 1);
9074815c
CH
3040 error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_mkdir,
3041 nres, 0, 0, &tp);
2556c98b
BN
3042 if (error)
3043 res_failed(error);
2bd0ea18 3044
2556c98b 3045 libxfs_trans_ijoin(tp, ip, 0);
2bd0ea18 3046
12b53197 3047 error = -libxfs_dir_createname(tp, ip, &xfs_name_dot,
015bc82e 3048 ip->i_ino, nres);
5e656dbb 3049 if (error)
5d1b7f0f
CH
3050 do_error(
3051 _("can't make \".\" entry in dir ino %" PRIu64 ", createname error %d\n"),
2556c98b 3052 ino, error);
2bd0ea18 3053
2556c98b 3054 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
f2279d8d
DW
3055 error = -libxfs_trans_commit(tp);
3056 if (error)
3057 do_error(
3058 _("root inode \".\" entry recreation failed (%d)\n"), error);
2bd0ea18 3059 }
2bd0ea18 3060 }
31845e4c 3061 libxfs_irele(ip);
2bd0ea18
NS
3062}
3063
3064/*
3065 * mark realtime bitmap and summary inodes as reached.
3066 * quota inode will be marked here as well
3067 */
8b8a6b02 3068static void
2bd0ea18
NS
3069mark_standalone_inodes(xfs_mount_t *mp)
3070{
3071 ino_tree_node_t *irec;
3072 int offset;
3073
1ae311d5 3074 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rbmino),
2bd0ea18
NS
3075 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rbmino));
3076
2bd0ea18
NS
3077 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rbmino) -
3078 irec->ino_startnum;
3079
3080 add_inode_reached(irec, offset);
3081
1ae311d5 3082 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rsumino),
2bd0ea18
NS
3083 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rsumino));
3084
dfc130f3 3085 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rsumino) -
2bd0ea18
NS
3086 irec->ino_startnum;
3087
2bd0ea18
NS
3088 add_inode_reached(irec, offset);
3089
3090 if (fs_quotas) {
3091 if (mp->m_sb.sb_uquotino
3092 && mp->m_sb.sb_uquotino != NULLFSINO) {
1ae311d5 3093 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp,
2bd0ea18
NS
3094 mp->m_sb.sb_uquotino),
3095 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_uquotino));
3096 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_uquotino)
3097 - irec->ino_startnum;
3098 add_inode_reached(irec, offset);
3099 }
b36eef04
NS
3100 if (mp->m_sb.sb_gquotino
3101 && mp->m_sb.sb_gquotino != NULLFSINO) {
1ae311d5 3102 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp,
b36eef04
NS
3103 mp->m_sb.sb_gquotino),
3104 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_gquotino));
3105 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_gquotino)
2bd0ea18
NS
3106 - irec->ino_startnum;
3107 add_inode_reached(irec, offset);
3108 }
0340d706
CS
3109 if (mp->m_sb.sb_pquotino
3110 && mp->m_sb.sb_pquotino != NULLFSINO) {
3111 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp,
3112 mp->m_sb.sb_pquotino),
3113 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_pquotino));
3114 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_pquotino)
3115 - irec->ino_startnum;
3116 add_inode_reached(irec, offset);
3117 }
2bd0ea18
NS
3118 }
3119}
3120
6c39a3cb
BN
3121static void
3122check_for_orphaned_inodes(
3123 xfs_mount_t *mp,
2556c98b 3124 xfs_agnumber_t agno,
6c39a3cb
BN
3125 ino_tree_node_t *irec)
3126{
3127 int i;
6c39a3cb
BN
3128 xfs_ino_t ino;
3129
3130 for (i = 0; i < XFS_INODES_PER_CHUNK; i++) {
3131 ASSERT(is_inode_confirmed(irec, i));
3132 if (is_inode_free(irec, i))
3133 continue;
3134
2556c98b
BN
3135 if (is_inode_reached(irec, i))
3136 continue;
3137
3138 ASSERT(inode_isadir(irec, i) ||
3139 num_inode_references(irec, i) == 0);
3140
3141 ino = XFS_AGINO_TO_INO(mp, agno, i + irec->ino_startnum);
3142 if (inode_isadir(irec, i))
5d1b7f0f 3143 do_warn(_("disconnected dir inode %" PRIu64 ", "), ino);
2556c98b 3144 else
5d1b7f0f 3145 do_warn(_("disconnected inode %" PRIu64 ", "), ino);
9a048535
DC
3146 if (!no_modify) {
3147 if (!orphanage_ino)
2556c98b
BN
3148 orphanage_ino = mk_orphanage(mp);
3149 do_warn(_("moving to %s\n"), ORPHANAGE);
3150 mv_orphanage(mp, ino, inode_isadir(irec, i));
3151 } else {
3152 do_warn(_("would move to %s\n"), ORPHANAGE);
6c39a3cb 3153 }
2556c98b
BN
3154 /*
3155 * for read-only case, even though the inode isn't
3156 * really reachable, set the flag (and bump our link
3157 * count) anyway to fool phase 7
3158 */
3159 add_inode_reached(irec, i);
6c39a3cb
BN
3160 }
3161}
3162
a1d54891 3163static void
2556c98b 3164traverse_function(
62843f36 3165 struct workqueue *wq,
2556c98b
BN
3166 xfs_agnumber_t agno,
3167 void *arg)
a1d54891 3168{
2556c98b
BN
3169 ino_tree_node_t *irec;
3170 int i;
3171 prefetch_args_t *pf_args = arg;
3172
3173 wait_for_inode_prefetch(pf_args);
a1d54891
MV
3174
3175 if (verbose)
3176 do_log(_(" - agno = %d\n"), agno);
3177
2556c98b
BN
3178 for (irec = findfirst_inode_rec(agno); irec; irec = next_ino_rec(irec)) {
3179 if (irec->ino_isa_dir == 0)
3180 continue;
a1d54891 3181
004e18d4 3182 if (pf_args) {
2556c98b 3183 sem_post(&pf_args->ra_count);
004e18d4
DC
3184#ifdef XR_PF_TRACE
3185 sem_getvalue(&pf_args->ra_count, &i);
3186 pftrace(
3187 "processing inode chunk %p in AG %d (sem count = %d)",
3188 irec, agno, i);
3189#endif
3190 }
a1d54891 3191
2556c98b
BN
3192 for (i = 0; i < XFS_INODES_PER_CHUNK; i++) {
3193 if (inode_isadir(irec, i))
62843f36 3194 process_dir_inode(wq->wq_ctx, agno, irec, i);
a1d54891 3195 }
a1d54891 3196 }
2556c98b 3197 cleanup_inode_prefetch(pf_args);
a1d54891
MV
3198}
3199
575ca697
BN
3200static void
3201update_missing_dotdot_entries(
3202 xfs_mount_t *mp)
3203{
3204 dotdot_update_t *dir;
3205
3206 /*
3207 * these entries parents were updated, rebuild them again
3208 * set dotdot_update flag so processing routines do not count links
3209 */
3210 dotdot_update = 1;
1177f669
DC
3211 while (!list_empty(&dotdot_update_list)) {
3212 dir = list_entry(dotdot_update_list.prev, struct dotdot_update,
3213 list);
3214 list_del(&dir->list);
575ca697
BN
3215 process_dir_inode(mp, dir->agno, dir->irec, dir->ino_offset);
3216 free(dir);
3217 }
3218}
3219
a1d54891 3220static void
2556c98b 3221traverse_ags(
1164bde5 3222 struct xfs_mount *mp)
a1d54891 3223{
1164bde5 3224 do_inode_prefetch(mp, 0, traverse_function, false, true);
a1d54891
MV
3225}
3226
2bd0ea18
NS
3227void
3228phase6(xfs_mount_t *mp)
3229{
2bd0ea18 3230 ino_tree_node_t *irec;
2bd0ea18 3231 int i;
2bd0ea18 3232
dab9b8d6
BN
3233 memset(&zerocr, 0, sizeof(struct cred));
3234 memset(&zerofsx, 0, sizeof(struct fsxattr));
6c39a3cb 3235 orphanage_ino = 0;
2bd0ea18 3236
507f4e33 3237 do_log(_("Phase 6 - check inode connectivity...\n"));
2bd0ea18 3238
2bd0ea18
NS
3239 incore_ext_teardown(mp);
3240
0f012a4c 3241 add_ino_ex_data(mp);
2bd0ea18
NS
3242
3243 /*
3244 * verify existence of root directory - if we have to
3245 * make one, it's ok for the incore data structs not to
3246 * know about it since everything about it (and the other
3247 * inodes in its chunk if a new chunk was created) are ok
3248 */
3249 if (need_root_inode) {
9a048535 3250 if (!no_modify) {
507f4e33 3251 do_warn(_("reinitializing root directory\n"));
2bd0ea18
NS
3252 mk_root_dir(mp);
3253 need_root_inode = 0;
3254 need_root_dotdot = 0;
3255 } else {
507f4e33 3256 do_warn(_("would reinitialize root directory\n"));
2bd0ea18
NS
3257 }
3258 }
3259
3260 if (need_rbmino) {
3261 if (!no_modify) {
507f4e33 3262 do_warn(_("reinitializing realtime bitmap inode\n"));
2bd0ea18
NS
3263 mk_rbmino(mp);
3264 need_rbmino = 0;
3265 } else {
507f4e33 3266 do_warn(_("would reinitialize realtime bitmap inode\n"));
2bd0ea18
NS
3267 }
3268 }
3269
3270 if (need_rsumino) {
3271 if (!no_modify) {
507f4e33 3272 do_warn(_("reinitializing realtime summary inode\n"));
2bd0ea18
NS
3273 mk_rsumino(mp);
3274 need_rsumino = 0;
3275 } else {
507f4e33 3276 do_warn(_("would reinitialize realtime summary inode\n"));
2bd0ea18
NS
3277 }
3278 }
3279
3280 if (!no_modify) {
3281 do_log(
507f4e33 3282_(" - resetting contents of realtime bitmap and summary inodes\n"));
2bd0ea18
NS
3283 if (fill_rbmino(mp)) {
3284 do_warn(
507f4e33 3285 _("Warning: realtime bitmap may be inconsistent\n"));
2bd0ea18
NS
3286 }
3287
3288 if (fill_rsumino(mp)) {
3289 do_warn(
507f4e33 3290 _("Warning: realtime bitmap may be inconsistent\n"));
2bd0ea18
NS
3291 }
3292 }
3293
2bd0ea18
NS
3294 mark_standalone_inodes(mp);
3295
69ec88b5 3296 do_log(_(" - traversing filesystem ...\n"));
2bd0ea18 3297
1ae311d5 3298 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino),
2bd0ea18
NS
3299 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino));
3300
3301 /*
3302 * we always have a root inode, even if it's free...
3303 * if the root is free, forget it, lost+found is already gone
3304 */
3305 if (is_inode_free(irec, 0) || !inode_isadir(irec, 0)) {
3306 need_root_inode = 1;
3307 }
3308
3309 /*
2556c98b 3310 * then process all inodes by walking incore inode tree
2bd0ea18 3311 */
2556c98b 3312 traverse_ags(mp);
2bd0ea18 3313
575ca697
BN
3314 /*
3315 * any directories that had updated ".." entries, rebuild them now
3316 */
3317 update_missing_dotdot_entries(mp);
3318
69ec88b5
BN
3319 do_log(_(" - traversal finished ...\n"));
3320 do_log(_(" - moving disconnected inodes to %s ...\n"),
6c39a3cb 3321 ORPHANAGE);
2bd0ea18
NS
3322
3323 /*
3324 * move all disconnected inodes to the orphanage
3325 */
3326 for (i = 0; i < glob_agcount; i++) {
3327 irec = findfirst_inode_rec(i);
2bd0ea18 3328 while (irec != NULL) {
2556c98b 3329 check_for_orphaned_inodes(mp, i, irec);
2bd0ea18
NS
3330 irec = next_ino_rec(irec);
3331 }
3332 }
3333}