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