]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - repair/phase6.c
xfs_repair: estimate per-AG btree slack better
[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);
1179 if (!no_modify) {
1180 if (verbose)
1181 do_warn(_(", marking entry to be junked\n"));
9a048535
DC
1182 else
1183 do_warn("\n");
1184 } else
1185 do_warn(_(", would junk entry\n"));
1186 return !no_modify;
2bd0ea18
NS
1187}
1188
f9c559f4
DW
1189/* Find and invalidate all the directory's buffers. */
1190static int
1191dir_binval(
1192 struct xfs_trans *tp,
1193 struct xfs_inode *ip,
1194 int whichfork)
1195{
1196 struct xfs_iext_cursor icur;
1197 struct xfs_bmbt_irec rec;
1198 struct xfs_ifork *ifp;
1199 struct xfs_da_geometry *geo;
1200 struct xfs_buf *bp;
3f6bf952 1201 xfs_dablk_t dabno;
f9c559f4
DW
1202 int error = 0;
1203
d967a68d
CH
1204 if (ip->i_df.if_format != XFS_DINODE_FMT_EXTENTS &&
1205 ip->i_df.if_format != XFS_DINODE_FMT_BTREE)
f9c559f4
DW
1206 return 0;
1207
1208 geo = tp->t_mountp->m_dir_geo;
722e81c1 1209 ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK);
f9c559f4 1210 for_each_xfs_iext(ifp, &icur, &rec) {
3f6bf952
DW
1211 for (dabno = roundup(rec.br_startoff, geo->fsbcount);
1212 dabno < rec.br_startoff + rec.br_blockcount;
1213 dabno += geo->fsbcount) {
f9c559f4 1214 bp = NULL;
c1d19744 1215 error = -libxfs_da_get_buf(tp, ip, dabno, &bp,
f9c559f4
DW
1216 whichfork);
1217 if (error)
1218 return error;
1219 if (!bp)
1220 continue;
1221 libxfs_trans_binval(tp, bp);
1222 libxfs_trans_brelse(tp, bp);
1223 }
1224 }
1225
1226 return error;
1227}
1228
33165ec3
BN
1229/*
1230 * Unexpected failure during the rebuild will leave the entries in
1231 * lost+found on the next run
1232 */
1233
0f012a4c 1234static void
33165ec3 1235longform_dir2_rebuild(
266b73fa 1236 struct xfs_mount *mp,
6fa00c33 1237 xfs_ino_t ino,
266b73fa
DC
1238 struct xfs_inode *ip,
1239 struct ino_tree_node *irec,
6fa00c33 1240 int ino_offset,
266b73fa 1241 struct dir_hash_tab *hashtab)
33165ec3
BN
1242{
1243 int error;
1244 int nres;
266b73fa 1245 struct xfs_trans *tp;
33165ec3 1246 xfs_fileoff_t lastblock;
266b73fa
DC
1247 struct xfs_inode pip;
1248 struct dir_hash_ent *p;
ea7be342 1249 int done = 0;
0f012a4c
BN
1250
1251 /*
33165ec3
BN
1252 * trash directory completely and rebuild from scratch using the
1253 * name/inode pairs in the hash table
1254 */
0f012a4c 1255
5d1b7f0f 1256 do_warn(_("rebuilding directory inode %" PRIu64 "\n"), ino);
0f012a4c
BN
1257
1258 /*
6fa00c33
BN
1259 * first attempt to locate the parent inode, if it can't be
1260 * found, set it to the root inode and it'll be moved to the
1261 * orphanage later (the inode number here needs to be valid
5e656dbb 1262 * for the libxfs_dir_init() call).
33165ec3 1263 */
6fa00c33 1264 pip.i_ino = get_inode_parent(irec, ino_offset);
01914f06 1265 if (pip.i_ino == NULLFSINO ||
e2f60652 1266 libxfs_dir_ino_validate(mp, pip.i_ino))
6fa00c33 1267 pip.i_ino = mp->m_sb.sb_rootino;
33165ec3 1268
33165ec3 1269 nres = XFS_REMOVE_SPACE_RES(mp);
9074815c 1270 error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, nres, 0, 0, &tp);
33165ec3
BN
1271 if (error)
1272 res_failed(error);
1273 libxfs_trans_ijoin(tp, ip, 0);
0f012a4c 1274
f9c559f4
DW
1275 error = dir_binval(tp, ip, XFS_DATA_FORK);
1276 if (error)
af06261f
DW
1277 do_error(_("error %d invalidating directory %llu blocks\n"),
1278 error, (unsigned long long)ip->i_ino);
f9c559f4 1279
12b53197 1280 if ((error = -libxfs_bmap_last_offset(ip, &lastblock, XFS_DATA_FORK)))
0f012a4c 1281 do_error(_("xfs_bmap_last_offset failed -- error - %d\n"),
33165ec3 1282 error);
0f012a4c 1283
33165ec3 1284 /* free all data, leaf, node and freespace blocks */
ea7be342
ES
1285 while (!done) {
1286 error = -libxfs_bunmapi(tp, ip, 0, lastblock, XFS_BMAPI_METADATA,
1287 0, &done);
1288 if (error) {
1289 do_warn(_("xfs_bunmapi failed -- error - %d\n"), error);
1290 goto out_bmap_cancel;
1291 }
1292 error = -libxfs_defer_finish(&tp);
1293 if (error) {
1294 do_warn(("defer_finish failed -- error - %d\n"), error);
1295 goto out_bmap_cancel;
1296 }
1297 /*
1298 * Close out trans and start the next one in the chain.
1299 */
1300 error = -libxfs_trans_roll_inode(&tp, ip);
1301 if (error)
1302 goto out_bmap_cancel;
1303 }
33165ec3 1304
e2f60652 1305 error = -libxfs_dir_init(tp, ip, &pip);
01914f06
DW
1306 if (error) {
1307 do_warn(_("xfs_dir_init failed -- error - %d\n"), error);
1308 goto out_bmap_cancel;
1309 }
0f012a4c 1310
f2279d8d
DW
1311 error = -libxfs_trans_commit(tp);
1312 if (error)
1313 do_error(
1314 _("dir init failed (%d)\n"), error);
0f012a4c 1315
1f60de28
ES
1316 if (ino == mp->m_sb.sb_rootino)
1317 need_root_dotdot = 0;
1318
33165ec3
BN
1319 /* go through the hash list and re-add the inodes */
1320
1321 for (p = hashtab->first; p; p = p->nextbyorder) {
0f012a4c 1322
5e656dbb
BN
1323 if (p->name.name[0] == '/' || (p->name.name[0] == '.' &&
1324 (p->name.len == 1 || (p->name.len == 2 &&
1325 p->name.name[1] == '.'))))
33165ec3 1326 continue;
0f012a4c 1327
5e656dbb 1328 nres = XFS_CREATE_SPACE_RES(mp, p->name.len);
9074815c
CH
1329 error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_create,
1330 nres, 0, 0, &tp);
14e36e34
LZ
1331 if (error)
1332 res_failed(error);
33165ec3
BN
1333
1334 libxfs_trans_ijoin(tp, ip, 0);
33165ec3 1335
12b53197 1336 error = -libxfs_dir_createname(tp, ip, &p->name, p->inum,
015bc82e 1337 nres);
5e656dbb 1338 if (error) {
33165ec3 1339 do_warn(
12518245 1340_("name create failed in ino %" PRIu64 " (%d)\n"), ino, error);
14e36e34 1341 goto out_bmap_cancel;
33165ec3
BN
1342 }
1343
f2279d8d
DW
1344 error = -libxfs_trans_commit(tp);
1345 if (error)
1346 do_error(
1347_("name create failed (%d) during rebuild\n"), error);
33165ec3 1348 }
14e36e34
LZ
1349
1350 return;
1351
1352out_bmap_cancel:
3d7434fe 1353 libxfs_trans_cancel(tp);
14e36e34 1354 return;
33165ec3
BN
1355}
1356
1357
2bd0ea18
NS
1358/*
1359 * Kill a block in a version 2 inode.
1360 * Makes its own transaction.
1361 */
1362static void
1363dir2_kill_block(
1364 xfs_mount_t *mp,
1365 xfs_inode_t *ip,
1366 xfs_dablk_t da_bno,
a2ceac1f 1367 struct xfs_buf *bp)
2bd0ea18
NS
1368{
1369 xfs_da_args_t args;
2bd0ea18 1370 int error;
2bd0ea18
NS
1371 int nres;
1372 xfs_trans_t *tp;
1373
2bd0ea18 1374 nres = XFS_REMOVE_SPACE_RES(mp);
9074815c 1375 error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, nres, 0, 0, &tp);
2bd0ea18
NS
1376 if (error)
1377 res_failed(error);
1378 libxfs_trans_ijoin(tp, ip, 0);
a2ceac1f 1379 libxfs_trans_bjoin(tp, bp);
1f7c7553 1380 libxfs_trans_bhold(tp, bp);
dab9b8d6 1381 memset(&args, 0, sizeof(args));
2bd0ea18
NS
1382 args.dp = ip;
1383 args.trans = tp;
2bd0ea18 1384 args.whichfork = XFS_DATA_FORK;
fe0591e7 1385 args.geo = mp->m_dir_geo;
ff105f75 1386 if (da_bno >= mp->m_dir_geo->leafblk && da_bno < mp->m_dir_geo->freeblk)
12b53197 1387 error = -libxfs_da_shrink_inode(&args, da_bno, bp);
2bd0ea18 1388 else
12b53197 1389 error = -libxfs_dir2_shrink_inode(&args,
ff105f75 1390 xfs_dir2_da_to_db(mp->m_dir_geo, da_bno), bp);
2bd0ea18 1391 if (error)
5d1b7f0f 1392 do_error(_("shrink_inode failed inode %" PRIu64 " block %u\n"),
2bd0ea18 1393 ip->i_ino, da_bno);
f2279d8d
DW
1394 error = -libxfs_trans_commit(tp);
1395 if (error)
1396 do_error(
1397_("directory shrink failed (%d)\n"), error);
2bd0ea18
NS
1398}
1399
9887f0ad
DW
1400static inline void
1401check_longform_ftype(
1402 struct xfs_mount *mp,
1403 struct xfs_inode *ip,
1404 xfs_dir2_data_entry_t *dep,
1405 ino_tree_node_t *irec,
1406 int ino_offset,
1407 struct dir_hash_tab *hashtab,
1408 xfs_dir2_dataptr_t addr,
1409 struct xfs_da_args *da,
1410 struct xfs_buf *bp)
1411{
1412 xfs_ino_t inum = be64_to_cpu(dep->inumber);
1413 uint8_t dir_ftype;
1414 uint8_t ino_ftype;
1415
1416 if (!xfs_has_ftype(mp))
1417 return;
1418
1419 dir_ftype = libxfs_dir2_data_get_ftype(mp, dep);
1420 ino_ftype = get_inode_ftype(irec, ino_offset);
1421
1422 if (dir_ftype == ino_ftype)
1423 return;
1424
1425 if (no_modify) {
1426 do_warn(
1427_("would fix ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"),
1428 dir_ftype, ino_ftype,
1429 ip->i_ino, inum);
1430 return;
1431 }
1432
1433 do_warn(
1434_("fixing ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"),
1435 dir_ftype, ino_ftype,
1436 ip->i_ino, inum);
1437 libxfs_dir2_data_put_ftype(mp, dep, ino_ftype);
1438 libxfs_dir2_data_log_entry(da, bp, dep);
1439 dir_hash_update_ftype(hashtab, addr, ino_ftype);
1440}
1441
2bd0ea18
NS
1442/*
1443 * process a data block, also checks for .. entry
1444 * and corrects it to match what we think .. should be
1445 */
1446static void
1447longform_dir2_entry_check_data(
266b73fa
DC
1448 struct xfs_mount *mp,
1449 struct xfs_inode *ip,
2bd0ea18
NS
1450 int *num_illegal,
1451 int *need_dot,
266b73fa 1452 struct ino_tree_node *current_irec,
2bd0ea18 1453 int current_ino_offset,
1f7c7553 1454 struct xfs_buf *bp,
266b73fa 1455 struct dir_hash_tab *hashtab,
2bd0ea18
NS
1456 freetab_t **freetabp,
1457 xfs_dablk_t da_bno,
1a3bfffe 1458 bool isblock)
2bd0ea18
NS
1459{
1460 xfs_dir2_dataptr_t addr;
1461 xfs_dir2_leaf_entry_t *blp;
2bd0ea18 1462 xfs_dir2_block_tail_t *btp;
a354abc8 1463 struct xfs_dir2_data_hdr *d;
2bd0ea18
NS
1464 xfs_dir2_db_t db;
1465 xfs_dir2_data_entry_t *dep;
1466 xfs_dir2_data_unused_t *dup;
d2006f04 1467 struct xfs_dir2_data_free *bf;
2bd0ea18
NS
1468 char *endptr;
1469 int error;
2bd0ea18
NS
1470 char fname[MAXNAMELEN + 1];
1471 freetab_t *freetab;
1472 int i;
1473 int ino_offset;
33165ec3 1474 xfs_ino_t inum;
2bd0ea18
NS
1475 ino_tree_node_t *irec;
1476 int junkit;
1477 int lastfree;
1478 int len;
1479 int nbad;
1480 int needlog;
1481 int needscan;
1482 xfs_ino_t parent;
1483 char *ptr;
1484 xfs_trans_t *tp;
1485 int wantmagic;
ff105f75
DC
1486 struct xfs_da_args da = {
1487 .dp = ip,
a5459506 1488 .geo = mp->m_dir_geo,
ff105f75
DC
1489 };
1490
2bd0ea18 1491
a2ceac1f 1492 d = bp->b_addr;
58a1d356 1493 ptr = (char *)d + mp->m_dir_geo->data_entry_offset;
2bd0ea18
NS
1494 nbad = 0;
1495 needscan = needlog = 0;
9d7d6241 1496 junkit = 0;
2bd0ea18
NS
1497 freetab = *freetabp;
1498 if (isblock) {
ff105f75 1499 btp = xfs_dir2_block_tail_p(mp->m_dir_geo, d);
5e656dbb 1500 blp = xfs_dir2_block_leaf_p(btp);
2bd0ea18
NS
1501 endptr = (char *)blp;
1502 if (endptr > (char *)btp)
1503 endptr = (char *)btp;
2660e653 1504 if (xfs_has_crc(mp))
658ac3e3
DC
1505 wantmagic = XFS_DIR3_BLOCK_MAGIC;
1506 else
1507 wantmagic = XFS_DIR2_BLOCK_MAGIC;
2bd0ea18 1508 } else {
ff105f75 1509 endptr = (char *)d + mp->m_dir_geo->blksize;
2660e653 1510 if (xfs_has_crc(mp))
658ac3e3
DC
1511 wantmagic = XFS_DIR3_DATA_MAGIC;
1512 else
1513 wantmagic = XFS_DIR2_DATA_MAGIC;
2bd0ea18 1514 }
ff105f75 1515 db = xfs_dir2_da_to_db(mp->m_dir_geo, da_bno);
9d7d6241
NS
1516
1517 /* check for data block beyond expected end */
2bd0ea18
NS
1518 if (freetab->naents <= db) {
1519 struct freetab_ent e;
1520
1521 *freetabp = freetab = realloc(freetab, FREETAB_SIZE(db + 1));
1522 if (!freetab) {
15e3986b
DC
1523 do_error(_("realloc failed in %s (%zu bytes)\n"),
1524 __func__, FREETAB_SIZE(db + 1));
2bd0ea18
NS
1525 }
1526 e.v = NULLDATAOFF;
1527 e.s = 0;
1528 for (i = freetab->naents; i < db; i++)
1529 freetab->ents[i] = e;
1530 freetab->naents = db + 1;
1531 }
9d7d6241
NS
1532
1533 /* check the data block */
2bd0ea18 1534 while (ptr < endptr) {
9d7d6241
NS
1535
1536 /* check for freespace */
2bd0ea18 1537 dup = (xfs_dir2_data_unused_t *)ptr;
5e656dbb 1538 if (XFS_DIR2_DATA_FREE_TAG == be16_to_cpu(dup->freetag)) {
9d7d6241
NS
1539
1540 /* check for invalid freespace length */
5e656dbb
BN
1541 if (ptr + be16_to_cpu(dup->length) > endptr ||
1542 be16_to_cpu(dup->length) == 0 ||
1543 (be16_to_cpu(dup->length) &
1544 (XFS_DIR2_DATA_ALIGN - 1)))
2bd0ea18 1545 break;
9d7d6241
NS
1546
1547 /* check for invalid tag */
5e656dbb
BN
1548 if (be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) !=
1549 (char *)dup - (char *)d)
2bd0ea18 1550 break;
9d7d6241
NS
1551
1552 /* check for block with no data entries */
58a1d356 1553 if ((ptr == (char *)d + mp->m_dir_geo->data_entry_offset) &&
658ac3e3 1554 (ptr + be16_to_cpu(dup->length) >= endptr)) {
9d7d6241
NS
1555 junkit = 1;
1556 *num_illegal += 1;
1557 break;
1558 }
1559
1560 /* continue at the end of the freespace */
5e656dbb 1561 ptr += be16_to_cpu(dup->length);
2bd0ea18
NS
1562 if (ptr >= endptr)
1563 break;
1564 }
9d7d6241
NS
1565
1566 /* validate data entry size */
2bd0ea18 1567 dep = (xfs_dir2_data_entry_t *)ptr;
271a654f 1568 if (ptr + libxfs_dir2_data_entsize(mp, dep->namelen) > endptr)
2bd0ea18 1569 break;
823711f2 1570 if (be16_to_cpu(*libxfs_dir2_data_entry_tag_p(mp, dep)) !=
5e656dbb 1571 (char *)dep - (char *)d)
2bd0ea18 1572 break;
271a654f 1573 ptr += libxfs_dir2_data_entsize(mp, dep->namelen);
2bd0ea18 1574 }
9d7d6241
NS
1575
1576 /* did we find an empty or corrupt block? */
2bd0ea18 1577 if (ptr != endptr) {
9d7d6241 1578 if (junkit) {
507f4e33 1579 do_warn(
5d1b7f0f 1580 _("empty data block %u in directory inode %" PRIu64 ": "),
9d7d6241
NS
1581 da_bno, ip->i_ino);
1582 } else {
5d1b7f0f
CH
1583 do_warn(_
1584 ("corrupt block %u in directory inode %" PRIu64 ": "),
9d7d6241
NS
1585 da_bno, ip->i_ino);
1586 }
2bd0ea18 1587 if (!no_modify) {
507f4e33 1588 do_warn(_("junking block\n"));
2bd0ea18
NS
1589 dir2_kill_block(mp, ip, da_bno, bp);
1590 } else {
507f4e33 1591 do_warn(_("would junk block\n"));
2bd0ea18
NS
1592 }
1593 freetab->ents[db].v = NULLDATAOFF;
2bd0ea18
NS
1594 return;
1595 }
9d7d6241
NS
1596
1597 /* update number of data blocks processed */
1598 if (freetab->nents < db + 1)
1599 freetab->nents = db + 1;
1600
9074815c 1601 error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, 0, 0, 0, &tp);
2bd0ea18
NS
1602 if (error)
1603 res_failed(error);
ff105f75 1604 da.trans = tp;
2bd0ea18 1605 libxfs_trans_ijoin(tp, ip, 0);
a2ceac1f
DC
1606 libxfs_trans_bjoin(tp, bp);
1607 libxfs_trans_bhold(tp, bp);
a354abc8 1608 if (be32_to_cpu(d->magic) != wantmagic) {
5d1b7f0f
CH
1609 do_warn(
1610 _("bad directory block magic # %#x for directory inode %" PRIu64 " block %d: "),
a354abc8 1611 be32_to_cpu(d->magic), ip->i_ino, da_bno);
2bd0ea18 1612 if (!no_modify) {
507f4e33 1613 do_warn(_("fixing magic # to %#x\n"), wantmagic);
a354abc8 1614 d->magic = cpu_to_be32(wantmagic);
2bd0ea18
NS
1615 needlog = 1;
1616 } else
507f4e33 1617 do_warn(_("would fix magic # to %#x\n"), wantmagic);
2bd0ea18
NS
1618 }
1619 lastfree = 0;
58a1d356 1620 ptr = (char *)d + mp->m_dir_geo->data_entry_offset;
2bd0ea18
NS
1621 /*
1622 * look at each entry. reference inode pointed to by each
1623 * entry in the incore inode tree.
1624 * if not a directory, set reached flag, increment link count
1625 * if a directory and reached, mark entry as to be deleted.
1626 * if a directory, check to see if recorded parent
1627 * matches current inode #,
1628 * if so, then set reached flag, increment link count
1629 * of current and child dir inodes, push the child
1630 * directory inode onto the directory stack.
1631 * if current inode != parent, then mark entry to be deleted.
1632 */
1633 while (ptr < endptr) {
1634 dup = (xfs_dir2_data_unused_t *)ptr;
5e656dbb 1635 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
2bd0ea18 1636 if (lastfree) {
5d1b7f0f
CH
1637 do_warn(
1638 _("directory inode %" PRIu64 " block %u has consecutive free entries: "),
2bd0ea18
NS
1639 ip->i_ino, da_bno);
1640 if (!no_modify) {
ff105f75 1641
507f4e33 1642 do_warn(_("joining together\n"));
5e656dbb 1643 len = be16_to_cpu(dup->length);
ff105f75 1644 libxfs_dir2_data_use_free(&da, bp, dup,
2bd0ea18
NS
1645 ptr - (char *)d, len, &needlog,
1646 &needscan);
ff105f75 1647 libxfs_dir2_data_make_free(&da, bp,
2bd0ea18
NS
1648 ptr - (char *)d, len, &needlog,
1649 &needscan);
1650 } else
507f4e33 1651 do_warn(_("would join together\n"));
2bd0ea18 1652 }
5e656dbb 1653 ptr += be16_to_cpu(dup->length);
2bd0ea18
NS
1654 lastfree = 1;
1655 continue;
1656 }
ff105f75
DC
1657 addr = xfs_dir2_db_off_to_dataptr(mp->m_dir_geo, db,
1658 ptr - (char *)d);
2bd0ea18 1659 dep = (xfs_dir2_data_entry_t *)ptr;
271a654f 1660 ptr += libxfs_dir2_data_entsize(mp, dep->namelen);
5e656dbb 1661 inum = be64_to_cpu(dep->inumber);
2bd0ea18 1662 lastfree = 0;
2bd0ea18
NS
1663 /*
1664 * skip bogus entries (leading '/'). they'll be deleted
c7f277c9
NS
1665 * later. must still log it, else we leak references to
1666 * buffers.
2bd0ea18
NS
1667 */
1668 if (dep->name[0] == '/') {
1669 nbad++;
c7f277c9 1670 if (!no_modify)
ff105f75 1671 libxfs_dir2_data_log_entry(&da, bp, dep);
2bd0ea18
NS
1672 continue;
1673 }
2556c98b 1674
dab9b8d6 1675 memmove(fname, dep->name, dep->namelen);
2bd0ea18 1676 fname[dep->namelen] = '\0';
33165ec3 1677 ASSERT(inum != NULLFSINO);
6c39a3cb 1678
1ae311d5 1679 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, inum),
6c39a3cb
BN
1680 XFS_INO_TO_AGINO(mp, inum));
1681 if (irec == NULL) {
1682 nbad++;
5d1b7f0f
CH
1683 if (entry_junked(
1684 _("entry \"%s\" in directory inode %" PRIu64 " points to non-existent inode %" PRIu64 ""),
6c39a3cb
BN
1685 fname, ip->i_ino, inum)) {
1686 dep->name[0] = '/';
ff105f75 1687 libxfs_dir2_data_log_entry(&da, bp, dep);
6c39a3cb
BN
1688 }
1689 continue;
1690 }
1691 ino_offset = XFS_INO_TO_AGINO(mp, inum) - irec->ino_startnum;
1692
1693 /*
1694 * if it's a free inode, blow out the entry.
1695 * by now, any inode that we think is free
1696 * really is free.
1697 */
1698 if (is_inode_free(irec, ino_offset)) {
1699 nbad++;
5d1b7f0f 1700 if (entry_junked(
b52923f3 1701 _("entry \"%s\" in directory inode %" PRIu64 " points to free inode %" PRIu64),
6c39a3cb
BN
1702 fname, ip->i_ino, inum)) {
1703 dep->name[0] = '/';
ff105f75 1704 libxfs_dir2_data_log_entry(&da, bp, dep);
6c39a3cb
BN
1705 }
1706 continue;
1707 }
1708
1709 /*
1710 * check if this inode is lost+found dir in the root
1711 */
1712 if (inum == mp->m_sb.sb_rootino && strcmp(fname, ORPHANAGE) == 0) {
1713 /*
1714 * if it's not a directory, trash it
1715 */
1716 if (!inode_isadir(irec, ino_offset)) {
1717 nbad++;
5d1b7f0f
CH
1718 if (entry_junked(
1719 _("%s (ino %" PRIu64 ") in root (%" PRIu64 ") is not a directory"),
6c39a3cb
BN
1720 ORPHANAGE, inum, ip->i_ino)) {
1721 dep->name[0] = '/';
ff105f75 1722 libxfs_dir2_data_log_entry(&da, bp, dep);
6c39a3cb
BN
1723 }
1724 continue;
1725 }
1726 /*
1727 * if this is a dup, it will be picked up below,
1728 * otherwise, mark it as the orphanage for later.
1729 */
1730 if (!orphanage_ino)
1731 orphanage_ino = inum;
1732 }
aaca101b 1733
6c39a3cb
BN
1734 /*
1735 * check for duplicate names in directory.
1736 */
51ca7008 1737 if (!dir_hash_add(mp, hashtab, addr, inum, dep->namelen,
28e6e614 1738 dep->name, libxfs_dir2_data_get_ftype(mp, dep))) {
6c39a3cb 1739 nbad++;
5d1b7f0f
CH
1740 if (entry_junked(
1741 _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"),
6c39a3cb
BN
1742 fname, inum, ip->i_ino)) {
1743 dep->name[0] = '/';
ff105f75 1744 libxfs_dir2_data_log_entry(&da, bp, dep);
6c39a3cb
BN
1745 }
1746 if (inum == orphanage_ino)
1747 orphanage_ino = 0;
1748 continue;
1749 }
1750
575ca697
BN
1751 /*
1752 * if just scanning to rebuild a directory due to a ".."
1753 * update, just continue
1754 */
1755 if (dotdot_update)
1756 continue;
1757
2bd0ea18
NS
1758 /*
1759 * skip the '..' entry since it's checked when the
1760 * directory is reached by something else. if it never
1761 * gets reached, it'll be moved to the orphanage and we'll
6fa00c33
BN
1762 * take care of it then. If it doesn't exist at all, the
1763 * directory needs to be rebuilt first before being added
1764 * to the orphanage.
2bd0ea18
NS
1765 */
1766 if (dep->namelen == 2 && dep->name[0] == '.' &&
6fa00c33
BN
1767 dep->name[1] == '.') {
1768 if (da_bno != 0) {
1769 /* ".." should be in the first block */
1770 nbad++;
5d1b7f0f
CH
1771 if (entry_junked(
1772 _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is not in the the first block"), fname,
6fa00c33 1773 inum, ip->i_ino)) {
f1ea06d0 1774 dir_hash_junkit(hashtab, addr);
6fa00c33 1775 dep->name[0] = '/';
ff105f75 1776 libxfs_dir2_data_log_entry(&da, bp, dep);
6fa00c33
BN
1777 }
1778 }
9887f0ad
DW
1779
1780 if (!nbad)
1781 check_longform_ftype(mp, ip, dep, irec,
1782 ino_offset, hashtab, addr, &da,
1783 bp);
2bd0ea18 1784 continue;
6fa00c33 1785 }
017e979e 1786 ASSERT(no_modify || libxfs_verify_dir_ino(mp, inum));
2bd0ea18
NS
1787 /*
1788 * special case the . entry. we know there's only one
1789 * '.' and only '.' points to itself because bogus entries
1790 * got trashed in phase 3 if there were > 1.
1791 * bump up link count for '.' but don't set reached
1792 * until we're actually reached by another directory
1793 * '..' is already accounted for or will be taken care
1794 * of when directory is moved to orphanage.
1795 */
33165ec3 1796 if (ip->i_ino == inum) {
369c0b5f
DW
1797 ASSERT(no_modify ||
1798 (dep->name[0] == '.' && dep->namelen == 1));
2bd0ea18 1799 add_inode_ref(current_irec, current_ino_offset);
658ac3e3 1800 if (da_bno != 0 ||
58a1d356 1801 dep != (void *)d + mp->m_dir_geo->data_entry_offset) {
6fa00c33
BN
1802 /* "." should be the first entry */
1803 nbad++;
5d1b7f0f
CH
1804 if (entry_junked(
1805 _("entry \"%s\" in dir %" PRIu64 " is not the first entry"),
6fa00c33 1806 fname, inum, ip->i_ino)) {
f1ea06d0 1807 dir_hash_junkit(hashtab, addr);
6fa00c33 1808 dep->name[0] = '/';
ff105f75 1809 libxfs_dir2_data_log_entry(&da, bp, dep);
6fa00c33
BN
1810 }
1811 }
9887f0ad
DW
1812
1813 if (!nbad)
1814 check_longform_ftype(mp, ip, dep, irec,
1815 ino_offset, hashtab, addr, &da,
1816 bp);
2bd0ea18
NS
1817 *need_dot = 0;
1818 continue;
1819 }
2bd0ea18
NS
1820 /*
1821 * skip entries with bogus inumbers if we're in no modify mode
1822 */
017e979e 1823 if (no_modify && !libxfs_verify_dir_ino(mp, inum))
2bd0ea18 1824 continue;
aaca101b
DC
1825
1826 /* validate ftype field if supported */
9887f0ad
DW
1827 check_longform_ftype(mp, ip, dep, irec, ino_offset, hashtab,
1828 addr, &da, bp);
aaca101b 1829
2bd0ea18
NS
1830 /*
1831 * check easy case first, regular inode, just bump
1832 * the link count and continue
1833 */
1834 if (!inode_isadir(irec, ino_offset)) {
1835 add_inode_reached(irec, ino_offset);
1836 continue;
1837 }
1838 parent = get_inode_parent(irec, ino_offset);
978c3087
DW
1839 if (parent == 0) {
1840 if (no_modify)
1841 do_warn(
1842 _("unknown parent for inode %" PRIu64 "\n"),
1843 inum);
1844 else
1845 ASSERT(parent != 0);
1846 }
6c39a3cb 1847 junkit = 0;
2bd0ea18
NS
1848 /*
1849 * bump up the link counts in parent and child
1850 * directory but if the link doesn't agree with
1851 * the .. in the child, blow out the entry.
1852 * if the directory has already been reached,
1853 * blow away the entry also.
1854 */
1855 if (is_inode_reached(irec, ino_offset)) {
1856 junkit = 1;
507f4e33 1857 do_warn(
5d1b7f0f 1858_("entry \"%s\" in dir %" PRIu64" points to an already connected directory inode %" PRIu64 "\n"),
33165ec3 1859 fname, ip->i_ino, inum);
2bd0ea18
NS
1860 } else if (parent == ip->i_ino) {
1861 add_inode_reached(irec, ino_offset);
1862 add_inode_ref(current_irec, current_ino_offset);
6fa00c33
BN
1863 } else if (parent == NULLFSINO) {
1864 /* ".." was missing, but this entry refers to it,
1865 so, set it as the parent and mark for rebuild */
5d1b7f0f
CH
1866 do_warn(
1867 _("entry \"%s\" in dir ino %" PRIu64 " doesn't have a .. entry, will set it in ino %" PRIu64 ".\n"),
6fa00c33
BN
1868 fname, ip->i_ino, inum);
1869 set_inode_parent(irec, ino_offset, ip->i_ino);
1870 add_inode_reached(irec, ino_offset);
1871 add_inode_ref(current_irec, current_ino_offset);
575ca697
BN
1872 add_dotdot_update(XFS_INO_TO_AGNO(mp, inum), irec,
1873 ino_offset);
2bd0ea18
NS
1874 } else {
1875 junkit = 1;
507f4e33 1876 do_warn(
5d1b7f0f 1877_("entry \"%s\" in dir inode %" PRIu64 " inconsistent with .. value (%" PRIu64 ") in ino %" PRIu64 "\n"),
33165ec3 1878 fname, ip->i_ino, parent, inum);
2bd0ea18
NS
1879 }
1880 if (junkit) {
6c39a3cb
BN
1881 if (inum == orphanage_ino)
1882 orphanage_ino = 0;
2bd0ea18
NS
1883 nbad++;
1884 if (!no_modify) {
f1ea06d0 1885 dir_hash_junkit(hashtab, addr);
2bd0ea18 1886 dep->name[0] = '/';
ff105f75 1887 libxfs_dir2_data_log_entry(&da, bp, dep);
6c39a3cb 1888 if (verbose)
507f4e33
NS
1889 do_warn(
1890 _("\twill clear entry \"%s\"\n"),
2bd0ea18
NS
1891 fname);
1892 } else {
507f4e33
NS
1893 do_warn(_("\twould clear entry \"%s\"\n"),
1894 fname);
2bd0ea18
NS
1895 }
1896 }
1897 }
1898 *num_illegal += nbad;
1899 if (needscan)
d85595d0 1900 libxfs_dir2_data_freescan(mp, d, &i);
2bd0ea18 1901 if (needlog)
ff105f75 1902 libxfs_dir2_data_log_header(&da, bp);
f2279d8d
DW
1903 error = -libxfs_trans_commit(tp);
1904 if (error)
1905 do_error(
1906_("directory block fixing failed (%d)\n"), error);
d2006f04
DC
1907
1908 /* record the largest free space in the freetab for later checking */
04f6f354 1909 bf = libxfs_dir2_data_bestfree_p(mp, d);
d2006f04 1910 freetab->ents[db].v = be16_to_cpu(bf[0].length);
2bd0ea18
NS
1911 freetab->ents[db].s = 0;
1912}
1913
0519f662
DW
1914/* check v5 metadata */
1915static int
1916__check_dir3_header(
1917 struct xfs_mount *mp,
1918 struct xfs_buf *bp,
1919 xfs_ino_t ino,
1920 __be64 owner,
1921 __be64 blkno,
1922 uuid_t *uuid)
1923{
1924
1925 /* verify owner */
1926 if (be64_to_cpu(owner) != ino) {
1927 do_warn(
1928_("expected owner inode %" PRIu64 ", got %llu, directory block %" PRIu64 "\n"),
f1208396 1929 ino, (unsigned long long)be64_to_cpu(owner), xfs_buf_daddr(bp));
0519f662
DW
1930 return 1;
1931 }
1932 /* verify block number */
f1208396 1933 if (be64_to_cpu(blkno) != xfs_buf_daddr(bp)) {
0519f662
DW
1934 do_warn(
1935_("expected block %" PRIu64 ", got %llu, directory inode %" PRIu64 "\n"),
f1208396 1936 xfs_buf_daddr(bp), (unsigned long long)be64_to_cpu(blkno), ino);
0519f662
DW
1937 return 1;
1938 }
1939 /* verify uuid */
f31982ae 1940 if (platform_uuid_compare(uuid, &mp->m_sb.sb_meta_uuid) != 0) {
0519f662
DW
1941 do_warn(
1942_("wrong FS UUID, directory inode %" PRIu64 " block %" PRIu64 "\n"),
f1208396 1943 ino, xfs_buf_daddr(bp));
0519f662
DW
1944 return 1;
1945 }
1946
1947 return 0;
1948}
1949
1950static int
1951check_da3_header(
1952 struct xfs_mount *mp,
1953 struct xfs_buf *bp,
1954 xfs_ino_t ino)
1955{
1956 struct xfs_da3_blkinfo *info = bp->b_addr;
1957
1958 return __check_dir3_header(mp, bp, ino, info->owner, info->blkno,
1959 &info->uuid);
1960}
1961
1962static int
1963check_dir3_header(
1964 struct xfs_mount *mp,
1965 struct xfs_buf *bp,
1966 xfs_ino_t ino)
1967{
1968 struct xfs_dir3_blk_hdr *info = bp->b_addr;
1969
1970 return __check_dir3_header(mp, bp, ino, info->owner, info->blkno,
1971 &info->uuid);
1972}
1973
2bd0ea18
NS
1974/*
1975 * Check contents of leaf-form block.
1976 */
2556c98b 1977static int
2bd0ea18 1978longform_dir2_check_leaf(
266b73fa
DC
1979 struct xfs_mount *mp,
1980 struct xfs_inode *ip,
1981 struct dir_hash_tab *hashtab,
1982 struct freetab *freetab)
2bd0ea18
NS
1983{
1984 int badtail;
5e656dbb 1985 __be16 *bestsp;
a2ceac1f 1986 struct xfs_buf *bp;
2bd0ea18
NS
1987 xfs_dablk_t da_bno;
1988 int i;
1989 xfs_dir2_leaf_t *leaf;
1990 xfs_dir2_leaf_tail_t *ltp;
1991 int seeval;
65b80c98 1992 struct xfs_dir2_leaf_entry *ents;
658ac3e3 1993 struct xfs_dir3_icleaf_hdr leafhdr;
8e7e14be
DC
1994 int error;
1995 int fixit = 0;
2bd0ea18 1996
ff105f75 1997 da_bno = mp->m_dir_geo->leafblk;
db8e6401 1998 error = dir_read_buf(ip, da_bno, &bp, &xfs_dir3_leaf1_buf_ops, &fixit);
ba1c6776
DW
1999 if (error == EFSBADCRC || error == EFSCORRUPTED || fixit) {
2000 do_warn(
2001 _("leaf block %u for directory inode %" PRIu64 " bad CRC\n"),
2002 da_bno, ip->i_ino);
2003 return 1;
2004 } else if (error) {
5d1b7f0f 2005 do_error(
8e7e14be
DC
2006 _("can't read block %u for directory inode %" PRIu64 ", error %d\n"),
2007 da_bno, ip->i_ino, error);
2bd0ea18
NS
2008 /* NOTREACHED */
2009 }
8e7e14be 2010
a2ceac1f 2011 leaf = bp->b_addr;
9db68faf 2012 libxfs_dir2_leaf_hdr_from_disk(mp, &leafhdr, leaf);
a2279497 2013 ents = leafhdr.ents;
ff105f75 2014 ltp = xfs_dir2_leaf_tail_p(mp->m_dir_geo, leaf);
5e656dbb 2015 bestsp = xfs_dir2_leaf_bests_p(ltp);
658ac3e3
DC
2016 if (!(leafhdr.magic == XFS_DIR2_LEAF1_MAGIC ||
2017 leafhdr.magic == XFS_DIR3_LEAF1_MAGIC) ||
2018 leafhdr.forw || leafhdr.back ||
5eb1ac90 2019 leafhdr.count < leafhdr.stale ||
d106a3e0 2020 leafhdr.count > mp->m_dir_geo->leaf_max_ents ||
658ac3e3 2021 (char *)&ents[leafhdr.count] > (char *)bestsp) {
507f4e33 2022 do_warn(
5d1b7f0f 2023 _("leaf block %u for directory inode %" PRIu64 " bad header\n"),
2bd0ea18 2024 da_bno, ip->i_ino);
e02ba985 2025 libxfs_buf_relse(bp);
2bd0ea18
NS
2026 return 1;
2027 }
0519f662
DW
2028
2029 if (leafhdr.magic == XFS_DIR3_LEAF1_MAGIC) {
2030 error = check_da3_header(mp, bp, ip->i_ino);
2031 if (error) {
e02ba985 2032 libxfs_buf_relse(bp);
0519f662
DW
2033 return error;
2034 }
2035 }
2036
658ac3e3 2037 seeval = dir_hash_see_all(hashtab, ents, leafhdr.count, leafhdr.stale);
2bd0ea18 2038 if (dir_hash_check(hashtab, ip, seeval)) {
e02ba985 2039 libxfs_buf_relse(bp);
2bd0ea18
NS
2040 return 1;
2041 }
5e656dbb
BN
2042 badtail = freetab->nents != be32_to_cpu(ltp->bestcount);
2043 for (i = 0; !badtail && i < be32_to_cpu(ltp->bestcount); i++) {
2bd0ea18 2044 freetab->ents[i].s = 1;
5e656dbb 2045 badtail = freetab->ents[i].v != be16_to_cpu(bestsp[i]);
2bd0ea18
NS
2046 }
2047 if (badtail) {
5d1b7f0f
CH
2048 do_warn(
2049 _("leaf block %u for directory inode %" PRIu64 " bad tail\n"),
2bd0ea18 2050 da_bno, ip->i_ino);
e02ba985 2051 libxfs_buf_relse(bp);
2bd0ea18
NS
2052 return 1;
2053 }
e02ba985 2054 libxfs_buf_relse(bp);
8e7e14be 2055 return fixit;
2bd0ea18
NS
2056}
2057
2058/*
2059 * Check contents of the node blocks (leaves)
2060 * Looks for matching hash values for the data entries.
2061 */
2556c98b 2062static int
2bd0ea18 2063longform_dir2_check_node(
266b73fa
DC
2064 struct xfs_mount *mp,
2065 struct xfs_inode *ip,
2066 struct dir_hash_tab *hashtab,
2067 struct freetab *freetab)
2bd0ea18 2068{
a2ceac1f 2069 struct xfs_buf *bp;
2bd0ea18
NS
2070 xfs_dablk_t da_bno;
2071 xfs_dir2_db_t fdb;
2072 xfs_dir2_free_t *free;
2073 int i;
2074 xfs_dir2_leaf_t *leaf;
2075 xfs_fileoff_t next_da_bno;
2076 int seeval = 0;
2077 int used;
65b80c98 2078 struct xfs_dir2_leaf_entry *ents;
658ac3e3
DC
2079 struct xfs_dir3_icleaf_hdr leafhdr;
2080 struct xfs_dir3_icfree_hdr freehdr;
2081 __be16 *bests;
8e7e14be
DC
2082 int error;
2083 int fixit = 0;
0f012a4c 2084
ff105f75
DC
2085 for (da_bno = mp->m_dir_geo->leafblk, next_da_bno = 0;
2086 next_da_bno != NULLFILEOFF && da_bno < mp->m_dir_geo->freeblk;
5e656dbb 2087 da_bno = (xfs_dablk_t)next_da_bno) {
ff105f75 2088 next_da_bno = da_bno + mp->m_dir_geo->fsbcount - 1;
f3a6a9f8 2089 if (bmap_next_offset(ip, &next_da_bno))
2bd0ea18 2090 break;
9b981421
DC
2091
2092 /*
2093 * we need to use the da3 node verifier here as it handles the
2094 * fact that reading the leaf hash tree blocks can return either
2095 * leaf or node blocks and calls the correct verifier. If we get
2096 * a node block, then we'll skip it below based on a magic
2097 * number check.
2098 */
db8e6401
DW
2099 error = dir_read_buf(ip, da_bno, &bp, &xfs_da3_node_buf_ops,
2100 &fixit);
8e7e14be 2101 if (error) {
33165ec3 2102 do_warn(
8e7e14be
DC
2103 _("can't read leaf block %u for directory inode %" PRIu64 ", error %d\n"),
2104 da_bno, ip->i_ino, error);
33165ec3 2105 return 1;
2bd0ea18 2106 }
a2ceac1f 2107 leaf = bp->b_addr;
9db68faf 2108 libxfs_dir2_leaf_hdr_from_disk(mp, &leafhdr, leaf);
a2279497 2109 ents = leafhdr.ents;
658ac3e3 2110 if (!(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC ||
0519f662
DW
2111 leafhdr.magic == XFS_DIR3_LEAFN_MAGIC ||
2112 leafhdr.magic == XFS_DA_NODE_MAGIC ||
2113 leafhdr.magic == XFS_DA3_NODE_MAGIC)) {
5d1b7f0f
CH
2114 do_warn(
2115 _("unknown magic number %#x for block %u in directory inode %" PRIu64 "\n"),
658ac3e3 2116 leafhdr.magic, da_bno, ip->i_ino);
e02ba985 2117 libxfs_buf_relse(bp);
2bd0ea18
NS
2118 return 1;
2119 }
8e7e14be 2120
0519f662
DW
2121 /* check v5 metadata */
2122 if (leafhdr.magic == XFS_DIR3_LEAFN_MAGIC ||
2123 leafhdr.magic == XFS_DA3_NODE_MAGIC) {
2124 error = check_da3_header(mp, bp, ip->i_ino);
2125 if (error) {
e02ba985 2126 libxfs_buf_relse(bp);
0519f662
DW
2127 return error;
2128 }
2129 }
2130
2131 /* ignore nodes */
2132 if (leafhdr.magic == XFS_DA_NODE_MAGIC ||
2133 leafhdr.magic == XFS_DA3_NODE_MAGIC) {
e02ba985 2134 libxfs_buf_relse(bp);
0519f662
DW
2135 continue;
2136 }
2137
8e7e14be
DC
2138 /*
2139 * If there's a validator error, we need to ensure that we got
2140 * the right ops on the buffer for when we write it back out.
2141 */
2142 bp->b_ops = &xfs_dir3_leafn_buf_ops;
d106a3e0 2143 if (leafhdr.count > mp->m_dir_geo->leaf_max_ents ||
658ac3e3 2144 leafhdr.count < leafhdr.stale) {
5d1b7f0f
CH
2145 do_warn(
2146 _("leaf block %u for directory inode %" PRIu64 " bad header\n"),
2bd0ea18 2147 da_bno, ip->i_ino);
e02ba985 2148 libxfs_buf_relse(bp);
2bd0ea18
NS
2149 return 1;
2150 }
65b80c98 2151 seeval = dir_hash_see_all(hashtab, ents,
658ac3e3 2152 leafhdr.count, leafhdr.stale);
e02ba985 2153 libxfs_buf_relse(bp);
0f012a4c 2154 if (seeval != DIR_HASH_CK_OK)
2bd0ea18
NS
2155 return 1;
2156 }
0f012a4c 2157 if (dir_hash_check(hashtab, ip, seeval))
2bd0ea18 2158 return 1;
0f012a4c 2159
ff105f75 2160 for (da_bno = mp->m_dir_geo->freeblk, next_da_bno = 0;
2bd0ea18
NS
2161 next_da_bno != NULLFILEOFF;
2162 da_bno = (xfs_dablk_t)next_da_bno) {
ff105f75 2163 next_da_bno = da_bno + mp->m_dir_geo->fsbcount - 1;
f3a6a9f8 2164 if (bmap_next_offset(ip, &next_da_bno))
2bd0ea18 2165 break;
8e7e14be 2166
db8e6401
DW
2167 error = dir_read_buf(ip, da_bno, &bp, &xfs_dir3_free_buf_ops,
2168 &fixit);
8e7e14be 2169 if (error) {
33165ec3 2170 do_warn(
8e7e14be
DC
2171 _("can't read freespace block %u for directory inode %" PRIu64 ", error %d\n"),
2172 da_bno, ip->i_ino, error);
33165ec3 2173 return 1;
2bd0ea18 2174 }
a2ceac1f 2175 free = bp->b_addr;
61e2142e 2176 libxfs_dir2_free_hdr_from_disk(mp, &freehdr, free);
cb5d1930 2177 bests = freehdr.bests;
ff105f75 2178 fdb = xfs_dir2_da_to_db(mp->m_dir_geo, da_bno);
658ac3e3
DC
2179 if (!(freehdr.magic == XFS_DIR2_FREE_MAGIC ||
2180 freehdr.magic == XFS_DIR3_FREE_MAGIC) ||
ff105f75
DC
2181 freehdr.firstdb !=
2182 (fdb - xfs_dir2_byte_to_db(mp->m_dir_geo, XFS_DIR2_FREE_OFFSET)) *
ae3cd5b1 2183 mp->m_dir_geo->free_max_bests ||
ff105f75 2184 freehdr.nvalid < freehdr.nused) {
5d1b7f0f
CH
2185 do_warn(
2186 _("free block %u for directory inode %" PRIu64 " bad header\n"),
2bd0ea18 2187 da_bno, ip->i_ino);
e02ba985 2188 libxfs_buf_relse(bp);
2bd0ea18
NS
2189 return 1;
2190 }
0519f662
DW
2191
2192 if (freehdr.magic == XFS_DIR3_FREE_MAGIC) {
2193 error = check_dir3_header(mp, bp, ip->i_ino);
2194 if (error) {
e02ba985 2195 libxfs_buf_relse(bp);
0519f662
DW
2196 return error;
2197 }
2198 }
658ac3e3
DC
2199 for (i = used = 0; i < freehdr.nvalid; i++) {
2200 if (i + freehdr.firstdb >= freetab->nents ||
2201 freetab->ents[i + freehdr.firstdb].v !=
2202 be16_to_cpu(bests[i])) {
507f4e33 2203 do_warn(
5d1b7f0f 2204 _("free block %u entry %i for directory ino %" PRIu64 " bad\n"),
2bd0ea18 2205 da_bno, i, ip->i_ino);
e02ba985 2206 libxfs_buf_relse(bp);
2bd0ea18
NS
2207 return 1;
2208 }
658ac3e3
DC
2209 used += be16_to_cpu(bests[i]) != NULLDATAOFF;
2210 freetab->ents[i + freehdr.firstdb].s = 1;
2bd0ea18 2211 }
658ac3e3 2212 if (used != freehdr.nused) {
5d1b7f0f
CH
2213 do_warn(
2214 _("free block %u for directory inode %" PRIu64 " bad nused\n"),
2bd0ea18 2215 da_bno, ip->i_ino);
e02ba985 2216 libxfs_buf_relse(bp);
2bd0ea18
NS
2217 return 1;
2218 }
e02ba985 2219 libxfs_buf_relse(bp);
2bd0ea18
NS
2220 }
2221 for (i = 0; i < freetab->nents; i++) {
4b6a2d8e
NS
2222 if ((freetab->ents[i].s == 0) &&
2223 (freetab->ents[i].v != NULLDATAOFF)) {
5d1b7f0f
CH
2224 do_warn(
2225 _("missing freetab entry %u for directory inode %" PRIu64 "\n"),
2bd0ea18
NS
2226 i, ip->i_ino);
2227 return 1;
2228 }
2229 }
8e7e14be 2230 return fixit;
2bd0ea18
NS
2231}
2232
2233/*
33165ec3
BN
2234 * If a directory is corrupt, we need to read in as many entries as possible,
2235 * destroy the entry and create a new one with recovered name/inode pairs.
2236 * (ie. get libxfs to do all the grunt work)
2bd0ea18 2237 */
2556c98b 2238static void
266b73fa
DC
2239longform_dir2_entry_check(
2240 struct xfs_mount *mp,
2241 xfs_ino_t ino,
2242 struct xfs_inode *ip,
2243 int *num_illegal,
2244 int *need_dot,
2245 struct ino_tree_node *irec,
2246 int ino_offset,
2247 struct dir_hash_tab *hashtab)
2bd0ea18 2248{
da7f6039 2249 struct xfs_buf *bp = NULL;
2bd0ea18
NS
2250 xfs_dablk_t da_bno;
2251 freetab_t *freetab;
2bd0ea18 2252 int i;
1a3bfffe
SZ
2253 bool isblock;
2254 bool isleaf;
2bd0ea18
NS
2255 xfs_fileoff_t next_da_bno;
2256 int seeval;
b5fa9e86 2257 int fixit = 0;
ff105f75 2258 struct xfs_da_args args;
2bd0ea18
NS
2259
2260 *need_dot = 1;
509dcb4b 2261 freetab = malloc(FREETAB_SIZE(ip->i_disk_size / mp->m_dir_geo->blksize));
2bd0ea18 2262 if (!freetab) {
15e3986b
DC
2263 do_error(_("malloc failed in %s (%" PRId64 " bytes)\n"),
2264 __func__,
509dcb4b 2265 FREETAB_SIZE(ip->i_disk_size / mp->m_dir_geo->blksize));
2bd0ea18
NS
2266 exit(1);
2267 }
509dcb4b 2268 freetab->naents = ip->i_disk_size / mp->m_dir_geo->blksize;
2bd0ea18
NS
2269 freetab->nents = 0;
2270 for (i = 0; i < freetab->naents; i++) {
2271 freetab->ents[i].v = NULLDATAOFF;
2272 freetab->ents[i].s = 0;
2273 }
15e3986b 2274
9d7d6241 2275 /* is this a block, leaf, or node directory? */
ff105f75
DC
2276 args.dp = ip;
2277 args.geo = mp->m_dir_geo;
2278 libxfs_dir2_isblock(&args, &isblock);
2279 libxfs_dir2_isleaf(&args, &isleaf);
9d7d6241 2280
33165ec3 2281 /* check directory "data" blocks (ie. name/inode pairs) */
2bd0ea18 2282 for (da_bno = 0, next_da_bno = 0;
ff105f75 2283 next_da_bno != NULLFILEOFF && da_bno < mp->m_dir_geo->leafblk;
2bd0ea18 2284 da_bno = (xfs_dablk_t)next_da_bno) {
b5fa9e86 2285 const struct xfs_buf_ops *ops;
8e7e14be 2286 int error;
0519f662 2287 struct xfs_dir2_data_hdr *d;
b5fa9e86 2288
ff105f75 2289 next_da_bno = da_bno + mp->m_dir_geo->fsbcount - 1;
f3a6a9f8 2290 if (bmap_next_offset(ip, &next_da_bno)) {
15e3986b
DC
2291 /*
2292 * if this is the first block, there isn't anything we
2293 * can recover so we just trash it.
2294 */
2295 if (da_bno == 0) {
2296 fixit++;
2297 goto out_fix;
2298 }
2bd0ea18 2299 break;
15e3986b
DC
2300 }
2301
b5fa9e86
DC
2302 if (isblock)
2303 ops = &xfs_dir3_block_buf_ops;
2304 else
2305 ops = &xfs_dir3_data_buf_ops;
8e7e14be 2306
1f7c7553 2307 error = dir_read_buf(ip, da_bno, &bp, ops, &fixit);
8e7e14be 2308 if (error) {
5d1b7f0f 2309 do_warn(
8e7e14be
DC
2310 _("can't read data block %u for directory inode %" PRIu64 " error %d\n"),
2311 da_bno, ino, error);
95dff16b 2312 *num_illegal += 1;
b5fa9e86
DC
2313
2314 /*
2315 * we try to read all "data" blocks, but if we are in
2316 * block form and we fail, there isn't anything else to
2317 * read, and nothing we can do but trash it.
2318 */
2319 if (isblock) {
2320 fixit++;
2321 goto out_fix;
2322 }
2323 continue;
2bd0ea18 2324 }
0519f662
DW
2325
2326 /* check v5 metadata */
1f7c7553 2327 d = bp->b_addr;
0519f662
DW
2328 if (be32_to_cpu(d->magic) == XFS_DIR3_BLOCK_MAGIC ||
2329 be32_to_cpu(d->magic) == XFS_DIR3_DATA_MAGIC) {
0519f662
DW
2330 error = check_dir3_header(mp, bp, ino);
2331 if (error) {
2332 fixit++;
1f7c7553
DC
2333 if (isblock)
2334 goto out_fix;
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);
2bd0ea18 2346 }
8e7e14be 2347 fixit |= (*num_illegal != 0) || dir2_is_badino(ino) || *need_dot;
9d7d6241 2348
575ca697
BN
2349 if (!dotdot_update) {
2350 /* check btree and freespace */
2351 if (isblock) {
a354abc8 2352 struct xfs_dir2_data_hdr *block;
575ca697
BN
2353 xfs_dir2_block_tail_t *btp;
2354 xfs_dir2_leaf_entry_t *blp;
2355
1f7c7553 2356 block = bp->b_addr;
ff105f75 2357 btp = xfs_dir2_block_tail_p(mp->m_dir_geo, block);
5e656dbb 2358 blp = xfs_dir2_block_leaf_p(btp);
575ca697
BN
2359 seeval = dir_hash_see_all(hashtab, blp,
2360 be32_to_cpu(btp->count),
2361 be32_to_cpu(btp->stale));
2362 if (dir_hash_check(hashtab, ip, seeval))
2363 fixit |= 1;
2364 } else if (isleaf) {
2365 fixit |= longform_dir2_check_leaf(mp, ip, hashtab,
2366 freetab);
2367 } else {
2368 fixit |= longform_dir2_check_node(mp, ip, hashtab,
2369 freetab);
2370 }
2bd0ea18 2371 }
b5fa9e86 2372out_fix:
1f7c7553
DC
2373 if (isblock && bp)
2374 libxfs_buf_relse(bp);
2375
575ca697 2376 if (!no_modify && (fixit || dotdot_update)) {
6fa00c33 2377 longform_dir2_rebuild(mp, ino, ip, irec, ino_offset, hashtab);
33165ec3 2378 *num_illegal = 0;
6fa00c33 2379 *need_dot = 0;
33165ec3 2380 } else {
41f8fc57
DW
2381 if (fixit || dotdot_update)
2382 do_warn(
2383 _("would rebuild directory inode %" PRIu64 "\n"), ino);
33165ec3 2384 }
0f012a4c 2385
2bd0ea18
NS
2386 free(freetab);
2387}
2388
2bd0ea18
NS
2389/*
2390 * shortform directory v2 processing routines -- entry verification and
2391 * bad entry deletion (pruning).
2392 */
aaca101b
DC
2393static struct xfs_dir2_sf_entry *
2394shortform_dir2_junk(
2395 struct xfs_mount *mp,
2396 struct xfs_dir2_sf_hdr *sfp,
2397 struct xfs_dir2_sf_entry *sfep,
2398 xfs_ino_t lino,
2399 int *max_size,
2400 int *index,
2401 int *bytes_deleted,
2402 int *ino_dirty)
2403{
2404 struct xfs_dir2_sf_entry *next_sfep;
2405 int next_len;
2406 int next_elen;
2407
2408 if (lino == orphanage_ino)
2409 orphanage_ino = 0;
2410
660836c9
CH
2411 next_elen = libxfs_dir2_sf_entsize(mp, sfp, sfep->namelen);
2412 next_sfep = libxfs_dir2_sf_nextentry(mp, sfp, sfep);
aaca101b
DC
2413
2414 /*
2415 * if we are just checking, simply return the pointer to the next entry
2416 * here so that the checking loop can continue.
2417 */
2418 if (no_modify) {
2419 do_warn(_("would junk entry\n"));
2420 return next_sfep;
2421 }
2422
2423 /*
2424 * now move all the remaining entries down over the junked entry and
2425 * clear the newly unused bytes at the tail of the directory region.
2426 */
ee6cd73e 2427 next_len = *max_size - ((intptr_t)next_sfep - (intptr_t)sfp);
aaca101b
DC
2428 *max_size -= next_elen;
2429 *bytes_deleted += next_elen;
2430
2431 memmove(sfep, next_sfep, next_len);
ee6cd73e 2432 memset((void *)((intptr_t)sfep + next_len), 0, next_elen);
aaca101b
DC
2433 sfp->count -= 1;
2434 *ino_dirty = 1;
2435
2436 /*
2437 * WARNING: drop the index i by one so it matches the decremented count
2438 * for accurate comparisons in the loop test
2439 */
2440 (*index)--;
2441
2442 if (verbose)
2443 do_warn(_("junking entry\n"));
2444 else
2445 do_warn("\n");
2446 return sfep;
2447}
2448
2556c98b 2449static void
266b73fa
DC
2450shortform_dir2_entry_check(
2451 struct xfs_mount *mp,
2452 xfs_ino_t ino,
2453 struct xfs_inode *ip,
2454 int *ino_dirty,
2455 struct ino_tree_node *current_irec,
2456 int current_ino_offset,
2457 struct dir_hash_tab *hashtab)
2bd0ea18
NS
2458{
2459 xfs_ino_t lino;
2460 xfs_ino_t parent;
a354abc8 2461 struct xfs_dir2_sf_hdr *sfp;
aaca101b
DC
2462 struct xfs_dir2_sf_entry *sfep;
2463 struct xfs_dir2_sf_entry *next_sfep;
2464 struct xfs_ifork *ifp;
2465 struct ino_tree_node *irec;
2bd0ea18
NS
2466 int max_size;
2467 int ino_offset;
2468 int i;
2bd0ea18
NS
2469 int bad_sfnamelen;
2470 int namelen;
2471 int bytes_deleted;
2472 char fname[MAXNAMELEN + 1];
2473 int i8;
2474
2475 ifp = &ip->i_df;
a354abc8 2476 sfp = (struct xfs_dir2_sf_hdr *) ifp->if_u1.if_data;
2bd0ea18 2477 *ino_dirty = 0;
e55d768a 2478 bytes_deleted = 0;
2bd0ea18
NS
2479
2480 max_size = ifp->if_bytes;
509dcb4b 2481 ASSERT(ip->i_disk_size <= ifp->if_bytes);
2bd0ea18 2482
575ca697
BN
2483 /*
2484 * if just rebuild a directory due to a "..", update and return
2485 */
2486 if (dotdot_update) {
2487 parent = get_inode_parent(current_irec, current_ino_offset);
2488 if (no_modify) {
5d1b7f0f
CH
2489 do_warn(
2490 _("would set .. in sf dir inode %" PRIu64 " to %" PRIu64 "\n"),
575ca697
BN
2491 ino, parent);
2492 } else {
5d1b7f0f
CH
2493 do_warn(
2494 _("setting .. in sf dir inode %" PRIu64 " to %" PRIu64 "\n"),
575ca697 2495 ino, parent);
8a7190bd 2496 libxfs_dir2_sf_put_parent_ino(sfp, parent);
575ca697
BN
2497 *ino_dirty = 1;
2498 }
2499 return;
2500 }
2501
2bd0ea18
NS
2502 /*
2503 * no '.' entry in shortform dirs, just bump up ref count by 1
2504 * '..' was already (or will be) accounted for and checked when
2505 * the directory is reached or will be taken care of when the
2506 * directory is moved to orphanage.
2507 */
2508 add_inode_ref(current_irec, current_ino_offset);
2509
e55d768a
NS
2510 /*
2511 * Initialise i8 counter -- the parent inode number counts as well.
2512 */
8a7190bd 2513 i8 = libxfs_dir2_sf_get_parent_ino(sfp) > XFS_DIR2_MAX_SHORT_INUM;
e55d768a 2514
2bd0ea18
NS
2515 /*
2516 * now run through entries, stop at first bad entry, don't need
2517 * to skip over '..' since that's encoded in its own field and
2518 * no need to worry about '.' since it doesn't exist.
2519 */
a354abc8 2520 sfep = next_sfep = xfs_dir2_sf_firstentry(sfp);
2bd0ea18 2521
a354abc8 2522 for (i = 0; i < sfp->count && max_size >
ee6cd73e 2523 (intptr_t)next_sfep - (intptr_t)sfp;
2bd0ea18 2524 sfep = next_sfep, i++) {
2bd0ea18 2525 bad_sfnamelen = 0;
2bd0ea18 2526
e96bd2d3 2527 lino = libxfs_dir2_sf_get_ino(mp, sfp, sfep);
2bd0ea18
NS
2528
2529 namelen = sfep->namelen;
2530
2531 ASSERT(no_modify || namelen > 0);
2532
2533 if (no_modify && namelen == 0) {
2534 /*
2535 * if we're really lucky, this is
2536 * the last entry in which case we
2537 * can use the dir size to set the
2538 * namelen value. otherwise, forget
2539 * it because we're not going to be
2540 * able to find the next entry.
2541 */
2542 bad_sfnamelen = 1;
2543
a354abc8 2544 if (i == sfp->count - 1) {
509dcb4b 2545 namelen = ip->i_disk_size -
ee6cd73e
CH
2546 ((intptr_t) &sfep->name[0] -
2547 (intptr_t) sfp);
2bd0ea18
NS
2548 } else {
2549 /*
2550 * don't process the rest of the directory,
2551 * break out of processing loop
2552 */
2553 break;
2554 }
ee6cd73e 2555 } else if (no_modify && (intptr_t) sfep - (intptr_t) sfp +
660836c9 2556 + libxfs_dir2_sf_entsize(mp, sfp, sfep->namelen)
509dcb4b 2557 > ip->i_disk_size) {
2bd0ea18
NS
2558 bad_sfnamelen = 1;
2559
a354abc8 2560 if (i == sfp->count - 1) {
509dcb4b 2561 namelen = ip->i_disk_size -
ee6cd73e
CH
2562 ((intptr_t) &sfep->name[0] -
2563 (intptr_t) sfp);
2bd0ea18
NS
2564 } else {
2565 /*
2566 * don't process the rest of the directory,
2567 * break out of processing loop
2568 */
2569 break;
2570 }
2571 }
2572
dab9b8d6 2573 memmove(fname, sfep->name, sfep->namelen);
2bd0ea18
NS
2574 fname[sfep->namelen] = '\0';
2575
2576 ASSERT(no_modify || (lino != NULLFSINO && lino != 0));
017e979e 2577 ASSERT(no_modify || libxfs_verify_dir_ino(mp, lino));
2bd0ea18 2578
e55d768a
NS
2579 /*
2580 * Also skip entries with bogus inode numbers if we're
2581 * in no modify mode.
2582 */
2583
017e979e 2584 if (no_modify && !libxfs_verify_dir_ino(mp, lino)) {
660836c9 2585 next_sfep = libxfs_dir2_sf_nextentry(mp, sfp, sfep);
2bd0ea18
NS
2586 continue;
2587 }
2588
1ae311d5 2589 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, lino),
2bd0ea18
NS
2590 XFS_INO_TO_AGINO(mp, lino));
2591
6c39a3cb 2592 if (irec == NULL) {
5d1b7f0f
CH
2593 do_warn(
2594 _("entry \"%s\" in shortform directory %" PRIu64 " references non-existent inode %" PRIu64 "\n"),
2bd0ea18 2595 fname, ino, lino);
aaca101b
DC
2596 next_sfep = shortform_dir2_junk(mp, sfp, sfep, lino,
2597 &max_size, &i, &bytes_deleted,
2598 ino_dirty);
2599 continue;
2bd0ea18
NS
2600 }
2601
2bd0ea18
NS
2602 ino_offset = XFS_INO_TO_AGINO(mp, lino) - irec->ino_startnum;
2603
2604 /*
2605 * if it's a free inode, blow out the entry.
2606 * by now, any inode that we think is free
2607 * really is free.
2608 */
2609 if (is_inode_free(irec, ino_offset)) {
5d1b7f0f
CH
2610 do_warn(
2611 _("entry \"%s\" in shortform directory inode %" PRIu64 " points to free inode %" PRIu64 "\n"),
6c39a3cb 2612 fname, ino, lino);
aaca101b
DC
2613 next_sfep = shortform_dir2_junk(mp, sfp, sfep, lino,
2614 &max_size, &i, &bytes_deleted,
2615 ino_dirty);
2616 continue;
6c39a3cb
BN
2617 }
2618 /*
2619 * check if this inode is lost+found dir in the root
2620 */
2621 if (ino == mp->m_sb.sb_rootino && strcmp(fname, ORPHANAGE) == 0) {
2bd0ea18 2622 /*
6c39a3cb 2623 * if it's not a directory, trash it
2bd0ea18 2624 */
6c39a3cb 2625 if (!inode_isadir(irec, ino_offset)) {
5d1b7f0f
CH
2626 do_warn(
2627 _("%s (ino %" PRIu64 ") in root (%" PRIu64 ") is not a directory"),
2628 ORPHANAGE, lino, ino);
aaca101b
DC
2629 next_sfep = shortform_dir2_junk(mp, sfp, sfep,
2630 lino, &max_size, &i,
2631 &bytes_deleted, ino_dirty);
2632 continue;
2bd0ea18 2633 }
64c54486 2634 /*
6c39a3cb
BN
2635 * if this is a dup, it will be picked up below,
2636 * otherwise, mark it as the orphanage for later.
0f012a4c 2637 */
6c39a3cb
BN
2638 if (!orphanage_ino)
2639 orphanage_ino = lino;
2640 }
2641 /*
2642 * check for duplicate names in directory.
2643 */
51ca7008 2644 if (!dir_hash_add(mp, hashtab, (xfs_dir2_dataptr_t)
a354abc8 2645 (sfep - xfs_dir2_sf_firstentry(sfp)),
aaca101b 2646 lino, sfep->namelen, sfep->name,
d49d4ff5 2647 libxfs_dir2_sf_get_ftype(mp, sfep))) {
5d1b7f0f
CH
2648 do_warn(
2649_("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"),
2650 fname, lino, ino);
aaca101b
DC
2651 next_sfep = shortform_dir2_junk(mp, sfp, sfep, lino,
2652 &max_size, &i, &bytes_deleted,
2653 ino_dirty);
2654 continue;
6c39a3cb 2655 }
575ca697 2656
6c39a3cb 2657 if (!inode_isadir(irec, ino_offset)) {
2bd0ea18
NS
2658 /*
2659 * check easy case first, regular inode, just bump
e55d768a 2660 * the link count
2bd0ea18
NS
2661 */
2662 add_inode_reached(irec, ino_offset);
2bd0ea18
NS
2663 } else {
2664 parent = get_inode_parent(irec, ino_offset);
2665
2666 /*
2667 * bump up the link counts in parent and child.
2668 * directory but if the link doesn't agree with
2669 * the .. in the child, blow out the entry
2670 */
2671 if (is_inode_reached(irec, ino_offset)) {
5d1b7f0f
CH
2672 do_warn(
2673 _("entry \"%s\" in directory inode %" PRIu64
2674 " references already connected inode %" PRIu64 ".\n"),
2bd0ea18 2675 fname, ino, lino);
aaca101b
DC
2676 next_sfep = shortform_dir2_junk(mp, sfp, sfep,
2677 lino, &max_size, &i,
2678 &bytes_deleted, ino_dirty);
2679 continue;
2bd0ea18
NS
2680 } else if (parent == ino) {
2681 add_inode_reached(irec, ino_offset);
2682 add_inode_ref(current_irec, current_ino_offset);
6fa00c33
BN
2683 } else if (parent == NULLFSINO) {
2684 /* ".." was missing, but this entry refers to it,
2685 so, set it as the parent and mark for rebuild */
5d1b7f0f
CH
2686 do_warn(
2687 _("entry \"%s\" in dir ino %" PRIu64 " doesn't have a .. entry, will set it in ino %" PRIu64 ".\n"),
6fa00c33
BN
2688 fname, ino, lino);
2689 set_inode_parent(irec, ino_offset, ino);
2690 add_inode_reached(irec, ino_offset);
2691 add_inode_ref(current_irec, current_ino_offset);
575ca697
BN
2692 add_dotdot_update(XFS_INO_TO_AGNO(mp, lino),
2693 irec, ino_offset);
2bd0ea18 2694 } else {
5d1b7f0f
CH
2695 do_warn(
2696 _("entry \"%s\" in directory inode %" PRIu64
2697 " not consistent with .. value (%" PRIu64
2698 ") in inode %" PRIu64 ",\n"),
2bd0ea18 2699 fname, ino, parent, lino);
aaca101b
DC
2700 next_sfep = shortform_dir2_junk(mp, sfp, sfep,
2701 lino, &max_size, &i,
2702 &bytes_deleted, ino_dirty);
2703 continue;
2bd0ea18
NS
2704 }
2705 }
2706
aaca101b 2707 /* validate ftype field if supported */
2660e653 2708 if (xfs_has_ftype(mp)) {
14f8b681
DW
2709 uint8_t dir_ftype;
2710 uint8_t ino_ftype;
2bd0ea18 2711
d49d4ff5 2712 dir_ftype = libxfs_dir2_sf_get_ftype(mp, sfep);
aaca101b 2713 ino_ftype = get_inode_ftype(irec, ino_offset);
2bd0ea18 2714
aaca101b
DC
2715 if (dir_ftype != ino_ftype) {
2716 if (no_modify) {
2717 do_warn(
2718 _("would fix ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"),
2719 dir_ftype, ino_ftype,
2720 ino, lino);
2721 } else {
2722 do_warn(
2723 _("fixing ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"),
2724 dir_ftype, ino_ftype,
2725 ino, lino);
d49d4ff5 2726 libxfs_dir2_sf_put_ftype(mp, sfep,
aaca101b
DC
2727 ino_ftype);
2728 dir_hash_update_ftype(hashtab,
2729 (xfs_dir2_dataptr_t)(sfep - xfs_dir2_sf_firstentry(sfp)),
2730 ino_ftype);
2731 *ino_dirty = 1;
2732 }
2bd0ea18 2733 }
aaca101b
DC
2734 }
2735
2736 if (lino > XFS_DIR2_MAX_SHORT_INUM)
2bd0ea18
NS
2737 i8++;
2738
2739 /*
aaca101b
DC
2740 * go onto next entry - we have to take entries with bad namelen
2741 * into account in no modify mode since we calculate size based
2742 * on next_sfep.
2bd0ea18
NS
2743 */
2744 ASSERT(no_modify || bad_sfnamelen == 0);
ee6cd73e 2745 next_sfep = (struct xfs_dir2_sf_entry *)((intptr_t)sfep +
aaca101b 2746 (bad_sfnamelen
660836c9
CH
2747 ? libxfs_dir2_sf_entsize(mp, sfp, namelen)
2748 : libxfs_dir2_sf_entsize(mp, sfp, sfep->namelen)));
2bd0ea18
NS
2749 }
2750
a354abc8 2751 if (sfp->i8count != i8) {
2bd0ea18 2752 if (no_modify) {
5d1b7f0f
CH
2753 do_warn(_("would fix i8count in inode %" PRIu64 "\n"),
2754 ino);
2bd0ea18
NS
2755 } else {
2756 if (i8 == 0) {
aaca101b
DC
2757 struct xfs_dir2_sf_entry *tmp_sfep;
2758
2bd0ea18 2759 tmp_sfep = next_sfep;
494434d7 2760 process_sf_dir2_fixi8(mp, sfp, &tmp_sfep);
2bd0ea18 2761 bytes_deleted +=
ee6cd73e
CH
2762 (intptr_t)next_sfep -
2763 (intptr_t)tmp_sfep;
2bd0ea18
NS
2764 next_sfep = tmp_sfep;
2765 } else
a354abc8 2766 sfp->i8count = i8;
2bd0ea18 2767 *ino_dirty = 1;
5d1b7f0f
CH
2768 do_warn(_("fixing i8count in inode %" PRIu64 "\n"),
2769 ino);
2bd0ea18
NS
2770 }
2771 }
2772
2773 /*
2774 * sync up sizes if required
2775 */
aaca101b 2776 if (*ino_dirty && bytes_deleted > 0) {
2bd0ea18
NS
2777 ASSERT(!no_modify);
2778 libxfs_idata_realloc(ip, -bytes_deleted, XFS_DATA_FORK);
509dcb4b 2779 ip->i_disk_size -= bytes_deleted;
2bd0ea18
NS
2780 }
2781
509dcb4b 2782 if (ip->i_disk_size != ip->i_df.if_bytes) {
2bd0ea18 2783 ASSERT(ip->i_df.if_bytes == (xfs_fsize_t)
ee6cd73e 2784 ((intptr_t) next_sfep - (intptr_t) sfp));
509dcb4b 2785 ip->i_disk_size = (xfs_fsize_t)
ee6cd73e 2786 ((intptr_t) next_sfep - (intptr_t) sfp);
5d1b7f0f
CH
2787 do_warn(
2788 _("setting size to %" PRId64 " bytes to reflect junked entries\n"),
509dcb4b 2789 ip->i_disk_size);
2bd0ea18
NS
2790 *ino_dirty = 1;
2791 }
2792}
2793
2794/*
2556c98b 2795 * processes all reachable inodes in directories
2bd0ea18 2796 */
2556c98b
BN
2797static void
2798process_dir_inode(
266b73fa 2799 struct xfs_mount *mp,
575ca697 2800 xfs_agnumber_t agno,
266b73fa 2801 struct ino_tree_node *irec,
2556c98b 2802 int ino_offset)
2bd0ea18 2803{
575ca697 2804 xfs_ino_t ino;
266b73fa
DC
2805 struct xfs_inode *ip;
2806 struct xfs_trans *tp;
2807 struct dir_hash_tab *hashtab;
0b66d459 2808 int need_dot;
2bd0ea18
NS
2809 int dirty, num_illegal, error, nres;
2810
575ca697
BN
2811 ino = XFS_AGINO_TO_INO(mp, agno, irec->ino_startnum + ino_offset);
2812
2bd0ea18 2813 /*
2bd0ea18
NS
2814 * open up directory inode, check all entries,
2815 * then call prune_dir_entries to remove all
2816 * remaining illegal directory entries.
2817 */
2818
f4ef1178 2819 ASSERT(!is_inode_refchecked(irec, ino_offset) || dotdot_update);
2bd0ea18 2820
1fecabf9 2821 error = -libxfs_iget(mp, NULL, ino, 0, &ip);
2556c98b
BN
2822 if (error) {
2823 if (!no_modify)
5d1b7f0f
CH
2824 do_error(
2825 _("couldn't map inode %" PRIu64 ", err = %d\n"),
2556c98b
BN
2826 ino, error);
2827 else {
5d1b7f0f
CH
2828 do_warn(
2829 _("couldn't map inode %" PRIu64 ", err = %d\n"),
2556c98b 2830 ino, error);
2bd0ea18 2831 /*
2556c98b
BN
2832 * see below for what we're doing if this
2833 * is root. Why do we need to do this here?
2834 * to ensure that the root doesn't show up
2835 * as being disconnected in the no_modify case.
2bd0ea18 2836 */
2556c98b
BN
2837 if (mp->m_sb.sb_rootino == ino) {
2838 add_inode_reached(irec, 0);
2839 add_inode_ref(irec, 0);
2840 }
2bd0ea18
NS
2841 }
2842
f4ef1178 2843 add_inode_refchecked(irec, 0);
2556c98b
BN
2844 return;
2845 }
2bd0ea18 2846
2556c98b 2847 need_dot = dirty = num_illegal = 0;
64c54486 2848
2556c98b 2849 if (mp->m_sb.sb_rootino == ino) {
2bd0ea18 2850 /*
2556c98b
BN
2851 * mark root inode reached and bump up
2852 * link count for root inode to account
2853 * for '..' entry since the root inode is
2854 * never reached by a parent. we know
2855 * that root's '..' is always good --
2856 * guaranteed by phase 3 and/or below.
2bd0ea18 2857 */
2556c98b
BN
2858 add_inode_reached(irec, ino_offset);
2859 }
2860
f4ef1178 2861 add_inode_refchecked(irec, ino_offset);
2556c98b 2862
509dcb4b 2863 hashtab = dir_hash_init(ip->i_disk_size);
2556c98b
BN
2864
2865 /*
2866 * look for bogus entries
2867 */
d967a68d 2868 switch (ip->i_df.if_format) {
2bd0ea18
NS
2869 case XFS_DINODE_FMT_EXTENTS:
2870 case XFS_DINODE_FMT_BTREE:
2871 /*
2872 * also check for missing '.' in longform dirs.
2873 * missing .. entries are added if required when
2874 * the directory is connected to lost+found. but
2875 * we need to create '.' entries here.
2876 */
9a048535
DC
2877 longform_dir2_entry_check(mp, ino, ip,
2878 &num_illegal, &need_dot,
2879 irec, ino_offset,
2880 hashtab);
2bd0ea18 2881 break;
2556c98b 2882
2bd0ea18 2883 case XFS_DINODE_FMT_LOCAL:
2bd0ea18
NS
2884 /*
2885 * using the remove reservation is overkill
2886 * since at most we'll only need to log the
2887 * inode but it's easier than wedging a
2888 * new define in ourselves.
2889 */
2890 nres = no_modify ? 0 : XFS_REMOVE_SPACE_RES(mp);
9074815c
CH
2891 error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove,
2892 nres, 0, 0, &tp);
2bd0ea18
NS
2893 if (error)
2894 res_failed(error);
2895
2896 libxfs_trans_ijoin(tp, ip, 0);
2bd0ea18 2897
9a048535
DC
2898 shortform_dir2_entry_check(mp, ino, ip, &dirty,
2899 irec, ino_offset,
2900 hashtab);
2bd0ea18 2901
27527004 2902 ASSERT(dirty == 0 || (dirty && !no_modify));
2bd0ea18
NS
2903 if (dirty) {
2904 libxfs_trans_log_inode(tp, ip,
2905 XFS_ILOG_CORE | XFS_ILOG_DDATA);
f2279d8d
DW
2906 error = -libxfs_trans_commit(tp);
2907 if (error)
af06261f
DW
2908 do_error(
2909_("error %d fixing shortform directory %llu\n"),
2910 error,
2911 (unsigned long long)ip->i_ino);
2bd0ea18 2912 } else {
3d7434fe 2913 libxfs_trans_cancel(tp);
2bd0ea18
NS
2914 }
2915 break;
2556c98b 2916
2bd0ea18
NS
2917 default:
2918 break;
2556c98b
BN
2919 }
2920 dir_hash_done(hashtab);
2bd0ea18 2921
2556c98b
BN
2922 /*
2923 * if we have to create a .. for /, do it now *before*
2924 * we delete the bogus entries, otherwise the directory
2925 * could transform into a shortform dir which would
2926 * probably cause the simulation to choke. Even
2927 * if the illegal entries get shifted around, it's ok
2928 * because the entries are structurally intact and in
2929 * in hash-value order so the simulation won't get confused
2930 * if it has to move them around.
2931 */
2932 if (!no_modify && need_root_dotdot && ino == mp->m_sb.sb_rootino) {
d967a68d 2933 ASSERT(ip->i_df.if_format != XFS_DINODE_FMT_LOCAL);
2bd0ea18 2934
2556c98b 2935 do_warn(_("recreating root directory .. entry\n"));
2bd0ea18 2936
2556c98b 2937 nres = XFS_MKDIR_SPACE_RES(mp, 2);
9074815c
CH
2938 error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_mkdir,
2939 nres, 0, 0, &tp);
2556c98b
BN
2940 if (error)
2941 res_failed(error);
2bd0ea18 2942
2556c98b 2943 libxfs_trans_ijoin(tp, ip, 0);
2bd0ea18 2944
12b53197 2945 error = -libxfs_dir_createname(tp, ip, &xfs_name_dotdot,
015bc82e 2946 ip->i_ino, nres);
2556c98b 2947 if (error)
5d1b7f0f
CH
2948 do_error(
2949 _("can't make \"..\" entry in root inode %" PRIu64 ", createname error %d\n"), ino, error);
2bd0ea18 2950
2556c98b 2951 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
f2279d8d
DW
2952 error = -libxfs_trans_commit(tp);
2953 if (error)
2954 do_error(
2955 _("root inode \"..\" entry recreation failed (%d)\n"), error);
2bd0ea18 2956
2556c98b
BN
2957 need_root_dotdot = 0;
2958 } else if (need_root_dotdot && ino == mp->m_sb.sb_rootino) {
2959 do_warn(_("would recreate root directory .. entry\n"));
2960 }
2bd0ea18 2961
2556c98b
BN
2962 /*
2963 * if we need to create the '.' entry, do so only if
ff1f79a7 2964 * the directory is a longform dir. if it's been
2556c98b
BN
2965 * turned into a shortform dir, then the inode is ok
2966 * since shortform dirs have no '.' entry and the inode
2967 * has already been committed by prune_lf_dir_entry().
2968 */
2969 if (need_dot) {
2bd0ea18 2970 /*
2556c98b
BN
2971 * bump up our link count but don't
2972 * bump up the inode link count. chances
2973 * are good that even though we lost '.'
2974 * the inode link counts reflect '.' so
2975 * leave the inode link count alone and if
2976 * it turns out to be wrong, we'll catch
2977 * that in phase 7.
2bd0ea18 2978 */
2556c98b
BN
2979 add_inode_ref(irec, ino_offset);
2980
2981 if (no_modify) {
5d1b7f0f
CH
2982 do_warn(
2983 _("would create missing \".\" entry in dir ino %" PRIu64 "\n"),
2556c98b 2984 ino);
d967a68d 2985 } else if (ip->i_df.if_format != XFS_DINODE_FMT_LOCAL) {
2bd0ea18 2986 /*
2556c98b 2987 * need to create . entry in longform dir.
2bd0ea18 2988 */
5d1b7f0f
CH
2989 do_warn(
2990 _("creating missing \".\" entry in dir ino %" PRIu64 "\n"), ino);
2bd0ea18 2991
2556c98b 2992 nres = XFS_MKDIR_SPACE_RES(mp, 1);
9074815c
CH
2993 error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_mkdir,
2994 nres, 0, 0, &tp);
2556c98b
BN
2995 if (error)
2996 res_failed(error);
2bd0ea18 2997
2556c98b 2998 libxfs_trans_ijoin(tp, ip, 0);
2bd0ea18 2999
12b53197 3000 error = -libxfs_dir_createname(tp, ip, &xfs_name_dot,
015bc82e 3001 ip->i_ino, nres);
5e656dbb 3002 if (error)
5d1b7f0f
CH
3003 do_error(
3004 _("can't make \".\" entry in dir ino %" PRIu64 ", createname error %d\n"),
2556c98b 3005 ino, error);
2bd0ea18 3006
2556c98b 3007 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
f2279d8d
DW
3008 error = -libxfs_trans_commit(tp);
3009 if (error)
3010 do_error(
3011 _("root inode \".\" entry recreation failed (%d)\n"), error);
2bd0ea18 3012 }
2bd0ea18 3013 }
31845e4c 3014 libxfs_irele(ip);
2bd0ea18
NS
3015}
3016
3017/*
3018 * mark realtime bitmap and summary inodes as reached.
3019 * quota inode will be marked here as well
3020 */
8b8a6b02 3021static void
2bd0ea18
NS
3022mark_standalone_inodes(xfs_mount_t *mp)
3023{
3024 ino_tree_node_t *irec;
3025 int offset;
3026
1ae311d5 3027 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rbmino),
2bd0ea18
NS
3028 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rbmino));
3029
2bd0ea18
NS
3030 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rbmino) -
3031 irec->ino_startnum;
3032
3033 add_inode_reached(irec, offset);
3034
1ae311d5 3035 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rsumino),
2bd0ea18
NS
3036 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rsumino));
3037
dfc130f3 3038 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rsumino) -
2bd0ea18
NS
3039 irec->ino_startnum;
3040
2bd0ea18
NS
3041 add_inode_reached(irec, offset);
3042
3043 if (fs_quotas) {
3044 if (mp->m_sb.sb_uquotino
3045 && mp->m_sb.sb_uquotino != NULLFSINO) {
1ae311d5 3046 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp,
2bd0ea18
NS
3047 mp->m_sb.sb_uquotino),
3048 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_uquotino));
3049 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_uquotino)
3050 - irec->ino_startnum;
3051 add_inode_reached(irec, offset);
3052 }
b36eef04
NS
3053 if (mp->m_sb.sb_gquotino
3054 && mp->m_sb.sb_gquotino != NULLFSINO) {
1ae311d5 3055 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp,
b36eef04
NS
3056 mp->m_sb.sb_gquotino),
3057 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_gquotino));
3058 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_gquotino)
2bd0ea18
NS
3059 - irec->ino_startnum;
3060 add_inode_reached(irec, offset);
3061 }
0340d706
CS
3062 if (mp->m_sb.sb_pquotino
3063 && mp->m_sb.sb_pquotino != NULLFSINO) {
3064 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp,
3065 mp->m_sb.sb_pquotino),
3066 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_pquotino));
3067 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_pquotino)
3068 - irec->ino_startnum;
3069 add_inode_reached(irec, offset);
3070 }
2bd0ea18
NS
3071 }
3072}
3073
6c39a3cb
BN
3074static void
3075check_for_orphaned_inodes(
3076 xfs_mount_t *mp,
2556c98b 3077 xfs_agnumber_t agno,
6c39a3cb
BN
3078 ino_tree_node_t *irec)
3079{
3080 int i;
6c39a3cb
BN
3081 xfs_ino_t ino;
3082
3083 for (i = 0; i < XFS_INODES_PER_CHUNK; i++) {
3084 ASSERT(is_inode_confirmed(irec, i));
3085 if (is_inode_free(irec, i))
3086 continue;
3087
2556c98b
BN
3088 if (is_inode_reached(irec, i))
3089 continue;
3090
3091 ASSERT(inode_isadir(irec, i) ||
3092 num_inode_references(irec, i) == 0);
3093
3094 ino = XFS_AGINO_TO_INO(mp, agno, i + irec->ino_startnum);
3095 if (inode_isadir(irec, i))
5d1b7f0f 3096 do_warn(_("disconnected dir inode %" PRIu64 ", "), ino);
2556c98b 3097 else
5d1b7f0f 3098 do_warn(_("disconnected inode %" PRIu64 ", "), ino);
9a048535
DC
3099 if (!no_modify) {
3100 if (!orphanage_ino)
2556c98b
BN
3101 orphanage_ino = mk_orphanage(mp);
3102 do_warn(_("moving to %s\n"), ORPHANAGE);
3103 mv_orphanage(mp, ino, inode_isadir(irec, i));
3104 } else {
3105 do_warn(_("would move to %s\n"), ORPHANAGE);
6c39a3cb 3106 }
2556c98b
BN
3107 /*
3108 * for read-only case, even though the inode isn't
3109 * really reachable, set the flag (and bump our link
3110 * count) anyway to fool phase 7
3111 */
3112 add_inode_reached(irec, i);
6c39a3cb
BN
3113 }
3114}
3115
a1d54891 3116static void
39054ffe 3117do_dir_inode(
62843f36 3118 struct workqueue *wq,
39054ffe 3119 xfs_agnumber_t agno,
2556c98b 3120 void *arg)
a1d54891 3121{
39054ffe 3122 struct ino_tree_node *irec = arg;
2556c98b 3123 int i;
39054ffe
DC
3124
3125 for (i = 0; i < XFS_INODES_PER_CHUNK; i++) {
3126 if (inode_isadir(irec, i))
3127 process_dir_inode(wq->wq_ctx, agno, irec, i);
3128 }
3129}
3130
3131static void
3132traverse_function(
3133 struct workqueue *wq,
3134 xfs_agnumber_t agno,
3135 void *arg)
3136{
3137 struct ino_tree_node *irec;
2556c98b 3138 prefetch_args_t *pf_args = arg;
39054ffe
DC
3139 struct workqueue lwq;
3140 struct xfs_mount *mp = wq->wq_ctx;
2556c98b
BN
3141
3142 wait_for_inode_prefetch(pf_args);
a1d54891
MV
3143
3144 if (verbose)
3145 do_log(_(" - agno = %d\n"), agno);
3146
39054ffe
DC
3147 /*
3148 * The more AGs we have in flight at once, the fewer processing threads
3149 * per AG. This means we don't overwhelm the machine with hundreds of
3150 * threads when we start acting on lots of AGs at once. We just want
3151 * enough that we can keep multiple CPUs busy across multiple AGs.
3152 */
3153 workqueue_create_bound(&lwq, mp, ag_stride, 1000);
3154
2556c98b
BN
3155 for (irec = findfirst_inode_rec(agno); irec; irec = next_ino_rec(irec)) {
3156 if (irec->ino_isa_dir == 0)
3157 continue;
a1d54891 3158
004e18d4 3159 if (pf_args) {
2556c98b 3160 sem_post(&pf_args->ra_count);
004e18d4 3161#ifdef XR_PF_TRACE
39054ffe
DC
3162 {
3163 int i;
004e18d4
DC
3164 sem_getvalue(&pf_args->ra_count, &i);
3165 pftrace(
3166 "processing inode chunk %p in AG %d (sem count = %d)",
3167 irec, agno, i);
39054ffe 3168 }
004e18d4
DC
3169#endif
3170 }
a1d54891 3171
39054ffe 3172 queue_work(&lwq, do_dir_inode, agno, irec);
a1d54891 3173 }
39054ffe 3174 destroy_work_queue(&lwq);
2556c98b 3175 cleanup_inode_prefetch(pf_args);
a1d54891
MV
3176}
3177
575ca697
BN
3178static void
3179update_missing_dotdot_entries(
3180 xfs_mount_t *mp)
3181{
3182 dotdot_update_t *dir;
3183
3184 /*
3185 * these entries parents were updated, rebuild them again
3186 * set dotdot_update flag so processing routines do not count links
3187 */
3188 dotdot_update = 1;
1177f669
DC
3189 while (!list_empty(&dotdot_update_list)) {
3190 dir = list_entry(dotdot_update_list.prev, struct dotdot_update,
3191 list);
3192 list_del(&dir->list);
575ca697
BN
3193 process_dir_inode(mp, dir->agno, dir->irec, dir->ino_offset);
3194 free(dir);
3195 }
3196}
3197
a1d54891 3198static void
2556c98b 3199traverse_ags(
1164bde5 3200 struct xfs_mount *mp)
a1d54891 3201{
39054ffe 3202 do_inode_prefetch(mp, ag_stride, traverse_function, false, true);
a1d54891
MV
3203}
3204
2bd0ea18
NS
3205void
3206phase6(xfs_mount_t *mp)
3207{
2bd0ea18 3208 ino_tree_node_t *irec;
2bd0ea18 3209 int i;
2bd0ea18 3210
dab9b8d6
BN
3211 memset(&zerocr, 0, sizeof(struct cred));
3212 memset(&zerofsx, 0, sizeof(struct fsxattr));
6c39a3cb 3213 orphanage_ino = 0;
2bd0ea18 3214
507f4e33 3215 do_log(_("Phase 6 - check inode connectivity...\n"));
2bd0ea18 3216
2bd0ea18
NS
3217 incore_ext_teardown(mp);
3218
0f012a4c 3219 add_ino_ex_data(mp);
2bd0ea18
NS
3220
3221 /*
3222 * verify existence of root directory - if we have to
3223 * make one, it's ok for the incore data structs not to
3224 * know about it since everything about it (and the other
3225 * inodes in its chunk if a new chunk was created) are ok
3226 */
3227 if (need_root_inode) {
9a048535 3228 if (!no_modify) {
507f4e33 3229 do_warn(_("reinitializing root directory\n"));
2bd0ea18
NS
3230 mk_root_dir(mp);
3231 need_root_inode = 0;
3232 need_root_dotdot = 0;
3233 } else {
507f4e33 3234 do_warn(_("would reinitialize root directory\n"));
2bd0ea18
NS
3235 }
3236 }
3237
3238 if (need_rbmino) {
3239 if (!no_modify) {
507f4e33 3240 do_warn(_("reinitializing realtime bitmap inode\n"));
2bd0ea18
NS
3241 mk_rbmino(mp);
3242 need_rbmino = 0;
3243 } else {
507f4e33 3244 do_warn(_("would reinitialize realtime bitmap inode\n"));
2bd0ea18
NS
3245 }
3246 }
3247
3248 if (need_rsumino) {
3249 if (!no_modify) {
507f4e33 3250 do_warn(_("reinitializing realtime summary inode\n"));
2bd0ea18
NS
3251 mk_rsumino(mp);
3252 need_rsumino = 0;
3253 } else {
507f4e33 3254 do_warn(_("would reinitialize realtime summary inode\n"));
2bd0ea18
NS
3255 }
3256 }
3257
3258 if (!no_modify) {
3259 do_log(
507f4e33 3260_(" - resetting contents of realtime bitmap and summary inodes\n"));
2bd0ea18
NS
3261 if (fill_rbmino(mp)) {
3262 do_warn(
507f4e33 3263 _("Warning: realtime bitmap may be inconsistent\n"));
2bd0ea18
NS
3264 }
3265
3266 if (fill_rsumino(mp)) {
3267 do_warn(
507f4e33 3268 _("Warning: realtime bitmap may be inconsistent\n"));
2bd0ea18
NS
3269 }
3270 }
3271
2bd0ea18
NS
3272 mark_standalone_inodes(mp);
3273
69ec88b5 3274 do_log(_(" - traversing filesystem ...\n"));
2bd0ea18 3275
1ae311d5 3276 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino),
2bd0ea18
NS
3277 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino));
3278
3279 /*
3280 * we always have a root inode, even if it's free...
3281 * if the root is free, forget it, lost+found is already gone
3282 */
3283 if (is_inode_free(irec, 0) || !inode_isadir(irec, 0)) {
3284 need_root_inode = 1;
3285 }
3286
3287 /*
2556c98b 3288 * then process all inodes by walking incore inode tree
2bd0ea18 3289 */
2556c98b 3290 traverse_ags(mp);
2bd0ea18 3291
575ca697
BN
3292 /*
3293 * any directories that had updated ".." entries, rebuild them now
3294 */
3295 update_missing_dotdot_entries(mp);
3296
69ec88b5
BN
3297 do_log(_(" - traversal finished ...\n"));
3298 do_log(_(" - moving disconnected inodes to %s ...\n"),
6c39a3cb 3299 ORPHANAGE);
2bd0ea18
NS
3300
3301 /*
3302 * move all disconnected inodes to the orphanage
3303 */
3304 for (i = 0; i < glob_agcount; i++) {
3305 irec = findfirst_inode_rec(i);
2bd0ea18 3306 while (irec != NULL) {
2556c98b 3307 check_for_orphaned_inodes(mp, i, irec);
2bd0ea18
NS
3308 irec = next_ino_rec(irec);
3309 }
3310 }
3311}