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