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