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