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