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