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