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