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