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