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