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