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