]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - repair/phase6.c
xfs_repair: validate & fix inode CRCs
[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);
1954 if (error) {
5d1b7f0f 1955 do_error(
8e7e14be
DC
1956 _("can't read block %u for directory inode %" PRIu64 ", error %d\n"),
1957 da_bno, ip->i_ino, error);
2bd0ea18
NS
1958 /* NOTREACHED */
1959 }
8e7e14be 1960
a2ceac1f 1961 leaf = bp->b_addr;
658ac3e3 1962 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
65b80c98 1963 ents = xfs_dir3_leaf_ents_p(leaf);
5e656dbb
BN
1964 ltp = xfs_dir2_leaf_tail_p(mp, leaf);
1965 bestsp = xfs_dir2_leaf_bests_p(ltp);
658ac3e3
DC
1966 if (!(leafhdr.magic == XFS_DIR2_LEAF1_MAGIC ||
1967 leafhdr.magic == XFS_DIR3_LEAF1_MAGIC) ||
1968 leafhdr.forw || leafhdr.back ||
5eb1ac90 1969 leafhdr.count < leafhdr.stale ||
658ac3e3 1970 leafhdr.count >
65b80c98 1971 xfs_dir3_max_leaf_ents(mp, leaf) ||
658ac3e3 1972 (char *)&ents[leafhdr.count] > (char *)bestsp) {
507f4e33 1973 do_warn(
5d1b7f0f 1974 _("leaf block %u for directory inode %" PRIu64 " bad header\n"),
2bd0ea18 1975 da_bno, ip->i_ino);
a2ceac1f 1976 libxfs_putbuf(bp);
2bd0ea18
NS
1977 return 1;
1978 }
658ac3e3 1979 seeval = dir_hash_see_all(hashtab, ents, leafhdr.count, leafhdr.stale);
2bd0ea18 1980 if (dir_hash_check(hashtab, ip, seeval)) {
a2ceac1f 1981 libxfs_putbuf(bp);
2bd0ea18
NS
1982 return 1;
1983 }
5e656dbb
BN
1984 badtail = freetab->nents != be32_to_cpu(ltp->bestcount);
1985 for (i = 0; !badtail && i < be32_to_cpu(ltp->bestcount); i++) {
2bd0ea18 1986 freetab->ents[i].s = 1;
5e656dbb 1987 badtail = freetab->ents[i].v != be16_to_cpu(bestsp[i]);
2bd0ea18
NS
1988 }
1989 if (badtail) {
5d1b7f0f
CH
1990 do_warn(
1991 _("leaf block %u for directory inode %" PRIu64 " bad tail\n"),
2bd0ea18 1992 da_bno, ip->i_ino);
a2ceac1f 1993 libxfs_putbuf(bp);
2bd0ea18
NS
1994 return 1;
1995 }
a2ceac1f 1996 libxfs_putbuf(bp);
8e7e14be 1997 return fixit;
2bd0ea18
NS
1998}
1999
2000/*
2001 * Check contents of the node blocks (leaves)
2002 * Looks for matching hash values for the data entries.
2003 */
2556c98b 2004static int
2bd0ea18
NS
2005longform_dir2_check_node(
2006 xfs_mount_t *mp,
2007 xfs_inode_t *ip,
2008 dir_hash_tab_t *hashtab,
2009 freetab_t *freetab)
2010{
a2ceac1f 2011 struct xfs_buf *bp;
2bd0ea18
NS
2012 xfs_dablk_t da_bno;
2013 xfs_dir2_db_t fdb;
2014 xfs_dir2_free_t *free;
2015 int i;
2016 xfs_dir2_leaf_t *leaf;
2017 xfs_fileoff_t next_da_bno;
2018 int seeval = 0;
2019 int used;
65b80c98 2020 struct xfs_dir2_leaf_entry *ents;
658ac3e3
DC
2021 struct xfs_dir3_icleaf_hdr leafhdr;
2022 struct xfs_dir3_icfree_hdr freehdr;
2023 __be16 *bests;
8e7e14be
DC
2024 int error;
2025 int fixit = 0;
0f012a4c 2026
2bd0ea18 2027 for (da_bno = mp->m_dirleafblk, next_da_bno = 0;
5e656dbb
BN
2028 next_da_bno != NULLFILEOFF && da_bno < mp->m_dirfreeblk;
2029 da_bno = (xfs_dablk_t)next_da_bno) {
2bd0ea18 2030 next_da_bno = da_bno + mp->m_dirblkfsbs - 1;
5e656dbb 2031 if (bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK))
2bd0ea18 2032 break;
9b981421
DC
2033
2034 /*
2035 * we need to use the da3 node verifier here as it handles the
2036 * fact that reading the leaf hash tree blocks can return either
2037 * leaf or node blocks and calls the correct verifier. If we get
2038 * a node block, then we'll skip it below based on a magic
2039 * number check.
2040 */
8e7e14be
DC
2041 error = dir_read_buf(ip, da_bno, -1, &bp,
2042 &xfs_da3_node_buf_ops, &fixit);
2043 if (error) {
33165ec3 2044 do_warn(
8e7e14be
DC
2045 _("can't read leaf block %u for directory inode %" PRIu64 ", error %d\n"),
2046 da_bno, ip->i_ino, error);
33165ec3 2047 return 1;
2bd0ea18 2048 }
a2ceac1f 2049 leaf = bp->b_addr;
658ac3e3 2050 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
65b80c98 2051 ents = xfs_dir3_leaf_ents_p(leaf);
658ac3e3
DC
2052 if (!(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC ||
2053 leafhdr.magic == XFS_DIR3_LEAFN_MAGIC)) {
2054 if (leafhdr.magic == XFS_DA_NODE_MAGIC ||
2055 leafhdr.magic == XFS_DA3_NODE_MAGIC) {
a2ceac1f 2056 libxfs_putbuf(bp);
2bd0ea18
NS
2057 continue;
2058 }
5d1b7f0f
CH
2059 do_warn(
2060 _("unknown magic number %#x for block %u in directory inode %" PRIu64 "\n"),
658ac3e3 2061 leafhdr.magic, da_bno, ip->i_ino);
a2ceac1f 2062 libxfs_putbuf(bp);
2bd0ea18
NS
2063 return 1;
2064 }
8e7e14be
DC
2065
2066 /*
2067 * If there's a validator error, we need to ensure that we got
2068 * the right ops on the buffer for when we write it back out.
2069 */
2070 bp->b_ops = &xfs_dir3_leafn_buf_ops;
658ac3e3
DC
2071 if (leafhdr.count > xfs_dir3_max_leaf_ents(mp, leaf) ||
2072 leafhdr.count < leafhdr.stale) {
5d1b7f0f
CH
2073 do_warn(
2074 _("leaf block %u for directory inode %" PRIu64 " bad header\n"),
2bd0ea18 2075 da_bno, ip->i_ino);
a2ceac1f 2076 libxfs_putbuf(bp);
2bd0ea18
NS
2077 return 1;
2078 }
65b80c98 2079 seeval = dir_hash_see_all(hashtab, ents,
658ac3e3 2080 leafhdr.count, leafhdr.stale);
a2ceac1f 2081 libxfs_putbuf(bp);
0f012a4c 2082 if (seeval != DIR_HASH_CK_OK)
2bd0ea18
NS
2083 return 1;
2084 }
0f012a4c 2085 if (dir_hash_check(hashtab, ip, seeval))
2bd0ea18 2086 return 1;
0f012a4c 2087
2bd0ea18
NS
2088 for (da_bno = mp->m_dirfreeblk, next_da_bno = 0;
2089 next_da_bno != NULLFILEOFF;
2090 da_bno = (xfs_dablk_t)next_da_bno) {
2091 next_da_bno = da_bno + mp->m_dirblkfsbs - 1;
5e656dbb 2092 if (bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK))
2bd0ea18 2093 break;
8e7e14be
DC
2094
2095 error = dir_read_buf(ip, da_bno, -1, &bp,
2096 &xfs_dir3_free_buf_ops, &fixit);
2097 if (error) {
33165ec3 2098 do_warn(
8e7e14be
DC
2099 _("can't read freespace block %u for directory inode %" PRIu64 ", error %d\n"),
2100 da_bno, ip->i_ino, error);
33165ec3 2101 return 1;
2bd0ea18 2102 }
a2ceac1f 2103 free = bp->b_addr;
658ac3e3
DC
2104 xfs_dir3_free_hdr_from_disk(&freehdr, free);
2105 bests = xfs_dir3_free_bests_p(mp, free);
5e656dbb 2106 fdb = xfs_dir2_da_to_db(mp, da_bno);
658ac3e3
DC
2107 if (!(freehdr.magic == XFS_DIR2_FREE_MAGIC ||
2108 freehdr.magic == XFS_DIR3_FREE_MAGIC) ||
2109 freehdr.firstdb !=
5e656dbb 2110 (fdb - XFS_DIR2_FREE_FIRSTDB(mp)) *
3303b09f 2111 xfs_dir3_free_max_bests(mp) ||
658ac3e3 2112 freehdr.nvalid < freehdr.nused) {
5d1b7f0f
CH
2113 do_warn(
2114 _("free block %u for directory inode %" PRIu64 " bad header\n"),
2bd0ea18 2115 da_bno, ip->i_ino);
a2ceac1f 2116 libxfs_putbuf(bp);
2bd0ea18
NS
2117 return 1;
2118 }
658ac3e3
DC
2119 for (i = used = 0; i < freehdr.nvalid; i++) {
2120 if (i + freehdr.firstdb >= freetab->nents ||
2121 freetab->ents[i + freehdr.firstdb].v !=
2122 be16_to_cpu(bests[i])) {
507f4e33 2123 do_warn(
5d1b7f0f 2124 _("free block %u entry %i for directory ino %" PRIu64 " bad\n"),
2bd0ea18 2125 da_bno, i, ip->i_ino);
a2ceac1f 2126 libxfs_putbuf(bp);
2bd0ea18
NS
2127 return 1;
2128 }
658ac3e3
DC
2129 used += be16_to_cpu(bests[i]) != NULLDATAOFF;
2130 freetab->ents[i + freehdr.firstdb].s = 1;
2bd0ea18 2131 }
658ac3e3 2132 if (used != freehdr.nused) {
5d1b7f0f
CH
2133 do_warn(
2134 _("free block %u for directory inode %" PRIu64 " bad nused\n"),
2bd0ea18 2135 da_bno, ip->i_ino);
a2ceac1f 2136 libxfs_putbuf(bp);
2bd0ea18
NS
2137 return 1;
2138 }
a2ceac1f 2139 libxfs_putbuf(bp);
2bd0ea18
NS
2140 }
2141 for (i = 0; i < freetab->nents; i++) {
4b6a2d8e
NS
2142 if ((freetab->ents[i].s == 0) &&
2143 (freetab->ents[i].v != NULLDATAOFF)) {
5d1b7f0f
CH
2144 do_warn(
2145 _("missing freetab entry %u for directory inode %" PRIu64 "\n"),
2bd0ea18
NS
2146 i, ip->i_ino);
2147 return 1;
2148 }
2149 }
8e7e14be 2150 return fixit;
2bd0ea18
NS
2151}
2152
2153/*
33165ec3
BN
2154 * If a directory is corrupt, we need to read in as many entries as possible,
2155 * destroy the entry and create a new one with recovered name/inode pairs.
2156 * (ie. get libxfs to do all the grunt work)
2bd0ea18 2157 */
2556c98b 2158static void
2bd0ea18
NS
2159longform_dir2_entry_check(xfs_mount_t *mp,
2160 xfs_ino_t ino,
2161 xfs_inode_t *ip,
2162 int *num_illegal,
2163 int *need_dot,
2bd0ea18 2164 ino_tree_node_t *irec,
64c54486 2165 int ino_offset,
33165ec3 2166 dir_hash_tab_t *hashtab)
2bd0ea18 2167{
a2ceac1f 2168 struct xfs_buf **bplist;
2bd0ea18
NS
2169 xfs_dablk_t da_bno;
2170 freetab_t *freetab;
95dff16b 2171 int num_bps;
2bd0ea18
NS
2172 int i;
2173 int isblock;
2174 int isleaf;
2175 xfs_fileoff_t next_da_bno;
2176 int seeval;
b5fa9e86 2177 int fixit = 0;
95dff16b 2178 xfs_dir2_db_t db;
2bd0ea18
NS
2179
2180 *need_dot = 1;
2181 freetab = malloc(FREETAB_SIZE(ip->i_d.di_size / mp->m_dirblksize));
2182 if (!freetab) {
15e3986b
DC
2183 do_error(_("malloc failed in %s (%" PRId64 " bytes)\n"),
2184 __func__,
2bd0ea18
NS
2185 FREETAB_SIZE(ip->i_d.di_size / mp->m_dirblksize));
2186 exit(1);
2187 }
2188 freetab->naents = ip->i_d.di_size / mp->m_dirblksize;
2189 freetab->nents = 0;
2190 for (i = 0; i < freetab->naents; i++) {
2191 freetab->ents[i].v = NULLDATAOFF;
2192 freetab->ents[i].s = 0;
2193 }
95dff16b 2194 num_bps = freetab->naents;
a2ceac1f 2195 bplist = calloc(num_bps, sizeof(struct xfs_buf*));
15e3986b
DC
2196 if (!bplist)
2197 do_error(_("calloc failed in %s (%zu bytes)\n"),
2198 __func__, num_bps * sizeof(struct xfs_buf*));
2199
9d7d6241 2200 /* is this a block, leaf, or node directory? */
2bd0ea18
NS
2201 libxfs_dir2_isblock(NULL, ip, &isblock);
2202 libxfs_dir2_isleaf(NULL, ip, &isleaf);
9d7d6241 2203
33165ec3 2204 /* check directory "data" blocks (ie. name/inode pairs) */
2bd0ea18
NS
2205 for (da_bno = 0, next_da_bno = 0;
2206 next_da_bno != NULLFILEOFF && da_bno < mp->m_dirleafblk;
2207 da_bno = (xfs_dablk_t)next_da_bno) {
b5fa9e86 2208 const struct xfs_buf_ops *ops;
8e7e14be 2209 int error;
b5fa9e86 2210
2bd0ea18 2211 next_da_bno = da_bno + mp->m_dirblkfsbs - 1;
15e3986b
DC
2212 if (bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK)) {
2213 /*
2214 * if this is the first block, there isn't anything we
2215 * can recover so we just trash it.
2216 */
2217 if (da_bno == 0) {
2218 fixit++;
2219 goto out_fix;
2220 }
2bd0ea18 2221 break;
15e3986b
DC
2222 }
2223
5e656dbb 2224 db = xfs_dir2_da_to_db(mp, da_bno);
95dff16b
BN
2225 if (db >= num_bps) {
2226 /* more data blocks than expected */
2227 num_bps = db + 1;
a2ceac1f 2228 bplist = realloc(bplist, num_bps * sizeof(struct xfs_buf*));
0f012a4c 2229 if (!bplist)
15e3986b
DC
2230 do_error(_("realloc failed in %s (%zu bytes)\n"),
2231 __func__,
a2ceac1f 2232 num_bps * sizeof(struct xfs_buf*));
95dff16b 2233 }
b5fa9e86
DC
2234
2235 if (isblock)
2236 ops = &xfs_dir3_block_buf_ops;
2237 else
2238 ops = &xfs_dir3_data_buf_ops;
8e7e14be
DC
2239
2240 error = dir_read_buf(ip, da_bno, -1, &bplist[db], ops, &fixit);
2241 if (error) {
5d1b7f0f 2242 do_warn(
8e7e14be
DC
2243 _("can't read data block %u for directory inode %" PRIu64 " error %d\n"),
2244 da_bno, ino, error);
95dff16b 2245 *num_illegal += 1;
b5fa9e86
DC
2246
2247 /*
2248 * we try to read all "data" blocks, but if we are in
2249 * block form and we fail, there isn't anything else to
2250 * read, and nothing we can do but trash it.
2251 */
2252 if (isblock) {
2253 fixit++;
2254 goto out_fix;
2255 }
2256 continue;
2bd0ea18
NS
2257 }
2258 longform_dir2_entry_check_data(mp, ip, num_illegal, need_dot,
2556c98b 2259 irec, ino_offset, &bplist[db], hashtab,
33165ec3 2260 &freetab, da_bno, isblock);
2bd0ea18 2261 }
8e7e14be 2262 fixit |= (*num_illegal != 0) || dir2_is_badino(ino) || *need_dot;
9d7d6241 2263
575ca697
BN
2264 if (!dotdot_update) {
2265 /* check btree and freespace */
2266 if (isblock) {
a354abc8 2267 struct xfs_dir2_data_hdr *block;
575ca697
BN
2268 xfs_dir2_block_tail_t *btp;
2269 xfs_dir2_leaf_entry_t *blp;
2270
a2ceac1f 2271 block = bplist[0]->b_addr;
a354abc8 2272 btp = xfs_dir2_block_tail_p(mp, block);
5e656dbb 2273 blp = xfs_dir2_block_leaf_p(btp);
575ca697
BN
2274 seeval = dir_hash_see_all(hashtab, blp,
2275 be32_to_cpu(btp->count),
2276 be32_to_cpu(btp->stale));
2277 if (dir_hash_check(hashtab, ip, seeval))
2278 fixit |= 1;
2279 } else if (isleaf) {
2280 fixit |= longform_dir2_check_leaf(mp, ip, hashtab,
2281 freetab);
2282 } else {
2283 fixit |= longform_dir2_check_node(mp, ip, hashtab,
2284 freetab);
2285 }
2bd0ea18 2286 }
b5fa9e86 2287out_fix:
575ca697 2288 if (!no_modify && (fixit || dotdot_update)) {
33165ec3 2289 dir_hash_dup_names(hashtab);
0f012a4c 2290 for (i = 0; i < freetab->naents; i++)
33165ec3 2291 if (bplist[i])
a2ceac1f 2292 libxfs_putbuf(bplist[i]);
6fa00c33 2293 longform_dir2_rebuild(mp, ino, ip, irec, ino_offset, hashtab);
33165ec3 2294 *num_illegal = 0;
6fa00c33 2295 *need_dot = 0;
33165ec3 2296 } else {
0f012a4c 2297 for (i = 0; i < freetab->naents; i++)
33165ec3 2298 if (bplist[i])
a2ceac1f 2299 libxfs_putbuf(bplist[i]);
33165ec3 2300 }
0f012a4c 2301
95dff16b 2302 free(bplist);
2bd0ea18
NS
2303 free(freetab);
2304}
2305
2bd0ea18
NS
2306/*
2307 * shortform directory v2 processing routines -- entry verification and
2308 * bad entry deletion (pruning).
2309 */
aaca101b
DC
2310static struct xfs_dir2_sf_entry *
2311shortform_dir2_junk(
2312 struct xfs_mount *mp,
2313 struct xfs_dir2_sf_hdr *sfp,
2314 struct xfs_dir2_sf_entry *sfep,
2315 xfs_ino_t lino,
2316 int *max_size,
2317 int *index,
2318 int *bytes_deleted,
2319 int *ino_dirty)
2320{
2321 struct xfs_dir2_sf_entry *next_sfep;
2322 int next_len;
2323 int next_elen;
2324
2325 if (lino == orphanage_ino)
2326 orphanage_ino = 0;
2327
2328 next_elen = xfs_dir3_sf_entsize(mp, sfp, sfep->namelen);
2329 next_sfep = (xfs_dir2_sf_entry_t *)((__psint_t)sfep + next_elen);
2330
2331 /*
2332 * if we are just checking, simply return the pointer to the next entry
2333 * here so that the checking loop can continue.
2334 */
2335 if (no_modify) {
2336 do_warn(_("would junk entry\n"));
2337 return next_sfep;
2338 }
2339
2340 /*
2341 * now move all the remaining entries down over the junked entry and
2342 * clear the newly unused bytes at the tail of the directory region.
2343 */
2344 next_len = *max_size - ((__psint_t)next_sfep - (__psint_t)sfp);
2345 *max_size -= next_elen;
2346 *bytes_deleted += next_elen;
2347
2348 memmove(sfep, next_sfep, next_len);
2349 memset((void *)((__psint_t)sfep + next_len), 0, next_elen);
2350 sfp->count -= 1;
2351 *ino_dirty = 1;
2352
2353 /*
2354 * WARNING: drop the index i by one so it matches the decremented count
2355 * for accurate comparisons in the loop test
2356 */
2357 (*index)--;
2358
2359 if (verbose)
2360 do_warn(_("junking entry\n"));
2361 else
2362 do_warn("\n");
2363 return sfep;
2364}
2365
2556c98b 2366static void
2bd0ea18
NS
2367shortform_dir2_entry_check(xfs_mount_t *mp,
2368 xfs_ino_t ino,
2369 xfs_inode_t *ip,
2370 int *ino_dirty,
2bd0ea18 2371 ino_tree_node_t *current_irec,
64c54486 2372 int current_ino_offset,
33165ec3 2373 dir_hash_tab_t *hashtab)
2bd0ea18
NS
2374{
2375 xfs_ino_t lino;
2376 xfs_ino_t parent;
a354abc8 2377 struct xfs_dir2_sf_hdr *sfp;
aaca101b
DC
2378 struct xfs_dir2_sf_entry *sfep;
2379 struct xfs_dir2_sf_entry *next_sfep;
2380 struct xfs_ifork *ifp;
2381 struct ino_tree_node *irec;
2bd0ea18
NS
2382 int max_size;
2383 int ino_offset;
2384 int i;
2bd0ea18
NS
2385 int bad_sfnamelen;
2386 int namelen;
2387 int bytes_deleted;
2388 char fname[MAXNAMELEN + 1];
2389 int i8;
2390
2391 ifp = &ip->i_df;
a354abc8 2392 sfp = (struct xfs_dir2_sf_hdr *) ifp->if_u1.if_data;
2bd0ea18 2393 *ino_dirty = 0;
e55d768a 2394 bytes_deleted = 0;
2bd0ea18
NS
2395
2396 max_size = ifp->if_bytes;
2397 ASSERT(ip->i_d.di_size <= ifp->if_bytes);
2398
575ca697
BN
2399 /*
2400 * if just rebuild a directory due to a "..", update and return
2401 */
2402 if (dotdot_update) {
2403 parent = get_inode_parent(current_irec, current_ino_offset);
2404 if (no_modify) {
5d1b7f0f
CH
2405 do_warn(
2406 _("would set .. in sf dir inode %" PRIu64 " to %" PRIu64 "\n"),
575ca697
BN
2407 ino, parent);
2408 } else {
5d1b7f0f
CH
2409 do_warn(
2410 _("setting .. in sf dir inode %" PRIu64 " to %" PRIu64 "\n"),
575ca697 2411 ino, parent);
a354abc8 2412 xfs_dir2_sf_put_parent_ino(sfp, parent);
575ca697
BN
2413 *ino_dirty = 1;
2414 }
2415 return;
2416 }
2417
2bd0ea18
NS
2418 /*
2419 * no '.' entry in shortform dirs, just bump up ref count by 1
2420 * '..' was already (or will be) accounted for and checked when
2421 * the directory is reached or will be taken care of when the
2422 * directory is moved to orphanage.
2423 */
2424 add_inode_ref(current_irec, current_ino_offset);
2425
e55d768a
NS
2426 /*
2427 * Initialise i8 counter -- the parent inode number counts as well.
2428 */
a354abc8 2429 i8 = xfs_dir2_sf_get_parent_ino(sfp) > XFS_DIR2_MAX_SHORT_INUM;
e55d768a 2430
2bd0ea18
NS
2431 /*
2432 * now run through entries, stop at first bad entry, don't need
2433 * to skip over '..' since that's encoded in its own field and
2434 * no need to worry about '.' since it doesn't exist.
2435 */
a354abc8 2436 sfep = next_sfep = xfs_dir2_sf_firstentry(sfp);
2bd0ea18 2437
a354abc8 2438 for (i = 0; i < sfp->count && max_size >
2bd0ea18
NS
2439 (__psint_t)next_sfep - (__psint_t)sfp;
2440 sfep = next_sfep, i++) {
2bd0ea18 2441 bad_sfnamelen = 0;
2bd0ea18 2442
494434d7 2443 lino = xfs_dir3_sfe_get_ino(mp, sfp, sfep);
2bd0ea18
NS
2444
2445 namelen = sfep->namelen;
2446
2447 ASSERT(no_modify || namelen > 0);
2448
2449 if (no_modify && namelen == 0) {
2450 /*
2451 * if we're really lucky, this is
2452 * the last entry in which case we
2453 * can use the dir size to set the
2454 * namelen value. otherwise, forget
2455 * it because we're not going to be
2456 * able to find the next entry.
2457 */
2458 bad_sfnamelen = 1;
2459
a354abc8 2460 if (i == sfp->count - 1) {
2bd0ea18
NS
2461 namelen = ip->i_d.di_size -
2462 ((__psint_t) &sfep->name[0] -
2463 (__psint_t) sfp);
2464 } else {
2465 /*
2466 * don't process the rest of the directory,
2467 * break out of processing loop
2468 */
2469 break;
2470 }
2471 } else if (no_modify && (__psint_t) sfep - (__psint_t) sfp +
494434d7 2472 + xfs_dir3_sf_entsize(mp, sfp, sfep->namelen)
2bd0ea18
NS
2473 > ip->i_d.di_size) {
2474 bad_sfnamelen = 1;
2475
a354abc8 2476 if (i == sfp->count - 1) {
2bd0ea18
NS
2477 namelen = ip->i_d.di_size -
2478 ((__psint_t) &sfep->name[0] -
2479 (__psint_t) sfp);
2480 } else {
2481 /*
2482 * don't process the rest of the directory,
2483 * break out of processing loop
2484 */
2485 break;
2486 }
2487 }
2488
dab9b8d6 2489 memmove(fname, sfep->name, sfep->namelen);
2bd0ea18
NS
2490 fname[sfep->namelen] = '\0';
2491
2492 ASSERT(no_modify || (lino != NULLFSINO && lino != 0));
2493 ASSERT(no_modify || !verify_inum(mp, lino));
2494
e55d768a
NS
2495 /*
2496 * Also skip entries with bogus inode numbers if we're
2497 * in no modify mode.
2498 */
2499
2500 if (no_modify && verify_inum(mp, lino)) {
5e656dbb 2501 next_sfep = (xfs_dir2_sf_entry_t *)((__psint_t)sfep +
494434d7 2502 xfs_dir3_sf_entsize(mp, sfp, sfep->namelen));
2bd0ea18
NS
2503 continue;
2504 }
2505
1ae311d5 2506 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, lino),
2bd0ea18
NS
2507 XFS_INO_TO_AGINO(mp, lino));
2508
6c39a3cb 2509 if (irec == NULL) {
5d1b7f0f
CH
2510 do_warn(
2511 _("entry \"%s\" in shortform directory %" PRIu64 " references non-existent inode %" PRIu64 "\n"),
2bd0ea18 2512 fname, ino, lino);
aaca101b
DC
2513 next_sfep = shortform_dir2_junk(mp, sfp, sfep, lino,
2514 &max_size, &i, &bytes_deleted,
2515 ino_dirty);
2516 continue;
2bd0ea18
NS
2517 }
2518
2bd0ea18
NS
2519 ino_offset = XFS_INO_TO_AGINO(mp, lino) - irec->ino_startnum;
2520
2521 /*
2522 * if it's a free inode, blow out the entry.
2523 * by now, any inode that we think is free
2524 * really is free.
2525 */
2526 if (is_inode_free(irec, ino_offset)) {
5d1b7f0f
CH
2527 do_warn(
2528 _("entry \"%s\" in shortform directory inode %" PRIu64 " points to free inode %" PRIu64 "\n"),
6c39a3cb 2529 fname, ino, lino);
aaca101b
DC
2530 next_sfep = shortform_dir2_junk(mp, sfp, sfep, lino,
2531 &max_size, &i, &bytes_deleted,
2532 ino_dirty);
2533 continue;
6c39a3cb
BN
2534 }
2535 /*
2536 * check if this inode is lost+found dir in the root
2537 */
2538 if (ino == mp->m_sb.sb_rootino && strcmp(fname, ORPHANAGE) == 0) {
2bd0ea18 2539 /*
6c39a3cb 2540 * if it's not a directory, trash it
2bd0ea18 2541 */
6c39a3cb 2542 if (!inode_isadir(irec, ino_offset)) {
5d1b7f0f
CH
2543 do_warn(
2544 _("%s (ino %" PRIu64 ") in root (%" PRIu64 ") is not a directory"),
2545 ORPHANAGE, lino, ino);
aaca101b
DC
2546 next_sfep = shortform_dir2_junk(mp, sfp, sfep,
2547 lino, &max_size, &i,
2548 &bytes_deleted, ino_dirty);
2549 continue;
2bd0ea18 2550 }
64c54486 2551 /*
6c39a3cb
BN
2552 * if this is a dup, it will be picked up below,
2553 * otherwise, mark it as the orphanage for later.
0f012a4c 2554 */
6c39a3cb
BN
2555 if (!orphanage_ino)
2556 orphanage_ino = lino;
2557 }
2558 /*
2559 * check for duplicate names in directory.
2560 */
51ca7008 2561 if (!dir_hash_add(mp, hashtab, (xfs_dir2_dataptr_t)
a354abc8 2562 (sfep - xfs_dir2_sf_firstentry(sfp)),
aaca101b
DC
2563 lino, sfep->namelen, sfep->name,
2564 xfs_dir3_sfe_get_ftype(mp, sfp, sfep))) {
5d1b7f0f
CH
2565 do_warn(
2566_("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"),
2567 fname, lino, ino);
aaca101b
DC
2568 next_sfep = shortform_dir2_junk(mp, sfp, sfep, lino,
2569 &max_size, &i, &bytes_deleted,
2570 ino_dirty);
2571 continue;
6c39a3cb 2572 }
575ca697 2573
6c39a3cb 2574 if (!inode_isadir(irec, ino_offset)) {
2bd0ea18
NS
2575 /*
2576 * check easy case first, regular inode, just bump
e55d768a 2577 * the link count
2bd0ea18
NS
2578 */
2579 add_inode_reached(irec, ino_offset);
2bd0ea18
NS
2580 } else {
2581 parent = get_inode_parent(irec, ino_offset);
2582
2583 /*
2584 * bump up the link counts in parent and child.
2585 * directory but if the link doesn't agree with
2586 * the .. in the child, blow out the entry
2587 */
2588 if (is_inode_reached(irec, ino_offset)) {
5d1b7f0f
CH
2589 do_warn(
2590 _("entry \"%s\" in directory inode %" PRIu64
2591 " references already connected inode %" PRIu64 ".\n"),
2bd0ea18 2592 fname, ino, lino);
aaca101b
DC
2593 next_sfep = shortform_dir2_junk(mp, sfp, sfep,
2594 lino, &max_size, &i,
2595 &bytes_deleted, ino_dirty);
2596 continue;
2bd0ea18
NS
2597 } else if (parent == ino) {
2598 add_inode_reached(irec, ino_offset);
2599 add_inode_ref(current_irec, current_ino_offset);
6fa00c33
BN
2600 } else if (parent == NULLFSINO) {
2601 /* ".." was missing, but this entry refers to it,
2602 so, set it as the parent and mark for rebuild */
5d1b7f0f
CH
2603 do_warn(
2604 _("entry \"%s\" in dir ino %" PRIu64 " doesn't have a .. entry, will set it in ino %" PRIu64 ".\n"),
6fa00c33
BN
2605 fname, ino, lino);
2606 set_inode_parent(irec, ino_offset, ino);
2607 add_inode_reached(irec, ino_offset);
2608 add_inode_ref(current_irec, current_ino_offset);
575ca697
BN
2609 add_dotdot_update(XFS_INO_TO_AGNO(mp, lino),
2610 irec, ino_offset);
2bd0ea18 2611 } else {
5d1b7f0f
CH
2612 do_warn(
2613 _("entry \"%s\" in directory inode %" PRIu64
2614 " not consistent with .. value (%" PRIu64
2615 ") in inode %" PRIu64 ",\n"),
2bd0ea18 2616 fname, ino, parent, lino);
aaca101b
DC
2617 next_sfep = shortform_dir2_junk(mp, sfp, sfep,
2618 lino, &max_size, &i,
2619 &bytes_deleted, ino_dirty);
2620 continue;
2bd0ea18
NS
2621 }
2622 }
2623
aaca101b
DC
2624 /* validate ftype field if supported */
2625 if (xfs_sb_version_hasftype(&mp->m_sb)) {
2626 __uint8_t dir_ftype;
2627 __uint8_t ino_ftype;
2bd0ea18 2628
aaca101b
DC
2629 dir_ftype = xfs_dir3_sfe_get_ftype(mp, sfp, sfep);
2630 ino_ftype = get_inode_ftype(irec, ino_offset);
2bd0ea18 2631
aaca101b
DC
2632 if (dir_ftype != ino_ftype) {
2633 if (no_modify) {
2634 do_warn(
2635 _("would fix ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"),
2636 dir_ftype, ino_ftype,
2637 ino, lino);
2638 } else {
2639 do_warn(
2640 _("fixing ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"),
2641 dir_ftype, ino_ftype,
2642 ino, lino);
2643 xfs_dir3_sfe_put_ftype(mp, sfp, sfep,
2644 ino_ftype);
2645 dir_hash_update_ftype(hashtab,
2646 (xfs_dir2_dataptr_t)(sfep - xfs_dir2_sf_firstentry(sfp)),
2647 ino_ftype);
2648 *ino_dirty = 1;
2649 }
2bd0ea18 2650 }
aaca101b
DC
2651 }
2652
2653 if (lino > XFS_DIR2_MAX_SHORT_INUM)
2bd0ea18
NS
2654 i8++;
2655
2656 /*
aaca101b
DC
2657 * go onto next entry - we have to take entries with bad namelen
2658 * into account in no modify mode since we calculate size based
2659 * on next_sfep.
2bd0ea18
NS
2660 */
2661 ASSERT(no_modify || bad_sfnamelen == 0);
aaca101b
DC
2662 next_sfep = (struct xfs_dir2_sf_entry *)((__psint_t)sfep +
2663 (bad_sfnamelen
2664 ? xfs_dir3_sf_entsize(mp, sfp, namelen)
2665 : xfs_dir3_sf_entsize(mp, sfp, sfep->namelen)));
2bd0ea18
NS
2666 }
2667
a354abc8 2668 if (sfp->i8count != i8) {
2bd0ea18 2669 if (no_modify) {
5d1b7f0f
CH
2670 do_warn(_("would fix i8count in inode %" PRIu64 "\n"),
2671 ino);
2bd0ea18
NS
2672 } else {
2673 if (i8 == 0) {
aaca101b
DC
2674 struct xfs_dir2_sf_entry *tmp_sfep;
2675
2bd0ea18 2676 tmp_sfep = next_sfep;
494434d7 2677 process_sf_dir2_fixi8(mp, sfp, &tmp_sfep);
2bd0ea18
NS
2678 bytes_deleted +=
2679 (__psint_t)next_sfep -
2680 (__psint_t)tmp_sfep;
2681 next_sfep = tmp_sfep;
2682 } else
a354abc8 2683 sfp->i8count = i8;
2bd0ea18 2684 *ino_dirty = 1;
5d1b7f0f
CH
2685 do_warn(_("fixing i8count in inode %" PRIu64 "\n"),
2686 ino);
2bd0ea18
NS
2687 }
2688 }
2689
2690 /*
2691 * sync up sizes if required
2692 */
aaca101b 2693 if (*ino_dirty && bytes_deleted > 0) {
2bd0ea18
NS
2694 ASSERT(!no_modify);
2695 libxfs_idata_realloc(ip, -bytes_deleted, XFS_DATA_FORK);
2696 ip->i_d.di_size -= bytes_deleted;
2697 }
2698
2699 if (ip->i_d.di_size != ip->i_df.if_bytes) {
2700 ASSERT(ip->i_df.if_bytes == (xfs_fsize_t)
2701 ((__psint_t) next_sfep - (__psint_t) sfp));
2702 ip->i_d.di_size = (xfs_fsize_t)
2703 ((__psint_t) next_sfep - (__psint_t) sfp);
5d1b7f0f
CH
2704 do_warn(
2705 _("setting size to %" PRId64 " bytes to reflect junked entries\n"),
2bd0ea18
NS
2706 ip->i_d.di_size);
2707 *ino_dirty = 1;
2708 }
2709}
2710
2711/*
2556c98b 2712 * processes all reachable inodes in directories
2bd0ea18 2713 */
2556c98b
BN
2714static void
2715process_dir_inode(
2716 xfs_mount_t *mp,
575ca697 2717 xfs_agnumber_t agno,
2556c98b
BN
2718 ino_tree_node_t *irec,
2719 int ino_offset)
2bd0ea18 2720{
575ca697 2721 xfs_ino_t ino;
2bd0ea18
NS
2722 xfs_bmap_free_t flist;
2723 xfs_fsblock_t first;
2bd0ea18
NS
2724 xfs_inode_t *ip;
2725 xfs_trans_t *tp;
33165ec3 2726 dir_hash_tab_t *hashtab;
2556c98b 2727 int need_dot, committed;
2bd0ea18
NS
2728 int dirty, num_illegal, error, nres;
2729
575ca697
BN
2730 ino = XFS_AGINO_TO_INO(mp, agno, irec->ino_startnum + ino_offset);
2731
2bd0ea18 2732 /*
2bd0ea18
NS
2733 * open up directory inode, check all entries,
2734 * then call prune_dir_entries to remove all
2735 * remaining illegal directory entries.
2736 */
2737
f4ef1178 2738 ASSERT(!is_inode_refchecked(irec, ino_offset) || dotdot_update);
2bd0ea18 2739
2556c98b
BN
2740 error = libxfs_iget(mp, NULL, ino, 0, &ip, 0);
2741 if (error) {
2742 if (!no_modify)
5d1b7f0f
CH
2743 do_error(
2744 _("couldn't map inode %" PRIu64 ", err = %d\n"),
2556c98b
BN
2745 ino, error);
2746 else {
5d1b7f0f
CH
2747 do_warn(
2748 _("couldn't map inode %" PRIu64 ", err = %d\n"),
2556c98b 2749 ino, error);
2bd0ea18 2750 /*
2556c98b
BN
2751 * see below for what we're doing if this
2752 * is root. Why do we need to do this here?
2753 * to ensure that the root doesn't show up
2754 * as being disconnected in the no_modify case.
2bd0ea18 2755 */
2556c98b
BN
2756 if (mp->m_sb.sb_rootino == ino) {
2757 add_inode_reached(irec, 0);
2758 add_inode_ref(irec, 0);
2759 }
2bd0ea18
NS
2760 }
2761
f4ef1178 2762 add_inode_refchecked(irec, 0);
2556c98b
BN
2763 return;
2764 }
2bd0ea18 2765
2556c98b 2766 need_dot = dirty = num_illegal = 0;
64c54486 2767
2556c98b 2768 if (mp->m_sb.sb_rootino == ino) {
2bd0ea18 2769 /*
2556c98b
BN
2770 * mark root inode reached and bump up
2771 * link count for root inode to account
2772 * for '..' entry since the root inode is
2773 * never reached by a parent. we know
2774 * that root's '..' is always good --
2775 * guaranteed by phase 3 and/or below.
2bd0ea18 2776 */
2556c98b
BN
2777 add_inode_reached(irec, ino_offset);
2778 }
2779
f4ef1178 2780 add_inode_refchecked(irec, ino_offset);
2556c98b
BN
2781
2782 hashtab = dir_hash_init(ip->i_d.di_size);
2783
2784 /*
2785 * look for bogus entries
2786 */
2787 switch (ip->i_d.di_format) {
2bd0ea18
NS
2788 case XFS_DINODE_FMT_EXTENTS:
2789 case XFS_DINODE_FMT_BTREE:
2790 /*
2791 * also check for missing '.' in longform dirs.
2792 * missing .. entries are added if required when
2793 * the directory is connected to lost+found. but
2794 * we need to create '.' entries here.
2795 */
9a048535
DC
2796 longform_dir2_entry_check(mp, ino, ip,
2797 &num_illegal, &need_dot,
2798 irec, ino_offset,
2799 hashtab);
2bd0ea18 2800 break;
2556c98b 2801
2bd0ea18
NS
2802 case XFS_DINODE_FMT_LOCAL:
2803 tp = libxfs_trans_alloc(mp, 0);
2804 /*
2805 * using the remove reservation is overkill
2806 * since at most we'll only need to log the
2807 * inode but it's easier than wedging a
2808 * new define in ourselves.
2809 */
2810 nres = no_modify ? 0 : XFS_REMOVE_SPACE_RES(mp);
48ea6cb9
DC
2811 error = libxfs_trans_reserve(tp, &M_RES(mp)->tr_remove,
2812 nres, 0);
2bd0ea18
NS
2813 if (error)
2814 res_failed(error);
2815
2816 libxfs_trans_ijoin(tp, ip, 0);
2bd0ea18 2817
9a048535
DC
2818 shortform_dir2_entry_check(mp, ino, ip, &dirty,
2819 irec, ino_offset,
2820 hashtab);
2bd0ea18 2821
27527004 2822 ASSERT(dirty == 0 || (dirty && !no_modify));
2bd0ea18
NS
2823 if (dirty) {
2824 libxfs_trans_log_inode(tp, ip,
2825 XFS_ILOG_CORE | XFS_ILOG_DDATA);
2556c98b
BN
2826 libxfs_trans_commit(tp,
2827 XFS_TRANS_RELEASE_LOG_RES |
5e656dbb 2828 XFS_TRANS_SYNC);
2bd0ea18 2829 } else {
2556c98b
BN
2830 libxfs_trans_cancel(tp,
2831 XFS_TRANS_RELEASE_LOG_RES);
2bd0ea18
NS
2832 }
2833 break;
2556c98b 2834
2bd0ea18
NS
2835 default:
2836 break;
2556c98b
BN
2837 }
2838 dir_hash_done(hashtab);
2bd0ea18 2839
2556c98b
BN
2840 /*
2841 * if we have to create a .. for /, do it now *before*
2842 * we delete the bogus entries, otherwise the directory
2843 * could transform into a shortform dir which would
2844 * probably cause the simulation to choke. Even
2845 * if the illegal entries get shifted around, it's ok
2846 * because the entries are structurally intact and in
2847 * in hash-value order so the simulation won't get confused
2848 * if it has to move them around.
2849 */
2850 if (!no_modify && need_root_dotdot && ino == mp->m_sb.sb_rootino) {
2851 ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_LOCAL);
2bd0ea18 2852
2556c98b 2853 do_warn(_("recreating root directory .. entry\n"));
2bd0ea18 2854
2556c98b
BN
2855 tp = libxfs_trans_alloc(mp, 0);
2856 ASSERT(tp != NULL);
2bd0ea18 2857
2556c98b 2858 nres = XFS_MKDIR_SPACE_RES(mp, 2);
48ea6cb9 2859 error = libxfs_trans_reserve(tp, &M_RES(mp)->tr_mkdir, nres, 0);
2556c98b
BN
2860 if (error)
2861 res_failed(error);
2bd0ea18 2862
2556c98b 2863 libxfs_trans_ijoin(tp, ip, 0);
2bd0ea18 2864
56b2de80 2865 xfs_bmap_init(&flist, &first);
2bd0ea18 2866
5e656dbb
BN
2867 error = libxfs_dir_createname(tp, ip, &xfs_name_dotdot,
2868 ip->i_ino, &first, &flist, nres);
2556c98b 2869 if (error)
5d1b7f0f
CH
2870 do_error(
2871 _("can't make \"..\" entry in root inode %" PRIu64 ", createname error %d\n"), ino, error);
2bd0ea18 2872
2556c98b 2873 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
2bd0ea18 2874
5e656dbb 2875 error = libxfs_bmap_finish(&tp, &flist, &committed);
2556c98b
BN
2876 ASSERT(error == 0);
2877 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES |
5e656dbb 2878 XFS_TRANS_SYNC);
2bd0ea18 2879
2556c98b
BN
2880 need_root_dotdot = 0;
2881 } else if (need_root_dotdot && ino == mp->m_sb.sb_rootino) {
2882 do_warn(_("would recreate root directory .. entry\n"));
2883 }
2bd0ea18 2884
2556c98b
BN
2885 /*
2886 * if we need to create the '.' entry, do so only if
ff1f79a7 2887 * the directory is a longform dir. if it's been
2556c98b
BN
2888 * turned into a shortform dir, then the inode is ok
2889 * since shortform dirs have no '.' entry and the inode
2890 * has already been committed by prune_lf_dir_entry().
2891 */
2892 if (need_dot) {
2bd0ea18 2893 /*
2556c98b
BN
2894 * bump up our link count but don't
2895 * bump up the inode link count. chances
2896 * are good that even though we lost '.'
2897 * the inode link counts reflect '.' so
2898 * leave the inode link count alone and if
2899 * it turns out to be wrong, we'll catch
2900 * that in phase 7.
2bd0ea18 2901 */
2556c98b
BN
2902 add_inode_ref(irec, ino_offset);
2903
2904 if (no_modify) {
5d1b7f0f
CH
2905 do_warn(
2906 _("would create missing \".\" entry in dir ino %" PRIu64 "\n"),
2556c98b
BN
2907 ino);
2908 } else if (ip->i_d.di_format != XFS_DINODE_FMT_LOCAL) {
2bd0ea18 2909 /*
2556c98b 2910 * need to create . entry in longform dir.
2bd0ea18 2911 */
5d1b7f0f
CH
2912 do_warn(
2913 _("creating missing \".\" entry in dir ino %" PRIu64 "\n"), ino);
2bd0ea18 2914
2556c98b
BN
2915 tp = libxfs_trans_alloc(mp, 0);
2916 ASSERT(tp != NULL);
2bd0ea18 2917
2556c98b 2918 nres = XFS_MKDIR_SPACE_RES(mp, 1);
48ea6cb9
DC
2919 error = libxfs_trans_reserve(tp, &M_RES(mp)->tr_mkdir,
2920 nres, 0);
2556c98b
BN
2921 if (error)
2922 res_failed(error);
2bd0ea18 2923
2556c98b 2924 libxfs_trans_ijoin(tp, ip, 0);
2bd0ea18 2925
56b2de80 2926 xfs_bmap_init(&flist, &first);
2bd0ea18 2927
5e656dbb
BN
2928 error = libxfs_dir_createname(tp, ip, &xfs_name_dot,
2929 ip->i_ino, &first, &flist, nres);
2930 if (error)
5d1b7f0f
CH
2931 do_error(
2932 _("can't make \".\" entry in dir ino %" PRIu64 ", createname error %d\n"),
2556c98b 2933 ino, error);
2bd0ea18 2934
2556c98b 2935 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
2bd0ea18 2936
5e656dbb 2937 error = libxfs_bmap_finish(&tp, &flist, &committed);
2556c98b
BN
2938 ASSERT(error == 0);
2939 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES
5e656dbb 2940 |XFS_TRANS_SYNC);
2bd0ea18 2941 }
2bd0ea18 2942 }
dd2c21d2 2943 IRELE(ip);
2bd0ea18
NS
2944}
2945
2946/*
2947 * mark realtime bitmap and summary inodes as reached.
2948 * quota inode will be marked here as well
2949 */
8b8a6b02 2950static void
2bd0ea18
NS
2951mark_standalone_inodes(xfs_mount_t *mp)
2952{
2953 ino_tree_node_t *irec;
2954 int offset;
2955
1ae311d5 2956 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rbmino),
2bd0ea18
NS
2957 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rbmino));
2958
2959 ASSERT(irec != NULL);
2960
2961 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rbmino) -
2962 irec->ino_startnum;
2963
2964 add_inode_reached(irec, offset);
2965
1ae311d5 2966 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rsumino),
2bd0ea18
NS
2967 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rsumino));
2968
dfc130f3 2969 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rsumino) -
2bd0ea18
NS
2970 irec->ino_startnum;
2971
2972 ASSERT(irec != NULL);
2973
2974 add_inode_reached(irec, offset);
2975
2976 if (fs_quotas) {
2977 if (mp->m_sb.sb_uquotino
2978 && mp->m_sb.sb_uquotino != NULLFSINO) {
1ae311d5 2979 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp,
2bd0ea18
NS
2980 mp->m_sb.sb_uquotino),
2981 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_uquotino));
2982 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_uquotino)
2983 - irec->ino_startnum;
2984 add_inode_reached(irec, offset);
2985 }
b36eef04
NS
2986 if (mp->m_sb.sb_gquotino
2987 && mp->m_sb.sb_gquotino != NULLFSINO) {
1ae311d5 2988 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp,
b36eef04
NS
2989 mp->m_sb.sb_gquotino),
2990 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_gquotino));
2991 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_gquotino)
2bd0ea18
NS
2992 - irec->ino_startnum;
2993 add_inode_reached(irec, offset);
2994 }
0340d706
CS
2995 if (mp->m_sb.sb_pquotino
2996 && mp->m_sb.sb_pquotino != NULLFSINO) {
2997 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp,
2998 mp->m_sb.sb_pquotino),
2999 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_pquotino));
3000 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_pquotino)
3001 - irec->ino_startnum;
3002 add_inode_reached(irec, offset);
3003 }
2bd0ea18
NS
3004 }
3005}
3006
6c39a3cb
BN
3007static void
3008check_for_orphaned_inodes(
3009 xfs_mount_t *mp,
2556c98b 3010 xfs_agnumber_t agno,
6c39a3cb
BN
3011 ino_tree_node_t *irec)
3012{
3013 int i;
6c39a3cb
BN
3014 xfs_ino_t ino;
3015
3016 for (i = 0; i < XFS_INODES_PER_CHUNK; i++) {
3017 ASSERT(is_inode_confirmed(irec, i));
3018 if (is_inode_free(irec, i))
3019 continue;
3020
2556c98b
BN
3021 if (is_inode_reached(irec, i))
3022 continue;
3023
3024 ASSERT(inode_isadir(irec, i) ||
3025 num_inode_references(irec, i) == 0);
3026
3027 ino = XFS_AGINO_TO_INO(mp, agno, i + irec->ino_startnum);
3028 if (inode_isadir(irec, i))
5d1b7f0f 3029 do_warn(_("disconnected dir inode %" PRIu64 ", "), ino);
2556c98b 3030 else
5d1b7f0f 3031 do_warn(_("disconnected inode %" PRIu64 ", "), ino);
9a048535
DC
3032 if (!no_modify) {
3033 if (!orphanage_ino)
2556c98b
BN
3034 orphanage_ino = mk_orphanage(mp);
3035 do_warn(_("moving to %s\n"), ORPHANAGE);
3036 mv_orphanage(mp, ino, inode_isadir(irec, i));
3037 } else {
3038 do_warn(_("would move to %s\n"), ORPHANAGE);
6c39a3cb 3039 }
2556c98b
BN
3040 /*
3041 * for read-only case, even though the inode isn't
3042 * really reachable, set the flag (and bump our link
3043 * count) anyway to fool phase 7
3044 */
3045 add_inode_reached(irec, i);
6c39a3cb
BN
3046 }
3047}
3048
a1d54891 3049static void
2556c98b
BN
3050traverse_function(
3051 work_queue_t *wq,
3052 xfs_agnumber_t agno,
3053 void *arg)
a1d54891 3054{
2556c98b
BN
3055 ino_tree_node_t *irec;
3056 int i;
3057 prefetch_args_t *pf_args = arg;
3058
3059 wait_for_inode_prefetch(pf_args);
a1d54891
MV
3060
3061 if (verbose)
3062 do_log(_(" - agno = %d\n"), agno);
3063
2556c98b
BN
3064 for (irec = findfirst_inode_rec(agno); irec; irec = next_ino_rec(irec)) {
3065 if (irec->ino_isa_dir == 0)
3066 continue;
a1d54891 3067
004e18d4 3068 if (pf_args) {
2556c98b 3069 sem_post(&pf_args->ra_count);
004e18d4
DC
3070#ifdef XR_PF_TRACE
3071 sem_getvalue(&pf_args->ra_count, &i);
3072 pftrace(
3073 "processing inode chunk %p in AG %d (sem count = %d)",
3074 irec, agno, i);
3075#endif
3076 }
a1d54891 3077
2556c98b
BN
3078 for (i = 0; i < XFS_INODES_PER_CHUNK; i++) {
3079 if (inode_isadir(irec, i))
575ca697 3080 process_dir_inode(wq->mp, agno, irec, i);
a1d54891 3081 }
a1d54891 3082 }
2556c98b 3083 cleanup_inode_prefetch(pf_args);
a1d54891
MV
3084}
3085
575ca697
BN
3086static void
3087update_missing_dotdot_entries(
3088 xfs_mount_t *mp)
3089{
3090 dotdot_update_t *dir;
3091
3092 /*
3093 * these entries parents were updated, rebuild them again
3094 * set dotdot_update flag so processing routines do not count links
3095 */
3096 dotdot_update = 1;
1177f669
DC
3097 while (!list_empty(&dotdot_update_list)) {
3098 dir = list_entry(dotdot_update_list.prev, struct dotdot_update,
3099 list);
3100 list_del(&dir->list);
575ca697
BN
3101 process_dir_inode(mp, dir->agno, dir->irec, dir->ino_offset);
3102 free(dir);
3103 }
3104}
3105
a1d54891 3106static void
2556c98b 3107traverse_ags(
1164bde5 3108 struct xfs_mount *mp)
a1d54891 3109{
1164bde5 3110 do_inode_prefetch(mp, 0, traverse_function, false, true);
a1d54891
MV
3111}
3112
2bd0ea18
NS
3113void
3114phase6(xfs_mount_t *mp)
3115{
2bd0ea18 3116 ino_tree_node_t *irec;
2bd0ea18 3117 int i;
2bd0ea18 3118
dab9b8d6
BN
3119 memset(&zerocr, 0, sizeof(struct cred));
3120 memset(&zerofsx, 0, sizeof(struct fsxattr));
6c39a3cb 3121 orphanage_ino = 0;
2bd0ea18 3122
507f4e33 3123 do_log(_("Phase 6 - check inode connectivity...\n"));
2bd0ea18 3124
2bd0ea18
NS
3125 incore_ext_teardown(mp);
3126
0f012a4c 3127 add_ino_ex_data(mp);
2bd0ea18
NS
3128
3129 /*
3130 * verify existence of root directory - if we have to
3131 * make one, it's ok for the incore data structs not to
3132 * know about it since everything about it (and the other
3133 * inodes in its chunk if a new chunk was created) are ok
3134 */
3135 if (need_root_inode) {
9a048535 3136 if (!no_modify) {
507f4e33 3137 do_warn(_("reinitializing root directory\n"));
2bd0ea18
NS
3138 mk_root_dir(mp);
3139 need_root_inode = 0;
3140 need_root_dotdot = 0;
3141 } else {
507f4e33 3142 do_warn(_("would reinitialize root directory\n"));
2bd0ea18
NS
3143 }
3144 }
3145
3146 if (need_rbmino) {
3147 if (!no_modify) {
507f4e33 3148 do_warn(_("reinitializing realtime bitmap inode\n"));
2bd0ea18
NS
3149 mk_rbmino(mp);
3150 need_rbmino = 0;
3151 } else {
507f4e33 3152 do_warn(_("would reinitialize realtime bitmap inode\n"));
2bd0ea18
NS
3153 }
3154 }
3155
3156 if (need_rsumino) {
3157 if (!no_modify) {
507f4e33 3158 do_warn(_("reinitializing realtime summary inode\n"));
2bd0ea18
NS
3159 mk_rsumino(mp);
3160 need_rsumino = 0;
3161 } else {
507f4e33 3162 do_warn(_("would reinitialize realtime summary inode\n"));
2bd0ea18
NS
3163 }
3164 }
3165
3166 if (!no_modify) {
3167 do_log(
507f4e33 3168_(" - resetting contents of realtime bitmap and summary inodes\n"));
2bd0ea18
NS
3169 if (fill_rbmino(mp)) {
3170 do_warn(
507f4e33 3171 _("Warning: realtime bitmap may be inconsistent\n"));
2bd0ea18
NS
3172 }
3173
3174 if (fill_rsumino(mp)) {
3175 do_warn(
507f4e33 3176 _("Warning: realtime bitmap may be inconsistent\n"));
2bd0ea18
NS
3177 }
3178 }
3179
2bd0ea18
NS
3180 mark_standalone_inodes(mp);
3181
69ec88b5 3182 do_log(_(" - traversing filesystem ...\n"));
2bd0ea18 3183
1ae311d5 3184 irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino),
2bd0ea18
NS
3185 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino));
3186
3187 /*
3188 * we always have a root inode, even if it's free...
3189 * if the root is free, forget it, lost+found is already gone
3190 */
3191 if (is_inode_free(irec, 0) || !inode_isadir(irec, 0)) {
3192 need_root_inode = 1;
3193 }
3194
3195 /*
2556c98b 3196 * then process all inodes by walking incore inode tree
2bd0ea18 3197 */
2556c98b 3198 traverse_ags(mp);
2bd0ea18 3199
575ca697
BN
3200 /*
3201 * any directories that had updated ".." entries, rebuild them now
3202 */
3203 update_missing_dotdot_entries(mp);
3204
69ec88b5
BN
3205 do_log(_(" - traversal finished ...\n"));
3206 do_log(_(" - moving disconnected inodes to %s ...\n"),
6c39a3cb 3207 ORPHANAGE);
2bd0ea18
NS
3208
3209 /*
3210 * move all disconnected inodes to the orphanage
3211 */
3212 for (i = 0; i < glob_agcount; i++) {
3213 irec = findfirst_inode_rec(i);
2bd0ea18 3214 while (irec != NULL) {
2556c98b 3215 check_for_orphaned_inodes(mp, i, irec);
2bd0ea18
NS
3216 irec = next_ino_rec(irec);
3217 }
3218 }
3219}