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