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