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