]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - repair/phase6.c
Minor fix up in xfs_db man page
[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"
24#include "dir.h"
25#include "dir2.h"
2bd0ea18
NS
26#include "protos.h"
27#include "err_protos.h"
28#include "dinode.h"
cb5b3ef4 29#include "prefetch.h"
06fbdda9 30#include "progress.h"
2556c98b 31#include "threads.h"
2bd0ea18
NS
32#include "versions.h"
33
6c39a3cb
BN
34static struct cred zerocr;
35static struct fsxattr zerofsx;
36static xfs_ino_t orphanage_ino;
2bd0ea18
NS
37
38/*
39 * Data structures and routines to keep track of directory entries
33165ec3
BN
40 * and whether their leaf entry has been seen. Also used for name
41 * duplicate checking and rebuilding step if required.
2bd0ea18
NS
42 */
43typedef struct dir_hash_ent {
33165ec3
BN
44 struct dir_hash_ent *nextbyaddr; /* next in addr bucket */
45 struct dir_hash_ent *nextbyhash; /* next in name bucket */
46 struct dir_hash_ent *nextbyorder; /* next in order added */
47 xfs_dahash_t hashval; /* hash value of name */
48 __uint32_t address; /* offset of data entry */
49 xfs_ino_t inum; /* inode num of entry */
50 short junkit; /* name starts with / */
51 short seen; /* have seen leaf entry */
52 int namelen; /* length of name */
53 uchar_t *name; /* pointer to name (no NULL) */
2bd0ea18
NS
54} dir_hash_ent_t;
55
56typedef struct dir_hash_tab {
33165ec3
BN
57 int size; /* size of hash tables */
58 int names_duped; /* 1 = ent names malloced */
59 dir_hash_ent_t *first; /* ptr to first added entry */
60 dir_hash_ent_t *last; /* ptr to last added entry */
61 dir_hash_ent_t **byhash; /* ptr to name hash buckets */
62 dir_hash_ent_t **byaddr; /* ptr to addr hash buckets */
2bd0ea18 63} dir_hash_tab_t;
33165ec3 64
2bd0ea18 65#define DIR_HASH_TAB_SIZE(n) \
33165ec3 66 (sizeof(dir_hash_tab_t) + (sizeof(dir_hash_ent_t *) * (n) * 2))
2bd0ea18
NS
67#define DIR_HASH_FUNC(t,a) ((a) % (t)->size)
68
69/*
70 * Track the contents of the freespace table in a directory.
71 */
72typedef struct freetab {
9d7d6241
NS
73 int naents; /* expected number of data blocks */
74 int nents; /* number of data blocks processed */
2bd0ea18
NS
75 struct freetab_ent {
76 xfs_dir2_data_off_t v;
77 short s;
78 } ents[1];
79} freetab_t;
80#define FREETAB_SIZE(n) \
81 (offsetof(freetab_t, ents) + (sizeof(struct freetab_ent) * (n)))
82
83#define DIR_HASH_CK_OK 0
84#define DIR_HASH_CK_DUPLEAF 1
85#define DIR_HASH_CK_BADHASH 2
86#define DIR_HASH_CK_NODATA 3
87#define DIR_HASH_CK_NOLEAF 4
88#define DIR_HASH_CK_BADSTALE 5
507f4e33 89#define DIR_HASH_CK_TOTAL 6
2bd0ea18 90
33165ec3
BN
91/*
92 * Returns 0 if the name already exists (ie. a duplicate)
93 */
94static int
2bd0ea18
NS
95dir_hash_add(
96 dir_hash_tab_t *hashtab,
0f012a4c 97 __uint32_t addr,
33165ec3
BN
98 xfs_ino_t inum,
99 int namelen,
100 uchar_t *name)
2bd0ea18 101{
33165ec3
BN
102 xfs_dahash_t hash = 0;
103 int byaddr;
104 int byhash = 0;
2bd0ea18 105 dir_hash_ent_t *p;
33165ec3
BN
106 int dup;
107 short junk;
0f012a4c 108
33165ec3 109 ASSERT(!hashtab->names_duped);
0f012a4c 110
33165ec3
BN
111 junk = name[0] == '/';
112 byaddr = DIR_HASH_FUNC(hashtab, addr);
113 dup = 0;
2bd0ea18 114
33165ec3
BN
115 if (!junk) {
116 hash = libxfs_da_hashname(name, namelen);
117 byhash = DIR_HASH_FUNC(hashtab, hash);
118
0f012a4c 119 /*
33165ec3
BN
120 * search hash bucket for existing name.
121 */
122 for (p = hashtab->byhash[byhash]; p; p = p->nextbyhash) {
123 if (p->hashval == hash && p->namelen == namelen) {
124 if (memcmp(p->name, name, namelen) == 0) {
125 dup = 1;
126 junk = 1;
127 break;
128 }
129 }
130 }
131 }
0f012a4c 132
507f4e33
NS
133 if ((p = malloc(sizeof(*p))) == NULL)
134 do_error(_("malloc failed in dir_hash_add (%u bytes)\n"),
2bd0ea18 135 sizeof(*p));
0f012a4c 136
33165ec3
BN
137 p->nextbyaddr = hashtab->byaddr[byaddr];
138 hashtab->byaddr[byaddr] = p;
0f012a4c 139 if (hashtab->last)
33165ec3
BN
140 hashtab->last->nextbyorder = p;
141 else
142 hashtab->first = p;
143 p->nextbyorder = NULL;
144 hashtab->last = p;
0f012a4c 145
33165ec3
BN
146 if (!(p->junkit = junk)) {
147 p->hashval = hash;
148 p->nextbyhash = hashtab->byhash[byhash];
149 hashtab->byhash[byhash] = p;
150 }
151 p->address = addr;
152 p->inum = inum;
2bd0ea18 153 p->seen = 0;
33165ec3
BN
154 p->namelen = namelen;
155 p->name = name;
0f012a4c 156
33165ec3 157 return !dup;
2bd0ea18
NS
158}
159
33165ec3 160/*
0f012a4c 161 * checks to see if any data entries are not in the leaf blocks
33165ec3 162 */
2bd0ea18
NS
163static int
164dir_hash_unseen(
165 dir_hash_tab_t *hashtab)
166{
167 int i;
168 dir_hash_ent_t *p;
169
170 for (i = 0; i < hashtab->size; i++) {
33165ec3 171 for (p = hashtab->byaddr[i]; p; p = p->nextbyaddr) {
2bd0ea18
NS
172 if (p->seen == 0)
173 return 1;
174 }
175 }
176 return 0;
177}
178
179static int
180dir_hash_check(
181 dir_hash_tab_t *hashtab,
182 xfs_inode_t *ip,
183 int seeval)
184{
507f4e33
NS
185 static char *seevalstr[DIR_HASH_CK_TOTAL];
186 static int done;
187
188 if (!done) {
189 seevalstr[DIR_HASH_CK_OK] = _("ok");
190 seevalstr[DIR_HASH_CK_DUPLEAF] = _("duplicate leaf");
191 seevalstr[DIR_HASH_CK_BADHASH] = _("hash value mismatch");
192 seevalstr[DIR_HASH_CK_NODATA] = _("no data entry");
193 seevalstr[DIR_HASH_CK_NOLEAF] = _("no leaf entry");
194 seevalstr[DIR_HASH_CK_BADSTALE] = _("bad stale count");
195 done = 1;
196 }
2bd0ea18
NS
197
198 if (seeval == DIR_HASH_CK_OK && dir_hash_unseen(hashtab))
199 seeval = DIR_HASH_CK_NOLEAF;
200 if (seeval == DIR_HASH_CK_OK)
201 return 0;
507f4e33
NS
202 do_warn(_("bad hash table for directory inode %llu (%s): "),
203 ip->i_ino, seevalstr[seeval]);
2bd0ea18 204 if (!no_modify)
507f4e33 205 do_warn(_("rebuilding\n"));
2bd0ea18 206 else
507f4e33 207 do_warn(_("would rebuild\n"));
2bd0ea18
NS
208 return 1;
209}
210
211static void
212dir_hash_done(
213 dir_hash_tab_t *hashtab)
214{
215 int i;
216 dir_hash_ent_t *n;
217 dir_hash_ent_t *p;
218
219 for (i = 0; i < hashtab->size; i++) {
33165ec3
BN
220 for (p = hashtab->byaddr[i]; p; p = n) {
221 n = p->nextbyaddr;
222 if (hashtab->names_duped)
223 free(p->name);
2bd0ea18
NS
224 free(p);
225 }
226 }
227 free(hashtab);
228}
229
230static dir_hash_tab_t *
231dir_hash_init(
232 xfs_fsize_t size)
233{
234 dir_hash_tab_t *hashtab;
235 int hsize;
236
237 hsize = size / (16 * 4);
2556c98b
BN
238 if (hsize > 65536)
239 hsize = 63336;
2bd0ea18
NS
240 else if (hsize < 16)
241 hsize = 16;
507f4e33
NS
242 if ((hashtab = calloc(DIR_HASH_TAB_SIZE(hsize), 1)) == NULL)
243 do_error(_("calloc failed in dir_hash_init\n"));
2bd0ea18 244 hashtab->size = hsize;
0f012a4c 245 hashtab->byhash = (dir_hash_ent_t**)((char *)hashtab +
33165ec3 246 sizeof(dir_hash_tab_t));
0f012a4c 247 hashtab->byaddr = (dir_hash_ent_t**)((char *)hashtab +
33165ec3 248 sizeof(dir_hash_tab_t) + sizeof(dir_hash_ent_t*) * hsize);
2bd0ea18
NS
249 return hashtab;
250}
251
252static int
253dir_hash_see(
254 dir_hash_tab_t *hashtab,
255 xfs_dahash_t hash,
256 xfs_dir2_dataptr_t addr)
257{
258 int i;
259 dir_hash_ent_t *p;
260
261 i = DIR_HASH_FUNC(hashtab, addr);
33165ec3
BN
262 for (p = hashtab->byaddr[i]; p; p = p->nextbyaddr) {
263 if (p->address != addr)
2bd0ea18
NS
264 continue;
265 if (p->seen)
266 return DIR_HASH_CK_DUPLEAF;
33165ec3 267 if (p->junkit == 0 && p->hashval != hash)
2bd0ea18
NS
268 return DIR_HASH_CK_BADHASH;
269 p->seen = 1;
270 return DIR_HASH_CK_OK;
271 }
272 return DIR_HASH_CK_NODATA;
273}
274
33165ec3
BN
275/*
276 * checks to make sure leafs match a data entry, and that the stale
277 * count is valid.
278 */
2bd0ea18
NS
279static int
280dir_hash_see_all(
281 dir_hash_tab_t *hashtab,
282 xfs_dir2_leaf_entry_t *ents,
283 int count,
284 int stale)
285{
286 int i;
287 int j;
288 int rval;
289
290 for (i = j = 0; i < count; i++) {
291 if (INT_GET(ents[i].address, ARCH_CONVERT) == XFS_DIR2_NULL_DATAPTR) {
292 j++;
293 continue;
294 }
295 rval = dir_hash_see(hashtab, INT_GET(ents[i].hashval, ARCH_CONVERT), INT_GET(ents[i].address, ARCH_CONVERT));
296 if (rval != DIR_HASH_CK_OK)
297 return rval;
298 }
299 return j == stale ? DIR_HASH_CK_OK : DIR_HASH_CK_BADSTALE;
300}
301
64c54486 302/*
33165ec3
BN
303 * Convert name pointers into locally allocated memory.
304 * This must only be done after all the entries have been added.
64c54486 305 */
33165ec3
BN
306static void
307dir_hash_dup_names(dir_hash_tab_t *hashtab)
64c54486 308{
33165ec3
BN
309 uchar_t *name;
310 dir_hash_ent_t *p;
0f012a4c 311
33165ec3
BN
312 if (hashtab->names_duped)
313 return;
0f012a4c 314
33165ec3
BN
315 for (p = hashtab->first; p; p = p->nextbyorder) {
316 name = malloc(p->namelen);
317 memcpy(name, p->name, p->namelen);
318 p->name = name;
64c54486 319 }
33165ec3 320 hashtab->names_duped = 1;
64c54486
BN
321}
322
2bd0ea18
NS
323/*
324 * Version 1 or 2 directory routine wrappers
325*/
326static void
327dir_init(xfs_mount_t *mp, xfs_trans_t *tp, xfs_inode_t *dp, xfs_inode_t *pdp)
328{
329 if (XFS_SB_VERSION_HASDIRV2(&mp->m_sb))
330 libxfs_dir2_init(tp, dp, pdp);
331 else
332 libxfs_dir_init(tp, dp, pdp);
333}
334
335static int
336dir_createname(xfs_mount_t *mp, xfs_trans_t *tp, xfs_inode_t *pip,
337 char *name, int namelen, xfs_ino_t inum, xfs_fsblock_t *first,
338 xfs_bmap_free_t *flist, xfs_extlen_t total)
339{
340 if (XFS_SB_VERSION_HASDIRV2(&mp->m_sb))
04d3ada9
BN
341 return libxfs_dir2_createname(tp, pip,
342 (uchar_t *)name, namelen,
2bd0ea18
NS
343 inum, first, flist, total);
344 else
04d3ada9
BN
345 return libxfs_dir_createname(tp, pip,
346 (uchar_t *)name, namelen,
2bd0ea18
NS
347 inum, first, flist, total);
348}
349
350static int
351dir_lookup(xfs_mount_t *mp, xfs_trans_t *tp, xfs_inode_t *dp, char *name,
352 int namelen, xfs_ino_t *inum)
353{
354 if (XFS_SB_VERSION_HASDIRV2(&mp->m_sb))
04d3ada9
BN
355 return libxfs_dir2_lookup(tp, dp,
356 (uchar_t *)name, namelen, inum);
2bd0ea18 357 else
04d3ada9
BN
358 return libxfs_dir_lookup(tp, dp,
359 (uchar_t *)name, namelen, inum);
2bd0ea18
NS
360}
361
362static int
363dir_replace(xfs_mount_t *mp, xfs_trans_t *tp, xfs_inode_t *dp, char *name,
364 int namelen, xfs_ino_t inum, xfs_fsblock_t *firstblock,
365 xfs_bmap_free_t *flist, xfs_extlen_t total)
366{
367 if (XFS_SB_VERSION_HASDIRV2(&mp->m_sb))
04d3ada9
BN
368 return libxfs_dir2_replace(tp, dp,
369 (uchar_t *)name, namelen, inum,
2bd0ea18
NS
370 firstblock, flist, total);
371 else
04d3ada9
BN
372 return libxfs_dir_replace(tp, dp,
373 (uchar_t *)name, namelen, inum,
2bd0ea18
NS
374 firstblock, flist, total);
375}
376
377static int
378dir_bogus_removename(xfs_mount_t *mp, xfs_trans_t *tp, xfs_inode_t *dp,
379 char *name, xfs_fsblock_t *firstblock, xfs_bmap_free_t *flist,
380 xfs_extlen_t total, xfs_dahash_t hashval, int namelen)
381{
382 if (XFS_SB_VERSION_HASDIRV2(&mp->m_sb))
04d3ada9
BN
383 return libxfs_dir2_bogus_removename(tp, dp,
384 (uchar_t *)name, firstblock,
2bd0ea18
NS
385 flist, total, hashval, namelen);
386 else
04d3ada9
BN
387 return libxfs_dir_bogus_removename(tp, dp,
388 (uchar_t *)name, firstblock,
2bd0ea18
NS
389 flist, total, hashval, namelen);
390}
391
392
393static void
394res_failed(
395 int err)
396{
397 if (err == ENOSPC) {
507f4e33 398 do_error(_("ran out of disk space!\n"));
2bd0ea18 399 } else
507f4e33 400 do_error(_("xfs_trans_reserve returned %d\n"), err);
2bd0ea18
NS
401}
402
403void
404mk_rbmino(xfs_mount_t *mp)
405{
406 xfs_trans_t *tp;
407 xfs_inode_t *ip;
408 xfs_bmbt_irec_t *ep;
409 xfs_fsblock_t first;
410 int i;
411 int nmap;
412 int committed;
413 int error;
414 xfs_bmap_free_t flist;
415 xfs_dfiloff_t bno;
416 xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP];
417
418 /*
419 * first set up inode
420 */
421 tp = libxfs_trans_alloc(mp, 0);
422
27527004 423 if ((i = libxfs_trans_reserve(tp, 10, 0, 0, 0, 0)))
2bd0ea18
NS
424 res_failed(i);
425
46eca962 426 error = libxfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, 0, &ip);
2bd0ea18 427 if (error) {
507f4e33
NS
428 do_error(
429 _("couldn't iget realtime bitmap inode -- error - %d\n"),
2bd0ea18
NS
430 error);
431 }
432
433 bzero(&ip->i_d, sizeof(xfs_dinode_core_t));
434
435 ip->i_d.di_magic = XFS_DINODE_MAGIC;
322f2a29 436 ip->i_d.di_mode = S_IFREG;
2bd0ea18
NS
437 ip->i_d.di_version = XFS_DINODE_VERSION_1;
438 ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
439 ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
440
441 ip->i_d.di_nlink = 1; /* account for sb ptr */
442
443 /*
444 * now the ifork
445 */
446 ip->i_df.if_flags = XFS_IFEXTENTS;
447 ip->i_df.if_bytes = ip->i_df.if_real_bytes = 0;
448 ip->i_df.if_u1.if_extents = NULL;
449
450 ip->i_d.di_size = mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize;
451
452 /*
453 * commit changes
454 */
455 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
456 libxfs_trans_ihold(tp, ip);
457 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC, NULL);
458
459 /*
460 * then allocate blocks for file and fill with zeroes (stolen
461 * from mkfs)
462 */
463 tp = libxfs_trans_alloc(mp, 0);
27527004
NS
464 if ((error = libxfs_trans_reserve(tp, mp->m_sb.sb_rbmblocks +
465 (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1), 0, 0, 0, 0)))
2bd0ea18
NS
466 res_failed(error);
467
468 libxfs_trans_ijoin(tp, ip, 0);
469 bno = 0;
470 XFS_BMAP_INIT(&flist, &first);
471 while (bno < mp->m_sb.sb_rbmblocks) {
472 nmap = XFS_BMAP_MAX_NMAP;
473 error = libxfs_bmapi(tp, ip, bno,
474 (xfs_extlen_t)(mp->m_sb.sb_rbmblocks - bno),
475 XFS_BMAPI_WRITE, &first, mp->m_sb.sb_rbmblocks,
476 map, &nmap, &flist);
477 if (error) {
507f4e33
NS
478 do_error(
479 _("couldn't allocate realtime bitmap, error = %d\n"),
2bd0ea18
NS
480 error);
481 }
482 for (i = 0, ep = map; i < nmap; i++, ep++) {
483 libxfs_device_zero(mp->m_dev,
484 XFS_FSB_TO_DADDR(mp, ep->br_startblock),
485 XFS_FSB_TO_BB(mp, ep->br_blockcount));
486 bno += ep->br_blockcount;
487 }
488 }
489 error = libxfs_bmap_finish(&tp, &flist, first, &committed);
490 if (error) {
491 do_error(
507f4e33 492 _("allocation of the realtime bitmap failed, error = %d\n"),
2bd0ea18
NS
493 error);
494 }
495 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC, 0);
496}
497
498int
499fill_rbmino(xfs_mount_t *mp)
500{
501 xfs_buf_t *bp;
502 xfs_trans_t *tp;
503 xfs_inode_t *ip;
504 xfs_rtword_t *bmp;
505 xfs_fsblock_t first;
506 int nmap;
507 int error;
508 xfs_dfiloff_t bno;
509 xfs_bmbt_irec_t map;
510
511 bmp = btmcompute;
512 bno = 0;
513
514 tp = libxfs_trans_alloc(mp, 0);
515
27527004 516 if ((error = libxfs_trans_reserve(tp, 10, 0, 0, 0, 0)))
2bd0ea18
NS
517 res_failed(error);
518
46eca962 519 error = libxfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, 0, &ip);
2bd0ea18 520 if (error) {
507f4e33
NS
521 do_error(
522 _("couldn't iget realtime bitmap inode -- error - %d\n"),
2bd0ea18
NS
523 error);
524 }
525
526 while (bno < mp->m_sb.sb_rbmblocks) {
527 /*
528 * fill the file one block at a time
529 */
530 nmap = 1;
531 error = libxfs_bmapi(tp, ip, bno, 1, XFS_BMAPI_WRITE,
532 &first, 1, &map, &nmap, NULL);
533 if (error || nmap != 1) {
534 do_error(
507f4e33 535 _("couldn't map realtime bitmap block %llu, error = %d\n"),
2bd0ea18
NS
536 bno, error);
537 }
538
539 ASSERT(map.br_startblock != HOLESTARTBLOCK);
540
541 error = libxfs_trans_read_buf(
542 mp, tp, mp->m_dev,
dfc130f3 543 XFS_FSB_TO_DADDR(mp, map.br_startblock),
2bd0ea18
NS
544 XFS_FSB_TO_BB(mp, 1), 1, &bp);
545
546 if (error) {
547 do_warn(
507f4e33 548_("can't access block %llu (fsbno %llu) of realtime bitmap inode %llu\n"),
2bd0ea18
NS
549 bno, map.br_startblock, mp->m_sb.sb_rbmino);
550 return(1);
551 }
552
553 bcopy(bmp, XFS_BUF_PTR(bp), mp->m_sb.sb_blocksize);
554
555 libxfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
556
557 bmp = (xfs_rtword_t *)((__psint_t) bmp + mp->m_sb.sb_blocksize);
558 bno++;
559 }
560
561 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC, 0);
2bd0ea18
NS
562 return(0);
563}
564
565int
566fill_rsumino(xfs_mount_t *mp)
567{
568 xfs_buf_t *bp;
569 xfs_trans_t *tp;
570 xfs_inode_t *ip;
571 xfs_suminfo_t *smp;
572 xfs_fsblock_t first;
573 int nmap;
574 int error;
575 xfs_dfiloff_t bno;
576 xfs_dfiloff_t end_bno;
577 xfs_bmbt_irec_t map;
578
579 smp = sumcompute;
580 bno = 0;
581 end_bno = mp->m_rsumsize >> mp->m_sb.sb_blocklog;
582
583 tp = libxfs_trans_alloc(mp, 0);
584
27527004 585 if ((error = libxfs_trans_reserve(tp, 10, 0, 0, 0, 0)))
2bd0ea18
NS
586 res_failed(error);
587
46eca962 588 error = libxfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino, 0, 0, &ip);
2bd0ea18 589 if (error) {
507f4e33
NS
590 do_error(
591 _("couldn't iget realtime summary inode -- error - %d\n"),
2bd0ea18
NS
592 error);
593 }
594
595 while (bno < end_bno) {
596 /*
597 * fill the file one block at a time
598 */
599 nmap = 1;
600 error = libxfs_bmapi(tp, ip, bno, 1, XFS_BMAPI_WRITE,
601 &first, 1, &map, &nmap, NULL);
602 if (error || nmap != 1) {
603 do_error(
507f4e33 604 _("couldn't map realtime summary inode block %llu, error = %d\n"),
2bd0ea18
NS
605 bno, error);
606 }
607
608 ASSERT(map.br_startblock != HOLESTARTBLOCK);
609
610 error = libxfs_trans_read_buf(
611 mp, tp, mp->m_dev,
dfc130f3 612 XFS_FSB_TO_DADDR(mp, map.br_startblock),
2bd0ea18
NS
613 XFS_FSB_TO_BB(mp, 1), 1, &bp);
614
615 if (error) {
616 do_warn(
507f4e33 617_("can't access block %llu (fsbno %llu) of realtime summary inode %llu\n"),
2bd0ea18
NS
618 bno, map.br_startblock, mp->m_sb.sb_rsumino);
619 return(1);
620 }
621
622 bcopy(smp, XFS_BUF_PTR(bp), mp->m_sb.sb_blocksize);
623
624 libxfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
625
626 smp = (xfs_suminfo_t *)((__psint_t)smp + mp->m_sb.sb_blocksize);
627 bno++;
628 }
629
630 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC, 0);
2bd0ea18
NS
631 return(0);
632}
633
634void
635mk_rsumino(xfs_mount_t *mp)
636{
637 xfs_trans_t *tp;
638 xfs_inode_t *ip;
639 xfs_bmbt_irec_t *ep;
640 xfs_fsblock_t first;
641 int i;
642 int nmap;
643 int committed;
644 int error;
645 int nsumblocks;
646 xfs_bmap_free_t flist;
647 xfs_dfiloff_t bno;
648 xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP];
649
650 /*
651 * first set up inode
652 */
653 tp = libxfs_trans_alloc(mp, 0);
654
27527004
NS
655 if ((i = libxfs_trans_reserve(tp, 10, XFS_ICHANGE_LOG_RES(mp), 0,
656 XFS_TRANS_PERM_LOG_RES, XFS_MKDIR_LOG_COUNT)))
2bd0ea18
NS
657 res_failed(i);
658
46eca962 659 error = libxfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino, 0, 0, &ip);
2bd0ea18 660 if (error) {
507f4e33
NS
661 do_error(
662 _("couldn't iget realtime summary inode -- error - %d\n"),
2bd0ea18
NS
663 error);
664 }
665
666 bzero(&ip->i_d, sizeof(xfs_dinode_core_t));
667
668 ip->i_d.di_magic = XFS_DINODE_MAGIC;
322f2a29 669 ip->i_d.di_mode = S_IFREG;
2bd0ea18
NS
670 ip->i_d.di_version = XFS_DINODE_VERSION_1;
671 ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
672 ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
673
674 ip->i_d.di_nlink = 1; /* account for sb ptr */
675
676 /*
677 * now the ifork
678 */
679 ip->i_df.if_flags = XFS_IFEXTENTS;
680 ip->i_df.if_bytes = ip->i_df.if_real_bytes = 0;
681 ip->i_df.if_u1.if_extents = NULL;
682
683 ip->i_d.di_size = mp->m_rsumsize;
684
685 /*
686 * commit changes
687 */
688 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
689 libxfs_trans_ihold(tp, ip);
690 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC, 0);
691
692 /*
693 * then allocate blocks for file and fill with zeroes (stolen
694 * from mkfs)
695 */
696 tp = libxfs_trans_alloc(mp, 0);
697 XFS_BMAP_INIT(&flist, &first);
698
699 nsumblocks = mp->m_rsumsize >> mp->m_sb.sb_blocklog;
27527004 700 if ((error = libxfs_trans_reserve(tp,
2bd0ea18
NS
701 mp->m_sb.sb_rbmblocks +
702 (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1),
703 BBTOB(128), 0, XFS_TRANS_PERM_LOG_RES,
27527004 704 XFS_DEFAULT_PERM_LOG_COUNT)))
2bd0ea18
NS
705 res_failed(error);
706
707 libxfs_trans_ijoin(tp, ip, 0);
708 bno = 0;
709 XFS_BMAP_INIT(&flist, &first);
710 while (bno < nsumblocks) {
711 nmap = XFS_BMAP_MAX_NMAP;
712 error = libxfs_bmapi(tp, ip, bno,
713 (xfs_extlen_t)(nsumblocks - bno),
714 XFS_BMAPI_WRITE, &first, nsumblocks,
715 map, &nmap, &flist);
716 if (error) {
717 do_error(
507f4e33 718 _("couldn't allocate realtime summary inode, error = %d\n"),
2bd0ea18
NS
719 error);
720 }
721 for (i = 0, ep = map; i < nmap; i++, ep++) {
722 libxfs_device_zero(mp->m_dev,
723 XFS_FSB_TO_DADDR(mp, ep->br_startblock),
724 XFS_FSB_TO_BB(mp, ep->br_blockcount));
2bd0ea18
NS
725 bno += ep->br_blockcount;
726 }
727 }
728 error = libxfs_bmap_finish(&tp, &flist, first, &committed);
729 if (error) {
730 do_error(
507f4e33 731 _("allocation of the realtime summary ino failed, error = %d\n"),
2bd0ea18
NS
732 error);
733 }
734 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC, 0);
735}
736
737/*
738 * makes a new root directory.
739 */
740void
741mk_root_dir(xfs_mount_t *mp)
742{
743 xfs_trans_t *tp;
744 xfs_inode_t *ip;
745 int i;
746 int error;
747 const mode_t mode = 0755;
69ec88b5 748 ino_tree_node_t *irec;
2bd0ea18
NS
749
750 tp = libxfs_trans_alloc(mp, 0);
751 ip = NULL;
752
27527004
NS
753 if ((i = libxfs_trans_reserve(tp, 10, XFS_ICHANGE_LOG_RES(mp), 0,
754 XFS_TRANS_PERM_LOG_RES, XFS_MKDIR_LOG_COUNT)))
2bd0ea18
NS
755 res_failed(i);
756
46eca962 757 error = libxfs_trans_iget(mp, tp, mp->m_sb.sb_rootino, 0, 0, &ip);
2bd0ea18 758 if (error) {
507f4e33 759 do_error(_("could not iget root inode -- error - %d\n"), error);
2bd0ea18
NS
760 }
761
762 /*
763 * take care of the core -- initialization from xfs_ialloc()
764 */
765 bzero(&ip->i_d, sizeof(xfs_dinode_core_t));
766
767 ip->i_d.di_magic = XFS_DINODE_MAGIC;
322f2a29 768 ip->i_d.di_mode = (__uint16_t) mode|S_IFDIR;
2bd0ea18
NS
769 ip->i_d.di_version = XFS_DINODE_VERSION_1;
770 ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
771 ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
772
773 ip->i_d.di_nlink = 1; /* account for . */
774
775 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
776
777 /*
778 * now the ifork
779 */
780 ip->i_df.if_flags = XFS_IFEXTENTS;
781 ip->i_df.if_bytes = ip->i_df.if_real_bytes = 0;
782 ip->i_df.if_u1.if_extents = NULL;
783
784 mp->m_rootip = ip;
785
786 /*
787 * initialize the directory
788 */
789 dir_init(mp, tp, ip, ip);
790
791 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC, 0);
69ec88b5
BN
792
793 irec = find_inode_rec(XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino),
794 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino));
795 set_inode_isadir(irec, XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino) -
796 irec->ino_startnum);
2bd0ea18
NS
797}
798
799/*
800 * orphanage name == lost+found
801 */
802xfs_ino_t
803mk_orphanage(xfs_mount_t *mp)
804{
805 xfs_ino_t ino;
806 xfs_trans_t *tp;
807 xfs_inode_t *ip;
808 xfs_inode_t *pip;
809 xfs_fsblock_t first;
810 int i;
811 int committed;
812 int error;
813 xfs_bmap_free_t flist;
814 const int mode = 0755;
2bd0ea18
NS
815 int nres;
816
6c39a3cb
BN
817 /*
818 * check for an existing lost+found first, if it exists, return
819 * it's inode. Otherwise, we can create it. Bad lost+found inodes
820 * would have been cleared in phase3 and phase4.
821 */
822
823 if ((i = libxfs_iget(mp, NULL, mp->m_sb.sb_rootino, 0, &pip, 0)))
824 do_error(_("%d - couldn't iget root inode to obtain %s\n"),
825 i, ORPHANAGE);
826
827 if (dir_lookup(mp, NULL, pip, ORPHANAGE, strlen(ORPHANAGE),
828 &ino) == 0)
829 return ino;
830
831 /*
832 * could not be found, create it
833 */
834
2bd0ea18
NS
835 tp = libxfs_trans_alloc(mp, 0);
836 XFS_BMAP_INIT(&flist, &first);
837
838 nres = XFS_MKDIR_SPACE_RES(mp, strlen(ORPHANAGE));
27527004
NS
839 if ((i = libxfs_trans_reserve(tp, nres, XFS_MKDIR_LOG_RES(mp), 0,
840 XFS_TRANS_PERM_LOG_RES, XFS_MKDIR_LOG_COUNT)))
2bd0ea18
NS
841 res_failed(i);
842
843 /*
844 * use iget/ijoin instead of trans_iget because the ialloc
845 * wrapper can commit the transaction and start a new one
846 */
6c39a3cb 847/* if ((i = libxfs_iget(mp, NULL, mp->m_sb.sb_rootino, 0, &pip, 0)))
507f4e33 848 do_error(_("%d - couldn't iget root inode to make %s\n"),
6c39a3cb 849 i, ORPHANAGE);*/
2bd0ea18 850
322f2a29 851 error = libxfs_inode_alloc(&tp, pip, mode|S_IFDIR,
9f064b7e 852 1, 0, &zerocr, &zerofsx, &ip);
2bd0ea18 853 if (error) {
507f4e33 854 do_error(_("%s inode allocation failed %d\n"),
2bd0ea18
NS
855 ORPHANAGE, error);
856 }
2bd0ea18
NS
857 ip->i_d.di_nlink++; /* account for . */
858
859 /*
860 * now that we know the transaction will stay around,
861 * add the root inode to it
862 */
863 libxfs_trans_ijoin(tp, pip, 0);
864
865 /*
866 * create the actual entry
867 */
27527004
NS
868 if ((error = dir_createname(mp, tp, pip, ORPHANAGE,
869 strlen(ORPHANAGE), ip->i_ino, &first, &flist, nres))) {
6c39a3cb
BN
870 do_error(
871 _("can't make %s, createname error %d\n"),
2bd0ea18 872 ORPHANAGE, error);
6c39a3cb 873 }
2bd0ea18 874
dfc130f3 875 /*
2bd0ea18
NS
876 * bump up the link count in the root directory to account
877 * for .. in the new directory
878 */
879 pip->i_d.di_nlink++;
6c39a3cb
BN
880 add_inode_ref(find_inode_rec(XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino),
881 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino)), 0);
882
2bd0ea18
NS
883
884 libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE);
885 dir_init(mp, tp, ip, pip);
886 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
887
888 error = libxfs_bmap_finish(&tp, &flist, first, &committed);
889 if (error) {
507f4e33 890 do_error(_("%s directory creation failed -- bmapf error %d\n"),
2bd0ea18
NS
891 ORPHANAGE, error);
892 }
893
894 ino = ip->i_ino;
895
896 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC, 0);
897
2bd0ea18
NS
898 return(ino);
899}
900
901/*
6c39a3cb 902 * move a file to the orphange.
2bd0ea18 903 */
6c39a3cb
BN
904static void
905mv_orphanage(
906 xfs_mount_t *mp,
907 xfs_ino_t ino, /* inode # to be moved */
908 int isa_dir) /* 1 if inode is a directory */
2bd0ea18 909{
2556c98b 910 xfs_inode_t *orphanage_ip;
6c39a3cb
BN
911 xfs_ino_t entry_ino_num;
912 xfs_inode_t *ino_p;
913 xfs_trans_t *tp;
914 xfs_fsblock_t first;
915 xfs_bmap_free_t flist;
916 int err;
917 int committed;
918 char fname[MAXPATHLEN + 1];
919 int fnamelen;
920 int nres;
921 int incr;
922 ino_tree_node_t *irec;
923 int ino_offset = 0;
2bd0ea18 924
6c39a3cb
BN
925 fnamelen = snprintf(fname, sizeof(fname), "%llu",
926 (unsigned long long)ino);
2bd0ea18 927
2556c98b
BN
928 err = libxfs_iget(mp, NULL, orphanage_ino, 0, &orphanage_ip, 0);
929 if (err)
930 do_error(_("%d - couldn't iget orphanage inode\n"), err);
6c39a3cb
BN
931 /*
932 * Make sure the filename is unique in the lost+found
933 */
934 incr = 0;
935 while (dir_lookup(mp, NULL, orphanage_ip, fname, fnamelen,
936 &entry_ino_num) == 0) {
937 fnamelen = snprintf(fname, sizeof(fname), "%llu.%d",
938 (unsigned long long)ino, ++incr);
939 }
2bd0ea18
NS
940
941 tp = libxfs_trans_alloc(mp, 0);
942
27527004 943 if ((err = libxfs_iget(mp, NULL, ino, 0, &ino_p, 0)))
507f4e33 944 do_error(_("%d - couldn't iget disconnected inode\n"), err);
2bd0ea18
NS
945
946 if (isa_dir) {
6c39a3cb
BN
947 irec = find_inode_rec(XFS_INO_TO_AGNO(mp, orphanage_ino),
948 XFS_INO_TO_AGINO(mp, orphanage_ino));
949 if (irec)
950 ino_offset = XFS_INO_TO_AGINO(mp, orphanage_ino) -
951 irec->ino_startnum;
952 nres = XFS_DIRENTER_SPACE_RES(mp, fnamelen) +
2bd0ea18 953 XFS_DIRENTER_SPACE_RES(mp, 2);
6c39a3cb
BN
954 err = dir_lookup(mp, tp, ino_p, "..", 2, &entry_ino_num);
955 if (err) {
2bd0ea18
NS
956 ASSERT(err == ENOENT);
957
27527004 958 if ((err = libxfs_trans_reserve(tp, nres,
2bd0ea18
NS
959 XFS_RENAME_LOG_RES(mp), 0,
960 XFS_TRANS_PERM_LOG_RES,
27527004 961 XFS_RENAME_LOG_COUNT)))
2bd0ea18 962 do_error(
507f4e33 963 _("space reservation failed (%d), filesystem may be out of space\n"),
2bd0ea18
NS
964 err);
965
6c39a3cb 966 libxfs_trans_ijoin(tp, orphanage_ip, 0);
2bd0ea18
NS
967 libxfs_trans_ijoin(tp, ino_p, 0);
968
969 XFS_BMAP_INIT(&flist, &first);
6c39a3cb
BN
970 if ((err = dir_createname(mp, tp, orphanage_ip, fname,
971 fnamelen, ino, &first,
27527004 972 &flist, nres)))
2bd0ea18 973 do_error(
507f4e33 974 _("name create failed in %s (%d), filesystem may be out of space\n"),
2bd0ea18
NS
975 ORPHANAGE, err);
976
6c39a3cb
BN
977 if (irec)
978 add_inode_ref(irec, ino_offset);
979 else
980 orphanage_ip->i_d.di_nlink++;
981 libxfs_trans_log_inode(tp, orphanage_ip, XFS_ILOG_CORE);
2bd0ea18 982
27527004 983 if ((err = dir_createname(mp, tp, ino_p, "..", 2,
6c39a3cb 984 orphanage_ino, &first, &flist, nres)))
2bd0ea18 985 do_error(
507f4e33 986 _("creation of .. entry failed (%d), filesystem may be out of space\n"),
2bd0ea18
NS
987 err);
988
989 ino_p->i_d.di_nlink++;
990 libxfs_trans_log_inode(tp, ino_p, XFS_ILOG_CORE);
991
27527004 992 if ((err = libxfs_bmap_finish(&tp, &flist, first, &committed)))
2bd0ea18 993 do_error(
507f4e33 994 _("bmap finish failed (err - %d), filesystem may be out of space\n"),
2bd0ea18
NS
995 err);
996
997 libxfs_trans_commit(tp,
998 XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC, 0);
999 } else {
27527004 1000 if ((err = libxfs_trans_reserve(tp, nres,
2bd0ea18
NS
1001 XFS_RENAME_LOG_RES(mp), 0,
1002 XFS_TRANS_PERM_LOG_RES,
27527004 1003 XFS_RENAME_LOG_COUNT)))
2bd0ea18 1004 do_error(
507f4e33 1005 _("space reservation failed (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1006 err);
1007
6c39a3cb 1008 libxfs_trans_ijoin(tp, orphanage_ip, 0);
2bd0ea18
NS
1009 libxfs_trans_ijoin(tp, ino_p, 0);
1010
1011 XFS_BMAP_INIT(&flist, &first);
1012
6c39a3cb
BN
1013 if ((err = dir_createname(mp, tp, orphanage_ip, fname,
1014 fnamelen, ino, &first,
27527004 1015 &flist, nres)))
2bd0ea18 1016 do_error(
507f4e33 1017 _("name create failed in %s (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1018 ORPHANAGE, err);
1019
6c39a3cb
BN
1020 if (irec)
1021 add_inode_ref(irec, ino_offset);
1022 else
1023 orphanage_ip->i_d.di_nlink++;
1024 libxfs_trans_log_inode(tp, orphanage_ip, XFS_ILOG_CORE);
2bd0ea18
NS
1025
1026 /*
1027 * don't replace .. value if it already points
1028 * to us. that'll pop a libxfs/kernel ASSERT.
1029 */
6c39a3cb 1030 if (entry_ino_num != orphanage_ino) {
27527004 1031 if ((err = dir_replace(mp, tp, ino_p, "..",
6c39a3cb 1032 2, orphanage_ino, &first,
27527004 1033 &flist, nres)))
2bd0ea18 1034 do_error(
507f4e33 1035 _("name replace op failed (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1036 err);
1037 }
1038
27527004
NS
1039 if ((err = libxfs_bmap_finish(&tp, &flist, first,
1040 &committed)))
2bd0ea18 1041 do_error(
507f4e33 1042 _("bmap finish failed (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1043 err);
1044
1045 libxfs_trans_commit(tp,
1046 XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC, 0);
1047 }
6c39a3cb 1048
2bd0ea18
NS
1049 } else {
1050 /*
1051 * use the remove log reservation as that's
1052 * more accurate. we're only creating the
1053 * links, we're not doing the inode allocation
1054 * also accounted for in the create
1055 */
6c39a3cb 1056 nres = XFS_DIRENTER_SPACE_RES(mp, fnamelen);
27527004
NS
1057 if ((err = libxfs_trans_reserve(tp, nres, XFS_REMOVE_LOG_RES(mp), 0,
1058 XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT)))
2bd0ea18 1059 do_error(
507f4e33 1060 _("space reservation failed (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1061 err);
1062
6c39a3cb 1063 libxfs_trans_ijoin(tp, orphanage_ip, 0);
2bd0ea18
NS
1064 libxfs_trans_ijoin(tp, ino_p, 0);
1065
1066 XFS_BMAP_INIT(&flist, &first);
6c39a3cb
BN
1067 if ((err = dir_createname(mp, tp, orphanage_ip, fname,
1068 fnamelen, ino, &first, &flist, nres)))
2bd0ea18 1069 do_error(
507f4e33 1070 _("name create failed in %s (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1071 ORPHANAGE, err);
1072 ASSERT(err == 0);
1073
1074 ino_p->i_d.di_nlink = 1;
1075 libxfs_trans_log_inode(tp, ino_p, XFS_ILOG_CORE);
1076
27527004 1077 if ((err = libxfs_bmap_finish(&tp, &flist, first, &committed)))
2bd0ea18 1078 do_error(
507f4e33 1079 _("bmap finish failed (%d), filesystem may be out of space\n"),
2bd0ea18
NS
1080 err);
1081
1082 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC, 0);
1083 }
1084}
1085
1086/*
1087 * like get_first_dblock_fsbno only it uses the simulation code instead
1088 * of raw I/O.
1089 *
1090 * Returns the fsbno of the first (leftmost) block in the directory leaf.
1091 * sets *bno to the directory block # corresponding to the returned fsbno.
1092 */
2556c98b 1093static xfs_dfsbno_t
2bd0ea18
NS
1094map_first_dblock_fsbno(xfs_mount_t *mp,
1095 xfs_ino_t ino,
1096 xfs_inode_t *ip,
1097 xfs_dablk_t *bno)
1098{
1099 xfs_fsblock_t fblock;
1100 xfs_da_intnode_t *node;
1101 xfs_buf_t *bp;
1102 xfs_dablk_t da_bno;
1103 xfs_dfsbno_t fsbno;
1104 xfs_bmbt_irec_t map;
1105 int nmap;
1106 int i;
1107 int error;
1108 char *ftype;
1109
1110 /*
1111 * traverse down left-side of tree until we hit the
1112 * left-most leaf block setting up the btree cursor along
1113 * the way.
1114 */
1115 da_bno = 0;
1116 *bno = 0;
1117 i = -1;
1118 node = NULL;
1119 fblock = NULLFSBLOCK;
507f4e33 1120 ftype = _("dir");
2bd0ea18
NS
1121
1122 nmap = 1;
1123 error = libxfs_bmapi(NULL, ip, (xfs_fileoff_t) da_bno, 1,
1124 XFS_BMAPI_METADATA, &fblock, 0,
1125 &map, &nmap, NULL);
1126 if (error || nmap != 1) {
1127 if (!no_modify)
1128 do_error(
507f4e33 1129_("can't map block %d in %s inode %llu, xfs_bmapi returns %d, nmap = %d\n"),
2bd0ea18
NS
1130 da_bno, ftype, ino, error, nmap);
1131 else {
1132 do_warn(
507f4e33 1133_("can't map block %d in %s inode %llu, xfs_bmapi returns %d, nmap = %d\n"),
2bd0ea18
NS
1134 da_bno, ftype, ino, error, nmap);
1135 return(NULLDFSBNO);
1136 }
1137 }
1138
1139 if ((fsbno = map.br_startblock) == HOLESTARTBLOCK) {
1140 if (!no_modify)
507f4e33 1141 do_error(_("block %d in %s ino %llu doesn't exist\n"),
2bd0ea18
NS
1142 da_bno, ftype, ino);
1143 else {
507f4e33 1144 do_warn(_("block %d in %s ino %llu doesn't exist\n"),
2bd0ea18
NS
1145 da_bno, ftype, ino);
1146 return(NULLDFSBNO);
1147 }
1148 }
1149
1150 if (ip->i_d.di_size <= XFS_LBSIZE(mp))
1151 return(fsbno);
1152
1153 if (XFS_SB_VERSION_HASDIRV2(&mp->m_sb))
1154 return(fsbno);
1155
1156 do {
1157 /*
1158 * walk down left side of btree, release buffers as you
1159 * go. if the root block is a leaf (single-level btree),
1160 * just return it.
dfc130f3 1161 *
2bd0ea18
NS
1162 */
1163
1164 bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, fsbno),
1165 XFS_FSB_TO_BB(mp, 1), 0);
1166
1167 if (!bp) {
1168 do_warn(
507f4e33 1169 _("can't read block %u (fsbno %llu) for directory inode %llu\n"),
2bd0ea18
NS
1170 da_bno, fsbno, ino);
1171 return(NULLDFSBNO);
1172 }
1173
1174 node = (xfs_da_intnode_t *)XFS_BUF_PTR(bp);
1175
1176 if (INT_GET(node->hdr.info.magic, ARCH_CONVERT) != XFS_DA_NODE_MAGIC) {
1177 libxfs_putbuf(bp);
1178 do_warn(
507f4e33 1179_("bad dir/attr magic number in inode %llu, file bno = %u, fsbno = %llu\n"),
2bd0ea18
NS
1180 ino, da_bno, fsbno);
1181 return(NULLDFSBNO);
1182 }
1183
1184 if (i == -1)
1185 i = INT_GET(node->hdr.level, ARCH_CONVERT);
1186
1187 da_bno = INT_GET(node->btree[0].before, ARCH_CONVERT);
1188
1189 libxfs_putbuf(bp);
1190 bp = NULL;
1191
1192 nmap = 1;
1193 error = libxfs_bmapi(NULL, ip, (xfs_fileoff_t) da_bno, 1,
1194 XFS_BMAPI_METADATA, &fblock, 0,
1195 &map, &nmap, NULL);
1196 if (error || nmap != 1) {
1197 if (!no_modify)
1198 do_error(
507f4e33 1199_("can't map block %d in %s ino %llu, xfs_bmapi returns %d, nmap = %d\n"),
2bd0ea18
NS
1200 da_bno, ftype, ino, error, nmap);
1201 else {
1202 do_warn(
507f4e33 1203_("can't map block %d in %s ino %llu, xfs_bmapi returns %d, nmap = %d\n"),
2bd0ea18
NS
1204 da_bno, ftype, ino, error, nmap);
1205 return(NULLDFSBNO);
1206 }
1207 }
1208 if ((fsbno = map.br_startblock) == HOLESTARTBLOCK) {
1209 if (!no_modify)
1210 do_error(
507f4e33 1211 _("block %d in %s inode %llu doesn't exist\n"),
2bd0ea18
NS
1212 da_bno, ftype, ino);
1213 else {
1214 do_warn(
507f4e33 1215 _("block %d in %s inode %llu doesn't exist\n"),
2bd0ea18
NS
1216 da_bno, ftype, ino);
1217 return(NULLDFSBNO);
1218 }
1219 }
1220
1221 i--;
1222 } while(i > 0);
1223
1224 *bno = da_bno;
1225 return(fsbno);
1226}
1227
1228/*
1229 * scan longform directory and prune first bad entry. returns 1 if
1230 * it had to remove something, 0 if it made it all the way through
1231 * the directory. prune_lf_dir_entry does all the necessary bmap calls.
1232 *
1233 * hashval is an in/out -- starting hashvalue in, hashvalue of the
1234 * deleted entry (if there was one) out
1235 *
1236 * this routine can NOT be called if running in no modify mode
1237 */
2556c98b 1238static int
2bd0ea18
NS
1239prune_lf_dir_entry(xfs_mount_t *mp, xfs_ino_t ino, xfs_inode_t *ip,
1240 xfs_dahash_t *hashval)
1241{
1242 xfs_dfsbno_t fsbno;
1243 int i;
1244 int index;
1245 int error;
1246 int namelen;
1247 xfs_bmap_free_t free_list;
1248 xfs_fsblock_t first_block;
1249 xfs_buf_t *bp;
1250 xfs_dir_leaf_name_t *namest;
1251 xfs_dir_leafblock_t *leaf;
1252 xfs_dir_leaf_entry_t *entry;
1253 xfs_trans_t *tp;
1254 xfs_dablk_t da_bno;
1255 xfs_fsblock_t fblock;
1256 int committed;
1257 int nmap;
1258 xfs_bmbt_irec_t map;
1259 char fname[MAXNAMELEN + 1];
1260 char *ftype;
1261 int nres;
1262
1263 /*
1264 * ok, this is kind of a schizoid routine. we use our
1265 * internal bmapi routines to walk the directory. when
1266 * we find a bogus entry, we release the buffer so
1267 * the simulation code doesn't deadlock and use the
1268 * sim code to remove the entry. That will cause an
1269 * extra bmap traversal to map the block but I think
1270 * that's preferable to hacking the bogus removename
1271 * function to be really different and then trying to
1272 * maintain both versions as time goes on.
1273 *
1274 * first, grab the dinode and find the right leaf block.
1275 */
1276
507f4e33 1277 ftype = _("dir");
2bd0ea18
NS
1278 da_bno = 0;
1279 bp = NULL;
1280 namest = NULL;
1281 fblock = NULLFSBLOCK;
1282
1283 fsbno = map_first_dblock_fsbno(mp, ino, ip, &da_bno);
1284
1285 /*
1286 * now go foward along the leaves of the btree looking
1287 * for an entry beginning with '/'
1288 */
1289 do {
1290 bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, fsbno),
1291 XFS_FSB_TO_BB(mp, 1), 0);
1292
1293 if (!bp) {
1294 do_error(
507f4e33 1295 _("can't read directory inode %llu (leaf) block %u (fsbno %llu)\n"),
2bd0ea18
NS
1296 ino, da_bno, fsbno);
1297 /* NOTREACHED */
1298 }
1299
1300 leaf = (xfs_dir_leafblock_t *)XFS_BUF_PTR(bp);
1301 ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC);
1302 entry = &leaf->entries[0];
1303
1304 for (index = -1, i = 0;
1305 i < INT_GET(leaf->hdr.count, ARCH_CONVERT) && index == -1;
1306 i++) {
1307 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
1308 if (namest->name[0] != '/')
1309 entry++;
1310 else
1311 index = i;
1312 }
1313
1314 /*
1315 * if we got a bogus entry, exit loop with a pointer to
1316 * the leaf block buffer. otherwise, keep trying blocks
1317 */
1318 da_bno = INT_GET(leaf->hdr.info.forw, ARCH_CONVERT);
1319
1320 if (index == -1) {
1321 if (bp != NULL) {
1322 libxfs_putbuf(bp);
1323 bp = NULL;
1324 }
1325
1326 /*
1327 * map next leaf block unless we've run out
1328 */
1329 if (da_bno != 0) {
1330 nmap = 1;
1331 error = libxfs_bmapi(NULL, ip,
1332 (xfs_fileoff_t) da_bno, 1,
1333 XFS_BMAPI_METADATA, &fblock, 0,
1334 &map, &nmap, NULL);
1335 if (error || nmap != 1)
1336 do_error(
507f4e33 1337_("can't map block %d in directory %llu, xfs_bmapi returns %d, nmap = %d\n"),
2bd0ea18
NS
1338 da_bno, ino, error, nmap);
1339 if ((fsbno = map.br_startblock)
1340 == HOLESTARTBLOCK) {
1341 do_error(
507f4e33 1342 _("%s ino %llu block %d doesn't exist\n"),
2bd0ea18
NS
1343 ftype, ino, da_bno);
1344 }
1345 }
1346 }
1347 } while (da_bno != 0 && index == -1);
1348
1349 /*
1350 * if we hit the edge of the tree with no bad entries, we're done
1351 * and the buffer was released.
1352 */
1353 if (da_bno == 0 && index == -1)
1354 return(0);
1355
1356 ASSERT(index >= 0);
1357 ASSERT(entry == &leaf->entries[index]);
507f4e33
NS
1358 ASSERT(namest == XFS_DIR_LEAF_NAMESTRUCT(leaf,
1359 INT_GET(entry->nameidx, ARCH_CONVERT)));
2bd0ea18
NS
1360
1361 /*
1362 * snag the info we need out of the directory then release all buffers
1363 */
1364 bcopy(namest->name, fname, entry->namelen);
1365 fname[entry->namelen] = '\0';
1366 *hashval = INT_GET(entry->hashval, ARCH_CONVERT);
1367 namelen = entry->namelen;
1368
1369 libxfs_putbuf(bp);
1370
1371 /*
1372 * ok, now the hard part, blow away the index'th entry in this block
1373 *
1374 * allocate a remove transaction for it. that's not quite true since
1375 * we're only messing with one inode, not two but...
1376 */
1377
1378 tp = libxfs_trans_alloc(mp, XFS_TRANS_REMOVE);
1379
1380 nres = XFS_REMOVE_SPACE_RES(mp);
1381 error = libxfs_trans_reserve(tp, nres, XFS_REMOVE_LOG_RES(mp),
1382 0, XFS_TRANS_PERM_LOG_RES,
1383 XFS_REMOVE_LOG_COUNT);
1384 if (error)
1385 res_failed(error);
1386
1387 libxfs_trans_ijoin(tp, ip, 0);
1388 libxfs_trans_ihold(tp, ip);
1389
1390 XFS_BMAP_INIT(&free_list, &first_block);
1391
1392 error = dir_bogus_removename(mp, tp, ip, fname,
1393 &first_block, &free_list, nres, *hashval, namelen);
1394
1395 if (error) {
1396 do_error(
507f4e33 1397_("couldn't remove bogus entry \"%s\" in\n\tdirectory inode %llu, errno = %d\n"),
2bd0ea18
NS
1398 fname, ino, error);
1399 /* NOTREACHED */
1400 }
1401
1402 error = libxfs_bmap_finish(&tp, &free_list, first_block, &committed);
1403
1404 ASSERT(error == 0);
1405
1406 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC, 0);
1407
1408 return(1);
1409}
1410
6c39a3cb
BN
1411static int
1412entry_junked(
1413 const char *msg,
1414 const char *iname,
1415 xfs_ino_t ino1,
1416 xfs_ino_t ino2)
1417{
1418 do_warn(msg, iname, ino1, ino2);
1419 if (!no_modify) {
1420 if (verbose)
1421 do_warn(_(", marking entry to be junked\n"));
1422 else
1423 do_warn("\n");
1424 } else
1425 do_warn(_(", would junk entry\n"));
1426 return !no_modify;
1427}
1428
2bd0ea18
NS
1429/*
1430 * process a leaf block, also checks for .. entry
1431 * and corrects it to match what we think .. should be
1432 */
2556c98b 1433static void
2bd0ea18
NS
1434lf_block_dir_entry_check(xfs_mount_t *mp,
1435 xfs_ino_t ino,
1436 xfs_dir_leafblock_t *leaf,
1437 int *dirty,
1438 int *num_illegal,
1439 int *need_dot,
2bd0ea18 1440 ino_tree_node_t *current_irec,
64c54486 1441 int current_ino_offset,
33165ec3
BN
1442 dir_hash_tab_t *hashtab,
1443 xfs_dablk_t da_bno)
2bd0ea18
NS
1444{
1445 xfs_dir_leaf_entry_t *entry;
1446 ino_tree_node_t *irec;
1447 xfs_ino_t lino;
1448 xfs_ino_t parent;
1449 xfs_dir_leaf_name_t *namest;
1450 int i;
1451 int junkit;
1452 int ino_offset;
1453 int nbad;
1454 char fname[MAXNAMELEN + 1];
1455
1456 entry = &leaf->entries[0];
1457 *dirty = 0;
1458 nbad = 0;
1459
1460 /*
1461 * look at each entry. reference inode pointed to by each
1462 * entry in the incore inode tree.
1463 * if not a directory, set reached flag, increment link count
1464 * if a directory and reached, mark entry as to be deleted.
1465 * if a directory, check to see if recorded parent
1466 * matches current inode #,
1467 * if so, then set reached flag, increment link count
1468 * of current and child dir inodes, push the child
1469 * directory inode onto the directory stack.
1470 * if current inode != parent, then mark entry to be deleted.
1471 *
1472 * return
1473 */
1474 for (i = 0; i < INT_GET(leaf->hdr.count, ARCH_CONVERT); entry++, i++) {
1475 /*
1476 * snag inode #, update link counts, and make sure
1477 * this isn't a loop if the child is a directory
1478 */
1479 namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
1480
1481 /*
1482 * skip bogus entries (leading '/'). they'll be deleted
1483 * later
1484 */
1485 if (namest->name[0] == '/') {
1486 nbad++;
1487 continue;
1488 }
1489
1490 junkit = 0;
1491
46eca962 1492 XFS_DIR_SF_GET_DIRINO(&namest->inumber, &lino);
2bd0ea18
NS
1493 bcopy(namest->name, fname, entry->namelen);
1494 fname[entry->namelen] = '\0';
1495
1496 ASSERT(lino != NULLFSINO);
1497
1498 /*
1499 * skip the '..' entry since it's checked when the
1500 * directory is reached by something else. if it never
1501 * gets reached, it'll be moved to the orphanage and we'll
1502 * take care of it then.
1503 */
1504 if (entry->namelen == 2 && namest->name[0] == '.' &&
6c39a3cb 1505 namest->name[1] == '.')
2bd0ea18 1506 continue;
6c39a3cb 1507
2bd0ea18
NS
1508 ASSERT(no_modify || !verify_inum(mp, lino));
1509
1510 /*
1511 * special case the . entry. we know there's only one
1512 * '.' and only '.' points to itself because bogus entries
1513 * got trashed in phase 3 if there were > 1.
1514 * bump up link count for '.' but don't set reached
1515 * until we're actually reached by another directory
1516 * '..' is already accounted for or will be taken care
1517 * of when directory is moved to orphanage.
1518 */
1519 if (ino == lino) {
1520 ASSERT(namest->name[0] == '.' && entry->namelen == 1);
1521 add_inode_ref(current_irec, current_ino_offset);
1522 *need_dot = 0;
1523 continue;
1524 }
1525
2bd0ea18
NS
1526 /*
1527 * skip entries with bogus inumbers if we're in no modify mode
1528 */
1529 if (no_modify && verify_inum(mp, lino))
1530 continue;
1531
1532 /*
1533 * ok, now handle the rest of the cases besides '.' and '..'
1534 */
1535 irec = find_inode_rec(XFS_INO_TO_AGNO(mp, lino),
1536 XFS_INO_TO_AGINO(mp, lino));
dfc130f3 1537
2bd0ea18
NS
1538 if (irec == NULL) {
1539 nbad++;
6c39a3cb
BN
1540 if (entry_junked(_("entry \"%s\" in dir inode %llu "
1541 "points to non-existent inode %llu"),
1542 fname, ino, lino)) {
2bd0ea18
NS
1543 namest->name[0] = '/';
1544 *dirty = 1;
2bd0ea18 1545 }
2bd0ea18
NS
1546 continue;
1547 }
1548
1549 ino_offset = XFS_INO_TO_AGINO(mp, lino) - irec->ino_startnum;
1550
1551 /*
1552 * if it's a free inode, blow out the entry.
1553 * by now, any inode that we think is free
1554 * really is free.
1555 */
1556 if (is_inode_free(irec, ino_offset)) {
2bd0ea18 1557 nbad++;
6c39a3cb
BN
1558 if (entry_junked(_("entry \"%s\" in dir inode %llu "
1559 "points to free inode %llu"),
1560 fname, ino, lino)) {
2bd0ea18
NS
1561 namest->name[0] = '/';
1562 *dirty = 1;
2bd0ea18 1563 }
2bd0ea18
NS
1564 continue;
1565 }
6c39a3cb
BN
1566 /*
1567 * check if this inode is lost+found dir in the root
1568 */
1569 if (ino == mp->m_sb.sb_rootino && strcmp(fname, ORPHANAGE) == 0) {
1570 /* root inode, "lost+found", if it's not a directory,
1571 * trash it, otherwise, assign it */
1572 if (!inode_isadir(irec, ino_offset)) {
1573 nbad++;
1574 if (entry_junked(_("%s (ino %llu) in root "
1575 "(%llu) is not a directory"),
1576 ORPHANAGE, lino, ino)) {
1577 namest->name[0] = '/';
1578 *dirty = 1;
1579 }
1580 continue;
1581 }
1582 /*
1583 * if this is a dup, it will be picked up below,
1584 * otherwise, mark it as the orphanage for later.
1585 */
1586 if (!orphanage_ino)
1587 orphanage_ino = lino;
1588 }
64c54486
BN
1589 /*
1590 * check for duplicate names in directory.
0f012a4c
BN
1591 */
1592 if (!dir_hash_add(hashtab, (da_bno << mp->m_sb.sb_blocklog) +
6c39a3cb
BN
1593 entry->nameidx, lino, entry->namelen,
1594 namest->name)) {
64c54486 1595 nbad++;
6c39a3cb
BN
1596 if (entry_junked(_("entry \"%s\" (ino %llu) in dir "
1597 "%llu is a duplicate name"),
1598 fname, lino, ino)) {
64c54486
BN
1599 namest->name[0] = '/';
1600 *dirty = 1;
64c54486 1601 }
6c39a3cb
BN
1602 if (lino == orphanage_ino)
1603 orphanage_ino = 0;
64c54486
BN
1604 continue;
1605 }
2bd0ea18
NS
1606 /*
1607 * check easy case first, regular inode, just bump
1608 * the link count and continue
1609 */
1610 if (!inode_isadir(irec, ino_offset)) {
1611 add_inode_reached(irec, ino_offset);
1612 continue;
1613 }
1614
1615 parent = get_inode_parent(irec, ino_offset);
1616 ASSERT(parent != 0);
1617
1618 /*
1619 * bump up the link counts in parent and child
1620 * directory but if the link doesn't agree with
1621 * the .. in the child, blow out the entry.
1622 * if the directory has already been reached,
1623 * blow away the entry also.
1624 */
1625 if (is_inode_reached(irec, ino_offset)) {
1626 junkit = 1;
6fa00c33
BN
1627 do_warn(_("entry \"%s\" in dir %llu points to an "
1628 "already connected dir inode %llu,\n"),
2bd0ea18
NS
1629 fname, ino, lino);
1630 } else if (parent == ino) {
1631 add_inode_reached(irec, ino_offset);
1632 add_inode_ref(current_irec, current_ino_offset);
6fa00c33
BN
1633 } else if (parent == NULLFSINO) {
1634 /* ".." was missing, but this entry refers to it,
1635 so, set it as the parent and mark for rebuild */
1636 do_warn(_("entry \"%s\" in dir ino %llu doesn't have a"
1637 " .. entry, will set it in ino %llu.\n"),
1638 fname, ino, lino);
1639 set_inode_parent(irec, ino_offset, ino);
1640 add_inode_reached(irec, ino_offset);
1641 add_inode_ref(current_irec, current_ino_offset);
1642 } else {
2bd0ea18 1643 junkit = 1;
6fa00c33
BN
1644 do_warn(_("entry \"%s\" in dir ino %llu not consistent"
1645 " with .. value (%llu) in ino %llu,\n"),
2bd0ea18
NS
1646 fname, ino, parent, lino);
1647 }
1648
1649 if (junkit) {
6c39a3cb
BN
1650 if (lino == orphanage_ino)
1651 orphanage_ino = 0;
2bd0ea18
NS
1652 junkit = 0;
1653 nbad++;
2bd0ea18
NS
1654 if (!no_modify) {
1655 namest->name[0] = '/';
1656 *dirty = 1;
6c39a3cb 1657 if (verbose)
507f4e33
NS
1658 do_warn(
1659 _("\twill clear entry \"%s\"\n"),
2bd0ea18
NS
1660 fname);
1661 } else {
507f4e33
NS
1662 do_warn(_("\twould clear entry \"%s\"\n"),
1663 fname);
2bd0ea18
NS
1664 }
1665 }
1666 }
1667
1668 *num_illegal += nbad;
1669}
1670
1671/*
1672 * succeeds or dies, inode never gets dirtied since all changes
1673 * happen in file blocks. the inode size and other core info
1674 * is already correct, it's just the leaf entries that get altered.
1675 */
2556c98b 1676static void
2bd0ea18
NS
1677longform_dir_entry_check(xfs_mount_t *mp,
1678 xfs_ino_t ino,
1679 xfs_inode_t *ip,
1680 int *num_illegal,
1681 int *need_dot,
2bd0ea18 1682 ino_tree_node_t *irec,
64c54486 1683 int ino_offset,
33165ec3 1684 dir_hash_tab_t *hashtab)
2bd0ea18
NS
1685{
1686 xfs_dir_leafblock_t *leaf;
1687 xfs_buf_t *bp;
1688 xfs_dfsbno_t fsbno;
1689 xfs_fsblock_t fblock;
1690 xfs_dablk_t da_bno;
1691 int dirty;
1692 int nmap;
1693 int error;
1694 int skipit;
1695 xfs_bmbt_irec_t map;
1696 char *ftype;
1697
1698 da_bno = 0;
1699 fblock = NULLFSBLOCK;
1700 *need_dot = 1;
507f4e33 1701 ftype = _("dir");
2bd0ea18
NS
1702
1703 fsbno = map_first_dblock_fsbno(mp, ino, ip, &da_bno);
1704
1705 if (fsbno == NULLDFSBNO && no_modify) {
507f4e33 1706 do_warn(_("cannot map block 0 of directory inode %llu\n"), ino);
2bd0ea18
NS
1707 return;
1708 }
1709
1710 do {
1711 ASSERT(fsbno != NULLDFSBNO);
1712 skipit = 0;
1713
1714 bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, fsbno),
1715 XFS_FSB_TO_BB(mp, 1), 0);
1716
1717 if (!bp) {
1718 do_error(
507f4e33 1719 _("can't read block %u (fsbno %llu) for directory inode %llu\n"),
2bd0ea18
NS
1720 da_bno, fsbno, ino);
1721 /* NOTREACHED */
1722 }
1723
1724 leaf = (xfs_dir_leafblock_t *)XFS_BUF_PTR(bp);
1725
507f4e33
NS
1726 if (INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) !=
1727 XFS_DIR_LEAF_MAGIC) {
2bd0ea18
NS
1728 if (!no_modify) {
1729 do_error(
507f4e33
NS
1730_("bad magic # (0x%x) for dir ino %llu leaf block (bno %u fsbno %llu)\n"),
1731 INT_GET(leaf->hdr.info.magic,
1732 ARCH_CONVERT),
2bd0ea18
NS
1733 ino, da_bno, fsbno);
1734 /* NOTREACHED */
1735 } else {
1736 /*
1737 * this block's bad but maybe the
1738 * forward pointer is good...
1739 */
1740 skipit = 1;
1741 dirty = 0;
1742 }
1743 }
1744
1745 if (!skipit)
0f012a4c 1746 lf_block_dir_entry_check(mp, ino, leaf, &dirty,
2556c98b 1747 num_illegal, need_dot, irec,
33165ec3
BN
1748 ino_offset, hashtab, da_bno);
1749
1750 da_bno = INT_GET(leaf->hdr.info.forw, ARCH_CONVERT);
2bd0ea18 1751
27527004 1752 ASSERT(dirty == 0 || (dirty && !no_modify));
2bd0ea18
NS
1753
1754 if (dirty && !no_modify)
1755 libxfs_writebuf(bp, 0);
1756 else
1757 libxfs_putbuf(bp);
1758 bp = NULL;
1759
1760 if (da_bno != 0) {
1761 nmap = 1;
1762 error = libxfs_bmapi(NULL, ip, (xfs_fileoff_t)da_bno, 1,
1763 XFS_BMAPI_METADATA, &fblock, 0,
1764 &map, &nmap, NULL);
1765 if (error || nmap != 1) {
1766 if (!no_modify)
1767 do_error(
507f4e33 1768_("can't map leaf block %d in dir %llu, xfs_bmapi returns %d, nmap = %d\n"),
2bd0ea18
NS
1769 da_bno, ino, error, nmap);
1770 else {
1771 do_warn(
507f4e33 1772_("can't map leaf block %d in dir %llu, xfs_bmapi returns %d, nmap = %d\n"),
2bd0ea18
NS
1773 da_bno, ino, error, nmap);
1774 return;
1775 }
1776 }
1777 if ((fsbno = map.br_startblock) == HOLESTARTBLOCK) {
1778 if (!no_modify)
1779 do_error(
507f4e33 1780 _("block %d in %s ino %llu doesn't exist\n"),
2bd0ea18
NS
1781 da_bno, ftype, ino);
1782 else {
1783 do_warn(
507f4e33 1784 _("block %d in %s ino %llu doesn't exist\n"),
2bd0ea18
NS
1785 da_bno, ftype, ino);
1786 return;
1787 }
1788 }
1789 }
1790 } while (da_bno != 0);
1791}
1792
33165ec3
BN
1793/*
1794 * Unexpected failure during the rebuild will leave the entries in
1795 * lost+found on the next run
1796 */
1797
0f012a4c 1798static void
33165ec3 1799longform_dir2_rebuild(
6fa00c33
BN
1800 xfs_mount_t *mp,
1801 xfs_ino_t ino,
1802 xfs_inode_t *ip,
1803 ino_tree_node_t *irec,
1804 int ino_offset,
1805 dir_hash_tab_t *hashtab)
33165ec3
BN
1806{
1807 int error;
1808 int nres;
1809 xfs_trans_t *tp;
1810 xfs_fileoff_t lastblock;
1811 xfs_fsblock_t firstblock;
1812 xfs_bmap_free_t flist;
2556c98b 1813 xfs_inode_t pip;
33165ec3
BN
1814 dir_hash_ent_t *p;
1815 int committed;
1816 int done;
0f012a4c
BN
1817
1818 /*
33165ec3
BN
1819 * trash directory completely and rebuild from scratch using the
1820 * name/inode pairs in the hash table
1821 */
0f012a4c 1822
33165ec3 1823 do_warn(_("rebuilding directory inode %llu\n"), ino);
0f012a4c
BN
1824
1825 /*
6fa00c33
BN
1826 * first attempt to locate the parent inode, if it can't be
1827 * found, set it to the root inode and it'll be moved to the
1828 * orphanage later (the inode number here needs to be valid
1829 * for the libxfs_dir2_init() call).
33165ec3 1830 */
6fa00c33
BN
1831 pip.i_ino = get_inode_parent(irec, ino_offset);
1832 if (pip.i_ino == NULLFSINO)
1833 pip.i_ino = mp->m_sb.sb_rootino;
33165ec3
BN
1834
1835 XFS_BMAP_INIT(&flist, &firstblock);
0f012a4c 1836
33165ec3
BN
1837 tp = libxfs_trans_alloc(mp, 0);
1838 nres = XFS_REMOVE_SPACE_RES(mp);
1839 error = libxfs_trans_reserve(tp, nres, XFS_REMOVE_LOG_RES(mp), 0,
1840 XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
1841 if (error)
1842 res_failed(error);
1843 libxfs_trans_ijoin(tp, ip, 0);
1844 libxfs_trans_ihold(tp, ip);
0f012a4c
BN
1845
1846 if ((error = libxfs_bmap_last_offset(tp, ip, &lastblock,
33165ec3 1847 XFS_DATA_FORK)))
0f012a4c 1848 do_error(_("xfs_bmap_last_offset failed -- error - %d\n"),
33165ec3 1849 error);
0f012a4c 1850
33165ec3 1851 /* free all data, leaf, node and freespace blocks */
0f012a4c
BN
1852
1853 if ((error = libxfs_bunmapi(tp, ip, 0, lastblock,
33165ec3
BN
1854 XFS_BMAPI_METADATA, 0, &firstblock, &flist,
1855 &done))) {
1856 do_warn(_("xfs_bunmapi failed -- error - %d\n"), error);
1857 libxfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
1858 XFS_TRANS_ABORT);
1859 return;
1860 }
0f012a4c 1861
33165ec3
BN
1862 ASSERT(done);
1863
2556c98b 1864 libxfs_dir2_init(tp, ip, &pip);
0f012a4c 1865
33165ec3 1866 error = libxfs_bmap_finish(&tp, &flist, firstblock, &committed);
0f012a4c
BN
1867
1868 libxfs_trans_commit(tp,
33165ec3 1869 XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC, 0);
0f012a4c 1870
33165ec3
BN
1871 /* go through the hash list and re-add the inodes */
1872
1873 for (p = hashtab->first; p; p = p->nextbyorder) {
0f012a4c
BN
1874
1875 if (p->name[0] == '/' || (p->name[0] == '.' && (p->namelen == 1
33165ec3
BN
1876 || (p->namelen == 2 && p->name[1] == '.'))))
1877 continue;
0f012a4c 1878
33165ec3
BN
1879 tp = libxfs_trans_alloc(mp, 0);
1880 nres = XFS_CREATE_SPACE_RES(mp, p->namelen);
0f012a4c 1881 if ((error = libxfs_trans_reserve(tp, nres,
33165ec3
BN
1882 XFS_CREATE_LOG_RES(mp), 0,
1883 XFS_TRANS_PERM_LOG_RES, XFS_CREATE_LOG_COUNT))) {
1884 do_warn(
1885 _("space reservation failed (%d), filesystem may be out of space\n"),
1886 error);
1887 break;
1888 }
1889
1890 libxfs_trans_ijoin(tp, ip, 0);
1891 libxfs_trans_ihold(tp, ip);
1892
1893 XFS_BMAP_INIT(&flist, &firstblock);
04d3ada9 1894 if ((error = libxfs_dir2_createname(tp, ip, (uchar_t *)p->name,
0f012a4c 1895 p->namelen, p->inum, &firstblock, &flist,
33165ec3
BN
1896 nres))) {
1897 do_warn(
1898_("name create failed in ino %llu (%d), filesystem may be out of space\n"),
1899 ino, error);
1900 libxfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
1901 XFS_TRANS_ABORT);
1902 break;
1903 }
1904
0f012a4c 1905 if ((error = libxfs_bmap_finish(&tp, &flist, firstblock,
33165ec3
BN
1906 &committed))) {
1907 do_warn(
1908 _("bmap finish failed (%d), filesystem may be out of space\n"),
1909 error);
1910 libxfs_bmap_cancel(&flist);
1911 libxfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
1912 XFS_TRANS_ABORT);
1913 break;
1914 }
33165ec3 1915
0f012a4c
BN
1916
1917 libxfs_trans_commit(tp,
33165ec3
BN
1918 XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC, 0);
1919 }
1920}
1921
1922
2bd0ea18
NS
1923/*
1924 * Kill a block in a version 2 inode.
1925 * Makes its own transaction.
1926 */
1927static void
1928dir2_kill_block(
1929 xfs_mount_t *mp,
1930 xfs_inode_t *ip,
1931 xfs_dablk_t da_bno,
1932 xfs_dabuf_t *bp)
1933{
1934 xfs_da_args_t args;
1935 int committed;
1936 int error;
1937 xfs_fsblock_t firstblock;
1938 xfs_bmap_free_t flist;
1939 int nres;
1940 xfs_trans_t *tp;
1941
1942 tp = libxfs_trans_alloc(mp, 0);
1943 nres = XFS_REMOVE_SPACE_RES(mp);
1944 error = libxfs_trans_reserve(tp, nres, XFS_REMOVE_LOG_RES(mp), 0,
1945 XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
1946 if (error)
1947 res_failed(error);
1948 libxfs_trans_ijoin(tp, ip, 0);
1949 libxfs_trans_ihold(tp, ip);
1950 libxfs_da_bjoin(tp, bp);
1951 bzero(&args, sizeof(args));
1952 XFS_BMAP_INIT(&flist, &firstblock);
1953 args.dp = ip;
1954 args.trans = tp;
1955 args.firstblock = &firstblock;
1956 args.flist = &flist;
1957 args.whichfork = XFS_DATA_FORK;
1958 if (da_bno >= mp->m_dirleafblk && da_bno < mp->m_dirfreeblk)
1959 error = libxfs_da_shrink_inode(&args, da_bno, bp);
1960 else
1961 error = libxfs_dir2_shrink_inode(&args,
1962 XFS_DIR2_DA_TO_DB(mp, da_bno), bp);
1963 if (error)
507f4e33 1964 do_error(_("shrink_inode failed inode %llu block %u\n"),
2bd0ea18
NS
1965 ip->i_ino, da_bno);
1966 libxfs_bmap_finish(&tp, &flist, firstblock, &committed);
1967 libxfs_trans_commit(tp, 0, 0);
1968}
1969
1970/*
1971 * process a data block, also checks for .. entry
1972 * and corrects it to match what we think .. should be
1973 */
1974static void
1975longform_dir2_entry_check_data(
1976 xfs_mount_t *mp,
1977 xfs_inode_t *ip,
1978 int *num_illegal,
1979 int *need_dot,
2bd0ea18
NS
1980 ino_tree_node_t *current_irec,
1981 int current_ino_offset,
1982 xfs_dabuf_t **bpp,
1983 dir_hash_tab_t *hashtab,
1984 freetab_t **freetabp,
1985 xfs_dablk_t da_bno,
1986 int isblock)
1987{
1988 xfs_dir2_dataptr_t addr;
1989 xfs_dir2_leaf_entry_t *blp;
1990 xfs_dabuf_t *bp;
1991 xfs_dir2_block_tail_t *btp;
1992 int committed;
1993 xfs_dir2_data_t *d;
1994 xfs_dir2_db_t db;
1995 xfs_dir2_data_entry_t *dep;
1996 xfs_dir2_data_unused_t *dup;
1997 char *endptr;
1998 int error;
1999 xfs_fsblock_t firstblock;
2000 xfs_bmap_free_t flist;
2001 char fname[MAXNAMELEN + 1];
2002 freetab_t *freetab;
2003 int i;
2004 int ino_offset;
33165ec3 2005 xfs_ino_t inum;
2bd0ea18
NS
2006 ino_tree_node_t *irec;
2007 int junkit;
2008 int lastfree;
2009 int len;
2010 int nbad;
2011 int needlog;
2012 int needscan;
2013 xfs_ino_t parent;
2014 char *ptr;
2015 xfs_trans_t *tp;
2016 int wantmagic;
2017
2018 bp = *bpp;
2019 d = bp->data;
2020 ptr = (char *)d->u;
2021 nbad = 0;
2022 needscan = needlog = 0;
9d7d6241 2023 junkit = 0;
2bd0ea18
NS
2024 freetab = *freetabp;
2025 if (isblock) {
f302e9e4 2026 btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d);
46eca962 2027 blp = XFS_DIR2_BLOCK_LEAF_P(btp);
2bd0ea18
NS
2028 endptr = (char *)blp;
2029 if (endptr > (char *)btp)
2030 endptr = (char *)btp;
2031 wantmagic = XFS_DIR2_BLOCK_MAGIC;
2032 } else {
2033 endptr = (char *)d + mp->m_dirblksize;
2034 wantmagic = XFS_DIR2_DATA_MAGIC;
2035 }
2036 db = XFS_DIR2_DA_TO_DB(mp, da_bno);
9d7d6241
NS
2037
2038 /* check for data block beyond expected end */
2bd0ea18
NS
2039 if (freetab->naents <= db) {
2040 struct freetab_ent e;
2041
2042 *freetabp = freetab = realloc(freetab, FREETAB_SIZE(db + 1));
2043 if (!freetab) {
2044 do_error(
507f4e33 2045 _("realloc failed in longform_dir2_entry_check_data (%u bytes)\n"),
2bd0ea18 2046 FREETAB_SIZE(db + 1));
2bd0ea18
NS
2047 }
2048 e.v = NULLDATAOFF;
2049 e.s = 0;
2050 for (i = freetab->naents; i < db; i++)
2051 freetab->ents[i] = e;
2052 freetab->naents = db + 1;
2053 }
9d7d6241
NS
2054
2055 /* check the data block */
2bd0ea18 2056 while (ptr < endptr) {
9d7d6241
NS
2057
2058 /* check for freespace */
2bd0ea18 2059 dup = (xfs_dir2_data_unused_t *)ptr;
9d7d6241
NS
2060 if (XFS_DIR2_DATA_FREE_TAG ==
2061 INT_GET(dup->freetag, ARCH_CONVERT)) {
2062
2063 /* check for invalid freespace length */
2064 if (ptr + INT_GET(dup->length, ARCH_CONVERT) > endptr ||
2065 INT_GET(dup->length, ARCH_CONVERT) == 0 ||
2066 (INT_GET(dup->length, ARCH_CONVERT) &
2067 (XFS_DIR2_DATA_ALIGN - 1)))
2bd0ea18 2068 break;
9d7d6241
NS
2069
2070 /* check for invalid tag */
46eca962
NS
2071 if (INT_GET(*XFS_DIR2_DATA_UNUSED_TAG_P(dup),
2072 ARCH_CONVERT) != (char *)dup - (char *)d)
2bd0ea18 2073 break;
9d7d6241
NS
2074
2075 /* check for block with no data entries */
2076 if ((ptr == (char *)d->u) &&
2077 (ptr + INT_GET(dup->length, ARCH_CONVERT) >=
2078 endptr)) {
2079 junkit = 1;
2080 *num_illegal += 1;
2081 break;
2082 }
2083
2084 /* continue at the end of the freespace */
2bd0ea18
NS
2085 ptr += INT_GET(dup->length, ARCH_CONVERT);
2086 if (ptr >= endptr)
2087 break;
2088 }
9d7d6241
NS
2089
2090 /* validate data entry size */
2bd0ea18
NS
2091 dep = (xfs_dir2_data_entry_t *)ptr;
2092 if (ptr + XFS_DIR2_DATA_ENTSIZE(dep->namelen) > endptr)
2093 break;
9d7d6241
NS
2094 if (INT_GET(*XFS_DIR2_DATA_ENTRY_TAG_P(dep), ARCH_CONVERT) !=
2095 (char *)dep - (char *)d)
2bd0ea18
NS
2096 break;
2097 ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
2098 }
9d7d6241
NS
2099
2100 /* did we find an empty or corrupt block? */
2bd0ea18 2101 if (ptr != endptr) {
9d7d6241 2102 if (junkit) {
507f4e33
NS
2103 do_warn(
2104 _("empty data block %u in directory inode %llu: "),
9d7d6241
NS
2105 da_bno, ip->i_ino);
2106 } else {
507f4e33 2107 do_warn(_("corrupt block %u in directory inode %llu: "),
9d7d6241
NS
2108 da_bno, ip->i_ino);
2109 }
2bd0ea18 2110 if (!no_modify) {
507f4e33 2111 do_warn(_("junking block\n"));
2bd0ea18
NS
2112 dir2_kill_block(mp, ip, da_bno, bp);
2113 } else {
507f4e33 2114 do_warn(_("would junk block\n"));
2bd0ea18
NS
2115 libxfs_da_brelse(NULL, bp);
2116 }
2117 freetab->ents[db].v = NULLDATAOFF;
2118 *bpp = NULL;
2119 return;
2120 }
9d7d6241
NS
2121
2122 /* update number of data blocks processed */
2123 if (freetab->nents < db + 1)
2124 freetab->nents = db + 1;
2125
2bd0ea18
NS
2126 tp = libxfs_trans_alloc(mp, 0);
2127 error = libxfs_trans_reserve(tp, 0, XFS_REMOVE_LOG_RES(mp), 0,
2128 XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT);
2129 if (error)
2130 res_failed(error);
2131 libxfs_trans_ijoin(tp, ip, 0);
2132 libxfs_trans_ihold(tp, ip);
2133 libxfs_da_bjoin(tp, bp);
33165ec3 2134 libxfs_da_bhold(tp, bp);
2bd0ea18
NS
2135 XFS_BMAP_INIT(&flist, &firstblock);
2136 if (INT_GET(d->hdr.magic, ARCH_CONVERT) != wantmagic) {
507f4e33
NS
2137 do_warn(_("bad directory block magic # %#x for directory inode "
2138 "%llu block %d: "),
2bd0ea18
NS
2139 INT_GET(d->hdr.magic, ARCH_CONVERT), ip->i_ino, da_bno);
2140 if (!no_modify) {
507f4e33 2141 do_warn(_("fixing magic # to %#x\n"), wantmagic);
2bd0ea18
NS
2142 INT_SET(d->hdr.magic, ARCH_CONVERT, wantmagic);
2143 needlog = 1;
2144 } else
507f4e33 2145 do_warn(_("would fix magic # to %#x\n"), wantmagic);
2bd0ea18
NS
2146 }
2147 lastfree = 0;
2148 ptr = (char *)d->u;
2149 /*
2150 * look at each entry. reference inode pointed to by each
2151 * entry in the incore inode tree.
2152 * if not a directory, set reached flag, increment link count
2153 * if a directory and reached, mark entry as to be deleted.
2154 * if a directory, check to see if recorded parent
2155 * matches current inode #,
2156 * if so, then set reached flag, increment link count
2157 * of current and child dir inodes, push the child
2158 * directory inode onto the directory stack.
2159 * if current inode != parent, then mark entry to be deleted.
2160 */
2161 while (ptr < endptr) {
2162 dup = (xfs_dir2_data_unused_t *)ptr;
507f4e33 2163 if (INT_GET(dup->freetag, ARCH_CONVERT) ==
33165ec3 2164 XFS_DIR2_DATA_FREE_TAG) {
2bd0ea18 2165 if (lastfree) {
507f4e33
NS
2166 do_warn(_("directory inode %llu block %u has "
2167 "consecutive free entries: "),
2bd0ea18
NS
2168 ip->i_ino, da_bno);
2169 if (!no_modify) {
507f4e33 2170 do_warn(_("joining together\n"));
2bd0ea18
NS
2171 len = INT_GET(dup->length, ARCH_CONVERT);
2172 libxfs_dir2_data_use_free(tp, bp, dup,
2173 ptr - (char *)d, len, &needlog,
2174 &needscan);
2175 libxfs_dir2_data_make_free(tp, bp,
2176 ptr - (char *)d, len, &needlog,
2177 &needscan);
2178 } else
507f4e33 2179 do_warn(_("would join together\n"));
2bd0ea18
NS
2180 }
2181 ptr += INT_GET(dup->length, ARCH_CONVERT);
2182 lastfree = 1;
2183 continue;
2184 }
2185 addr = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, db, ptr - (char *)d);
2186 dep = (xfs_dir2_data_entry_t *)ptr;
2187 ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
33165ec3 2188 inum = INT_GET(dep->inumber, ARCH_CONVERT);
2bd0ea18 2189 lastfree = 0;
2bd0ea18
NS
2190 /*
2191 * skip bogus entries (leading '/'). they'll be deleted
c7f277c9
NS
2192 * later. must still log it, else we leak references to
2193 * buffers.
2bd0ea18
NS
2194 */
2195 if (dep->name[0] == '/') {
2196 nbad++;
c7f277c9
NS
2197 if (!no_modify)
2198 libxfs_dir2_data_log_entry(tp, bp, dep);
2bd0ea18
NS
2199 continue;
2200 }
2556c98b 2201
2bd0ea18
NS
2202 bcopy(dep->name, fname, dep->namelen);
2203 fname[dep->namelen] = '\0';
33165ec3 2204 ASSERT(inum != NULLFSINO);
6c39a3cb
BN
2205
2206 irec = find_inode_rec(XFS_INO_TO_AGNO(mp, inum),
2207 XFS_INO_TO_AGINO(mp, inum));
2208 if (irec == NULL) {
2209 nbad++;
2210 if (entry_junked(_("entry \"%s\" in directory inode "
2211 "%llu points to non-existent inode %llu"),
2212 fname, ip->i_ino, inum)) {
2213 dep->name[0] = '/';
2214 libxfs_dir2_data_log_entry(tp, bp, dep);
2215 }
2216 continue;
2217 }
2218 ino_offset = XFS_INO_TO_AGINO(mp, inum) - irec->ino_startnum;
2219
2220 /*
2221 * if it's a free inode, blow out the entry.
2222 * by now, any inode that we think is free
2223 * really is free.
2224 */
2225 if (is_inode_free(irec, ino_offset)) {
2226 nbad++;
2227 if (entry_junked(_("entry \"%s\" in directory inode "
2228 "%llu points to free inode %llu"),
2229 fname, ip->i_ino, inum)) {
2230 dep->name[0] = '/';
2231 libxfs_dir2_data_log_entry(tp, bp, dep);
2232 }
2233 continue;
2234 }
2235
2236 /*
2237 * check if this inode is lost+found dir in the root
2238 */
2239 if (inum == mp->m_sb.sb_rootino && strcmp(fname, ORPHANAGE) == 0) {
2240 /*
2241 * if it's not a directory, trash it
2242 */
2243 if (!inode_isadir(irec, ino_offset)) {
2244 nbad++;
2245 if (entry_junked(_("%s (ino %llu) in root "
2246 "(%llu) is not a directory"),
2247 ORPHANAGE, inum, ip->i_ino)) {
2248 dep->name[0] = '/';
2249 libxfs_dir2_data_log_entry(tp, bp, dep);
2250 }
2251 continue;
2252 }
2253 /*
2254 * if this is a dup, it will be picked up below,
2255 * otherwise, mark it as the orphanage for later.
2256 */
2257 if (!orphanage_ino)
2258 orphanage_ino = inum;
2259 }
2260 /*
2261 * check for duplicate names in directory.
2262 */
2263 if (!dir_hash_add(hashtab, addr, inum, dep->namelen,
2264 dep->name)) {
2265 nbad++;
2266 if (entry_junked(_("entry \"%s\" (ino %llu) in dir "
2267 "%llu is a duplicate name"),
2268 fname, inum, ip->i_ino)) {
2269 dep->name[0] = '/';
2270 libxfs_dir2_data_log_entry(tp, bp, dep);
2271 }
2272 if (inum == orphanage_ino)
2273 orphanage_ino = 0;
2274 continue;
2275 }
2276
2bd0ea18
NS
2277 /*
2278 * skip the '..' entry since it's checked when the
2279 * directory is reached by something else. if it never
2280 * gets reached, it'll be moved to the orphanage and we'll
6fa00c33
BN
2281 * take care of it then. If it doesn't exist at all, the
2282 * directory needs to be rebuilt first before being added
2283 * to the orphanage.
2bd0ea18
NS
2284 */
2285 if (dep->namelen == 2 && dep->name[0] == '.' &&
6fa00c33
BN
2286 dep->name[1] == '.') {
2287 if (da_bno != 0) {
2288 /* ".." should be in the first block */
2289 nbad++;
2290 if (entry_junked(_("entry \"%s\" (ino %llu) "
2291 "in dir %llu is not in the "
2292 "the first block"), fname,
2293 inum, ip->i_ino)) {
2294 dep->name[0] = '/';
2295 libxfs_dir2_data_log_entry(tp, bp, dep);
2296 }
2297 }
2bd0ea18 2298 continue;
6fa00c33 2299 }
33165ec3 2300 ASSERT(no_modify || !verify_inum(mp, inum));
2bd0ea18
NS
2301 /*
2302 * special case the . entry. we know there's only one
2303 * '.' and only '.' points to itself because bogus entries
2304 * got trashed in phase 3 if there were > 1.
2305 * bump up link count for '.' but don't set reached
2306 * until we're actually reached by another directory
2307 * '..' is already accounted for or will be taken care
2308 * of when directory is moved to orphanage.
2309 */
33165ec3 2310 if (ip->i_ino == inum) {
2bd0ea18
NS
2311 ASSERT(dep->name[0] == '.' && dep->namelen == 1);
2312 add_inode_ref(current_irec, current_ino_offset);
6fa00c33
BN
2313 if (da_bno != 0 || dep != (xfs_dir2_data_entry_t *)d->u) {
2314 /* "." should be the first entry */
2315 nbad++;
2316 if (entry_junked(_("entry \"%s\" in dir %llu is "
2317 "not the first entry"),
2318 fname, inum, ip->i_ino)) {
2319 dep->name[0] = '/';
2320 libxfs_dir2_data_log_entry(tp, bp, dep);
2321 }
2322 }
2bd0ea18
NS
2323 *need_dot = 0;
2324 continue;
2325 }
2bd0ea18
NS
2326 /*
2327 * skip entries with bogus inumbers if we're in no modify mode
2328 */
33165ec3 2329 if (no_modify && verify_inum(mp, inum))
2bd0ea18 2330 continue;
2bd0ea18
NS
2331 /*
2332 * check easy case first, regular inode, just bump
2333 * the link count and continue
2334 */
2335 if (!inode_isadir(irec, ino_offset)) {
2336 add_inode_reached(irec, ino_offset);
2337 continue;
2338 }
2339 parent = get_inode_parent(irec, ino_offset);
2340 ASSERT(parent != 0);
6c39a3cb 2341 junkit = 0;
2bd0ea18
NS
2342 /*
2343 * bump up the link counts in parent and child
2344 * directory but if the link doesn't agree with
2345 * the .. in the child, blow out the entry.
2346 * if the directory has already been reached,
2347 * blow away the entry also.
2348 */
2349 if (is_inode_reached(irec, ino_offset)) {
2350 junkit = 1;
507f4e33 2351 do_warn(
6c39a3cb 2352_("entry \"%s\" in dir %llu points to an already connected directory inode %llu\n"),
33165ec3 2353 fname, ip->i_ino, inum);
2bd0ea18
NS
2354 } else if (parent == ip->i_ino) {
2355 add_inode_reached(irec, ino_offset);
2356 add_inode_ref(current_irec, current_ino_offset);
6fa00c33
BN
2357 } else if (parent == NULLFSINO) {
2358 /* ".." was missing, but this entry refers to it,
2359 so, set it as the parent and mark for rebuild */
2360 do_warn(_("entry \"%s\" in dir ino %llu doesn't have a"
2361 " .. entry, will set it in ino %llu.\n"),
2362 fname, ip->i_ino, inum);
2363 set_inode_parent(irec, ino_offset, ip->i_ino);
2364 add_inode_reached(irec, ino_offset);
2365 add_inode_ref(current_irec, current_ino_offset);
2bd0ea18
NS
2366 } else {
2367 junkit = 1;
507f4e33 2368 do_warn(
6c39a3cb 2369_("entry \"%s\" in dir inode %llu inconsistent with .. value (%llu) in ino %llu\n"),
33165ec3 2370 fname, ip->i_ino, parent, inum);
2bd0ea18
NS
2371 }
2372 if (junkit) {
6c39a3cb
BN
2373 if (inum == orphanage_ino)
2374 orphanage_ino = 0;
2bd0ea18
NS
2375 junkit = 0;
2376 nbad++;
2377 if (!no_modify) {
2378 dep->name[0] = '/';
2379 libxfs_dir2_data_log_entry(tp, bp, dep);
6c39a3cb 2380 if (verbose)
507f4e33
NS
2381 do_warn(
2382 _("\twill clear entry \"%s\"\n"),
2bd0ea18
NS
2383 fname);
2384 } else {
507f4e33
NS
2385 do_warn(_("\twould clear entry \"%s\"\n"),
2386 fname);
2bd0ea18
NS
2387 }
2388 }
2389 }
2390 *num_illegal += nbad;
2391 if (needscan)
2392 libxfs_dir2_data_freescan(mp, d, &needlog, NULL);
2393 if (needlog)
2394 libxfs_dir2_data_log_header(tp, bp);
2395 libxfs_bmap_finish(&tp, &flist, firstblock, &committed);
2396 libxfs_trans_commit(tp, 0, 0);
2397 freetab->ents[db].v = INT_GET(d->hdr.bestfree[0].length, ARCH_CONVERT);
2398 freetab->ents[db].s = 0;
2399}
2400
2401/*
2402 * Check contents of leaf-form block.
2403 */
2556c98b 2404static int
2bd0ea18
NS
2405longform_dir2_check_leaf(
2406 xfs_mount_t *mp,
2407 xfs_inode_t *ip,
2408 dir_hash_tab_t *hashtab,
2409 freetab_t *freetab)
2410{
2411 int badtail;
2412 xfs_dir2_data_off_t *bestsp;
2413 xfs_dabuf_t *bp;
2414 xfs_dablk_t da_bno;
2415 int i;
2416 xfs_dir2_leaf_t *leaf;
2417 xfs_dir2_leaf_tail_t *ltp;
2418 int seeval;
2419
2420 da_bno = mp->m_dirleafblk;
2421 if (libxfs_da_read_bufr(NULL, ip, da_bno, -1, &bp, XFS_DATA_FORK)) {
507f4e33 2422 do_error(_("can't read block %u for directory inode %llu\n"),
2bd0ea18
NS
2423 da_bno, ip->i_ino);
2424 /* NOTREACHED */
2425 }
2426 leaf = bp->data;
2427 ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
46eca962 2428 bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
507f4e33
NS
2429 if (INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) !=
2430 XFS_DIR2_LEAF1_MAGIC ||
2431 INT_GET(leaf->hdr.info.forw, ARCH_CONVERT) ||
2432 INT_GET(leaf->hdr.info.back, ARCH_CONVERT) ||
2433 INT_GET(leaf->hdr.count, ARCH_CONVERT) <
2434 INT_GET(leaf->hdr.stale, ARCH_CONVERT) ||
2435 INT_GET(leaf->hdr.count, ARCH_CONVERT) >
2436 XFS_DIR2_MAX_LEAF_ENTS(mp) ||
2437 (char *)&leaf->ents[INT_GET(leaf->hdr.count, ARCH_CONVERT)] >
2438 (char *)bestsp) {
2439 do_warn(
2440 _("leaf block %u for directory inode %llu bad header\n"),
2bd0ea18
NS
2441 da_bno, ip->i_ino);
2442 libxfs_da_brelse(NULL, bp);
2443 return 1;
2444 }
507f4e33
NS
2445 seeval = dir_hash_see_all(hashtab, leaf->ents,
2446 INT_GET(leaf->hdr.count, ARCH_CONVERT),
2bd0ea18
NS
2447 INT_GET(leaf->hdr.stale, ARCH_CONVERT));
2448 if (dir_hash_check(hashtab, ip, seeval)) {
2449 libxfs_da_brelse(NULL, bp);
2450 return 1;
2451 }
2452 badtail = freetab->nents != INT_GET(ltp->bestcount, ARCH_CONVERT);
2453 for (i = 0; !badtail && i < INT_GET(ltp->bestcount, ARCH_CONVERT); i++) {
2454 freetab->ents[i].s = 1;
2455 badtail = freetab->ents[i].v != INT_GET(bestsp[i], ARCH_CONVERT);
2456 }
2457 if (badtail) {
507f4e33 2458 do_warn(_("leaf block %u for directory inode %llu bad tail\n"),
2bd0ea18
NS
2459 da_bno, ip->i_ino);
2460 libxfs_da_brelse(NULL, bp);
2461 return 1;
2462 }
2463 libxfs_da_brelse(NULL, bp);
2464 return 0;
2465}
2466
2467/*
2468 * Check contents of the node blocks (leaves)
2469 * Looks for matching hash values for the data entries.
2470 */
2556c98b 2471static int
2bd0ea18
NS
2472longform_dir2_check_node(
2473 xfs_mount_t *mp,
2474 xfs_inode_t *ip,
2475 dir_hash_tab_t *hashtab,
2476 freetab_t *freetab)
2477{
2478 xfs_dabuf_t *bp;
2479 xfs_dablk_t da_bno;
2480 xfs_dir2_db_t fdb;
2481 xfs_dir2_free_t *free;
2482 int i;
2483 xfs_dir2_leaf_t *leaf;
2484 xfs_fileoff_t next_da_bno;
2485 int seeval = 0;
2486 int used;
0f012a4c 2487
2bd0ea18
NS
2488 for (da_bno = mp->m_dirleafblk, next_da_bno = 0;
2489 next_da_bno != NULLFILEOFF && da_bno < mp->m_dirfreeblk;
2490 da_bno = (xfs_dablk_t)next_da_bno) {
2491 next_da_bno = da_bno + mp->m_dirblkfsbs - 1;
0f012a4c 2492 if (libxfs_bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK))
2bd0ea18
NS
2493 break;
2494 if (libxfs_da_read_bufr(NULL, ip, da_bno, -1, &bp,
2495 XFS_DATA_FORK)) {
33165ec3
BN
2496 do_warn(
2497 _("can't read leaf block %u for directory inode %llu\n"),
2bd0ea18 2498 da_bno, ip->i_ino);
33165ec3 2499 return 1;
2bd0ea18
NS
2500 }
2501 leaf = bp->data;
507f4e33
NS
2502 if (INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) !=
2503 XFS_DIR2_LEAFN_MAGIC) {
2504 if (INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) ==
2505 XFS_DA_NODE_MAGIC) {
2bd0ea18
NS
2506 libxfs_da_brelse(NULL, bp);
2507 continue;
2508 }
507f4e33
NS
2509 do_warn(_("unknown magic number %#x for block %u in "
2510 "directory inode %llu\n"),
2511 INT_GET(leaf->hdr.info.magic, ARCH_CONVERT),
2512 da_bno, ip->i_ino);
2bd0ea18
NS
2513 libxfs_da_brelse(NULL, bp);
2514 return 1;
2515 }
507f4e33
NS
2516 if (INT_GET(leaf->hdr.count, ARCH_CONVERT) <
2517 INT_GET(leaf->hdr.stale, ARCH_CONVERT) ||
2518 INT_GET(leaf->hdr.count, ARCH_CONVERT) >
2519 XFS_DIR2_MAX_LEAF_ENTS(mp)) {
2520 do_warn(_("leaf block %u for directory inode %llu bad "
2521 "header\n"),
2bd0ea18
NS
2522 da_bno, ip->i_ino);
2523 libxfs_da_brelse(NULL, bp);
2524 return 1;
2525 }
2526 seeval = dir_hash_see_all(hashtab, leaf->ents, INT_GET(leaf->hdr.count, ARCH_CONVERT),
2527 INT_GET(leaf->hdr.stale, ARCH_CONVERT));
2528 libxfs_da_brelse(NULL, bp);
0f012a4c 2529 if (seeval != DIR_HASH_CK_OK)
2bd0ea18
NS
2530 return 1;
2531 }
0f012a4c 2532 if (dir_hash_check(hashtab, ip, seeval))
2bd0ea18 2533 return 1;
0f012a4c 2534
2bd0ea18
NS
2535 for (da_bno = mp->m_dirfreeblk, next_da_bno = 0;
2536 next_da_bno != NULLFILEOFF;
2537 da_bno = (xfs_dablk_t)next_da_bno) {
2538 next_da_bno = da_bno + mp->m_dirblkfsbs - 1;
0f012a4c 2539 if (libxfs_bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK))
2bd0ea18
NS
2540 break;
2541 if (libxfs_da_read_bufr(NULL, ip, da_bno, -1, &bp,
2542 XFS_DATA_FORK)) {
33165ec3
BN
2543 do_warn(
2544 _("can't read freespace block %u for directory inode %llu\n"),
2bd0ea18 2545 da_bno, ip->i_ino);
33165ec3 2546 return 1;
2bd0ea18
NS
2547 }
2548 free = bp->data;
2549 fdb = XFS_DIR2_DA_TO_DB(mp, da_bno);
507f4e33
NS
2550 if (INT_GET(free->hdr.magic, ARCH_CONVERT) !=
2551 XFS_DIR2_FREE_MAGIC ||
2bd0ea18 2552 INT_GET(free->hdr.firstdb, ARCH_CONVERT) !=
507f4e33
NS
2553 (fdb - XFS_DIR2_FREE_FIRSTDB(mp)) *
2554 XFS_DIR2_MAX_FREE_BESTS(mp) ||
2555 INT_GET(free->hdr.nvalid, ARCH_CONVERT) <
2556 INT_GET(free->hdr.nused, ARCH_CONVERT)) {
2557 do_warn(_("free block %u for directory inode %llu bad "
2558 "header\n"),
2bd0ea18
NS
2559 da_bno, ip->i_ino);
2560 libxfs_da_brelse(NULL, bp);
2561 return 1;
2562 }
2563 for (i = used = 0; i < INT_GET(free->hdr.nvalid, ARCH_CONVERT); i++) {
507f4e33
NS
2564 if (i + INT_GET(free->hdr.firstdb, ARCH_CONVERT) >=
2565 freetab->nents ||
2566 freetab->ents[i + INT_GET(free->hdr.firstdb,
2567 ARCH_CONVERT)].v !=
2bd0ea18 2568 INT_GET(free->bests[i], ARCH_CONVERT)) {
507f4e33
NS
2569 do_warn(
2570 _("free block %u entry %i for directory ino %llu bad\n"),
2bd0ea18
NS
2571 da_bno, i, ip->i_ino);
2572 libxfs_da_brelse(NULL, bp);
2573 return 1;
2574 }
2575 used += INT_GET(free->bests[i], ARCH_CONVERT) != NULLDATAOFF;
2576 freetab->ents[i + INT_GET(free->hdr.firstdb, ARCH_CONVERT)].s = 1;
2577 }
2578 if (used != INT_GET(free->hdr.nused, ARCH_CONVERT)) {
507f4e33
NS
2579 do_warn(_("free block %u for directory inode %llu bad "
2580 "nused\n"),
2bd0ea18
NS
2581 da_bno, ip->i_ino);
2582 libxfs_da_brelse(NULL, bp);
2583 return 1;
2584 }
2585 libxfs_da_brelse(NULL, bp);
2586 }
2587 for (i = 0; i < freetab->nents; i++) {
4b6a2d8e
NS
2588 if ((freetab->ents[i].s == 0) &&
2589 (freetab->ents[i].v != NULLDATAOFF)) {
507f4e33
NS
2590 do_warn(_("missing freetab entry %u for "
2591 "directory inode %llu\n"),
2bd0ea18
NS
2592 i, ip->i_ino);
2593 return 1;
2594 }
2595 }
2596 return 0;
2597}
2598
2599/*
33165ec3
BN
2600 * If a directory is corrupt, we need to read in as many entries as possible,
2601 * destroy the entry and create a new one with recovered name/inode pairs.
2602 * (ie. get libxfs to do all the grunt work)
2bd0ea18 2603 */
2556c98b 2604static void
2bd0ea18
NS
2605longform_dir2_entry_check(xfs_mount_t *mp,
2606 xfs_ino_t ino,
2607 xfs_inode_t *ip,
2608 int *num_illegal,
2609 int *need_dot,
2bd0ea18 2610 ino_tree_node_t *irec,
64c54486 2611 int ino_offset,
33165ec3 2612 dir_hash_tab_t *hashtab)
2bd0ea18
NS
2613{
2614 xfs_dir2_block_t *block;
2615 xfs_dir2_leaf_entry_t *blp;
33165ec3 2616 xfs_dabuf_t **bplist;
2bd0ea18
NS
2617 xfs_dir2_block_tail_t *btp;
2618 xfs_dablk_t da_bno;
2619 freetab_t *freetab;
95dff16b 2620 int num_bps;
2bd0ea18
NS
2621 int i;
2622 int isblock;
2623 int isleaf;
2624 xfs_fileoff_t next_da_bno;
2625 int seeval;
2626 int fixit;
95dff16b 2627 xfs_dir2_db_t db;
2bd0ea18
NS
2628
2629 *need_dot = 1;
2630 freetab = malloc(FREETAB_SIZE(ip->i_d.di_size / mp->m_dirblksize));
2631 if (!freetab) {
2632 do_error(
507f4e33 2633 _("malloc failed in longform_dir2_entry_check (%u bytes)\n"),
2bd0ea18
NS
2634 FREETAB_SIZE(ip->i_d.di_size / mp->m_dirblksize));
2635 exit(1);
2636 }
2637 freetab->naents = ip->i_d.di_size / mp->m_dirblksize;
2638 freetab->nents = 0;
2639 for (i = 0; i < freetab->naents; i++) {
2640 freetab->ents[i].v = NULLDATAOFF;
2641 freetab->ents[i].s = 0;
2642 }
95dff16b
BN
2643 num_bps = freetab->naents;
2644 bplist = calloc(num_bps, sizeof(xfs_dabuf_t*));
9d7d6241 2645 /* is this a block, leaf, or node directory? */
2bd0ea18
NS
2646 libxfs_dir2_isblock(NULL, ip, &isblock);
2647 libxfs_dir2_isleaf(NULL, ip, &isleaf);
9d7d6241 2648
33165ec3 2649 /* check directory "data" blocks (ie. name/inode pairs) */
2bd0ea18
NS
2650 for (da_bno = 0, next_da_bno = 0;
2651 next_da_bno != NULLFILEOFF && da_bno < mp->m_dirleafblk;
2652 da_bno = (xfs_dablk_t)next_da_bno) {
2653 next_da_bno = da_bno + mp->m_dirblkfsbs - 1;
2654 if (libxfs_bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK))
2655 break;
95dff16b
BN
2656 db = XFS_DIR2_DA_TO_DB(mp, da_bno);
2657 if (db >= num_bps) {
2658 /* more data blocks than expected */
2659 num_bps = db + 1;
2660 bplist = realloc(bplist, num_bps * sizeof(xfs_dabuf_t*));
0f012a4c 2661 if (!bplist)
95dff16b
BN
2662 do_error(
2663 _("realloc failed in longform_dir2_entry_check (%u bytes)\n"),
2664 num_bps * sizeof(xfs_dabuf_t*));
2665 }
0f012a4c 2666 if (libxfs_da_read_bufr(NULL, ip, da_bno, -1, &bplist[db],
33165ec3
BN
2667 XFS_DATA_FORK)) {
2668 do_warn(_(
2669 "can't read data block %u for directory inode %llu\n"),
2bd0ea18 2670 da_bno, ino);
95dff16b 2671 *num_illegal += 1;
33165ec3 2672 continue; /* try and read all "data" blocks */
2bd0ea18
NS
2673 }
2674 longform_dir2_entry_check_data(mp, ip, num_illegal, need_dot,
2556c98b 2675 irec, ino_offset, &bplist[db], hashtab,
33165ec3 2676 &freetab, da_bno, isblock);
2bd0ea18 2677 }
6fa00c33 2678 fixit = (*num_illegal != 0) || dir2_is_badino(ino) || *need_dot;
9d7d6241
NS
2679
2680 /* check btree and freespace */
2bd0ea18 2681 if (isblock) {
33165ec3 2682 block = bplist[0]->data;
2bd0ea18 2683 btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
46eca962 2684 blp = XFS_DIR2_BLOCK_LEAF_P(btp);
0f012a4c
BN
2685 seeval = dir_hash_see_all(hashtab, blp,
2686 INT_GET(btp->count, ARCH_CONVERT),
33165ec3 2687 INT_GET(btp->stale, ARCH_CONVERT));
2bd0ea18
NS
2688 if (dir_hash_check(hashtab, ip, seeval))
2689 fixit |= 1;
2bd0ea18
NS
2690 } else if (isleaf) {
2691 fixit |= longform_dir2_check_leaf(mp, ip, hashtab, freetab);
2692 } else {
2693 fixit |= longform_dir2_check_node(mp, ip, hashtab, freetab);
2694 }
33165ec3
BN
2695 if (!no_modify && fixit) {
2696 dir_hash_dup_names(hashtab);
0f012a4c 2697 for (i = 0; i < freetab->naents; i++)
33165ec3
BN
2698 if (bplist[i])
2699 libxfs_da_brelse(NULL, bplist[i]);
6fa00c33 2700 longform_dir2_rebuild(mp, ino, ip, irec, ino_offset, hashtab);
33165ec3 2701 *num_illegal = 0;
6fa00c33 2702 *need_dot = 0;
33165ec3 2703 } else {
0f012a4c 2704 for (i = 0; i < freetab->naents; i++)
33165ec3
BN
2705 if (bplist[i])
2706 libxfs_da_brelse(NULL, bplist[i]);
2707 }
0f012a4c 2708
95dff16b 2709 free(bplist);
2bd0ea18
NS
2710 free(freetab);
2711}
2712
2713/*
2714 * shortform directory processing routines -- entry verification and
2715 * bad entry deletion (pruning).
2716 */
2556c98b 2717static void
2bd0ea18
NS
2718shortform_dir_entry_check(xfs_mount_t *mp,
2719 xfs_ino_t ino,
2720 xfs_inode_t *ip,
2721 int *ino_dirty,
2bd0ea18 2722 ino_tree_node_t *current_irec,
64c54486 2723 int current_ino_offset,
33165ec3 2724 dir_hash_tab_t *hashtab)
2bd0ea18
NS
2725{
2726 xfs_ino_t lino;
2727 xfs_ino_t parent;
2728 xfs_dir_shortform_t *sf;
2729 xfs_dir_sf_entry_t *sf_entry, *next_sfe, *tmp_sfe;
2730 xfs_ifork_t *ifp;
2731 ino_tree_node_t *irec;
2732 int max_size;
2733 int ino_offset;
2734 int i;
2735 int junkit;
2736 int tmp_len;
2737 int tmp_elen;
2738 int bad_sfnamelen;
2739 int namelen;
2740 int bytes_deleted;
2741 char fname[MAXNAMELEN + 1];
2742
2743 ifp = &ip->i_df;
2744 sf = (xfs_dir_shortform_t *) ifp->if_u1.if_data;
2745 *ino_dirty = 0;
2746 bytes_deleted = 0;
2747
2748 max_size = ifp->if_bytes;
2749 ASSERT(ip->i_d.di_size <= ifp->if_bytes);
2750
2751 /*
2752 * no '.' entry in shortform dirs, just bump up ref count by 1
2753 * '..' was already (or will be) accounted for and checked when
2754 * the directory is reached or will be taken care of when the
2755 * directory is moved to orphanage.
2756 */
2757 add_inode_ref(current_irec, current_ino_offset);
2758
2759 /*
2760 * now run through entries, stop at first bad entry, don't need
2761 * to skip over '..' since that's encoded in its own field and
2762 * no need to worry about '.' since it doesn't exist.
2763 */
2764 sf_entry = next_sfe = &sf->list[0];
dfc130f3 2765 if (sf == NULL) {
2bd0ea18 2766 junkit = 1;
507f4e33
NS
2767 do_warn(_("shortform dir inode %llu has null data entries \n"),
2768 ino);
2bd0ea18
NS
2769
2770 }
2771 else {
2772 for (i = 0; i < INT_GET(sf->hdr.count, ARCH_CONVERT) && max_size >
2773 (__psint_t)next_sfe - (__psint_t)sf;
2774 sf_entry = next_sfe, i++) {
2775 junkit = 0;
2776 bad_sfnamelen = 0;
2777 tmp_sfe = NULL;
2778
46eca962 2779 XFS_DIR_SF_GET_DIRINO(&sf_entry->inumber, &lino);
2bd0ea18
NS
2780
2781 namelen = sf_entry->namelen;
2782
2783 ASSERT(no_modify || namelen > 0);
2784
2785 if (no_modify && namelen == 0) {
2786 /*
2787 * if we're really lucky, this is
2788 * the last entry in which case we
2789 * can use the dir size to set the
2790 * namelen value. otherwise, forget
2791 * it because we're not going to be
2792 * able to find the next entry.
2793 */
2794 bad_sfnamelen = 1;
2795
2796 if (i == INT_GET(sf->hdr.count, ARCH_CONVERT) - 1) {
2797 namelen = ip->i_d.di_size -
2798 ((__psint_t) &sf_entry->name[0] -
2799 (__psint_t) sf);
2800 } else {
2801 /*
2802 * don't process the rest of the directory,
2803 * break out of processing looop
2804 */
2805 break;
2806 }
2807 } else if (no_modify && (__psint_t) sf_entry - (__psint_t) sf +
2808 + XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry)
2809 > ip->i_d.di_size) {
2810 bad_sfnamelen = 1;
2811
2812 if (i == INT_GET(sf->hdr.count, ARCH_CONVERT) - 1) {
2813 namelen = ip->i_d.di_size -
2814 ((__psint_t) &sf_entry->name[0] -
2815 (__psint_t) sf);
2816 } else {
2817 /*
2818 * don't process the rest of the directory,
2819 * break out of processing looop
2820 */
2821 break;
2822 }
2823 }
2824
2825 bcopy(sf_entry->name, fname, sf_entry->namelen);
2826 fname[sf_entry->namelen] = '\0';
2827
2828 ASSERT(no_modify || lino != NULLFSINO);
2829 ASSERT(no_modify || !verify_inum(mp, lino));
2830
2bd0ea18
NS
2831 irec = find_inode_rec(XFS_INO_TO_AGNO(mp, lino),
2832 XFS_INO_TO_AGINO(mp, lino));
6c39a3cb
BN
2833 if (irec == NULL) {
2834 do_warn(_("entry \"%s\" in shortform dir %llu "
2835 "references non-existent ino %llu"),
2bd0ea18 2836 fname, ino, lino);
6c39a3cb 2837 goto do_junkit;
2bd0ea18 2838 }
2bd0ea18 2839 ino_offset = XFS_INO_TO_AGINO(mp, lino) - irec->ino_startnum;
0f012a4c 2840
2bd0ea18
NS
2841 /*
2842 * if it's a free inode, blow out the entry.
2843 * by now, any inode that we think is free
2844 * really is free.
2845 */
6c39a3cb
BN
2846 if (!is_inode_free(irec, ino_offset)) {
2847 do_warn(_("entry \"%s\" in shortform dir inode %llu "
2848 "points to free inode %llu"), fname, ino, lino);
2849 goto do_junkit;
2850 }
2851 /*
2852 * check if this inode is lost+found dir in the root
2853 */
2854 if (ino == mp->m_sb.sb_rootino && strcmp(fname, ORPHANAGE) == 0) {
2bd0ea18 2855 /*
6c39a3cb 2856 * if it's not a directory, trash it
2bd0ea18 2857 */
6c39a3cb
BN
2858 if (!inode_isadir(irec, ino_offset)) {
2859 do_warn(_("%s (ino %llu) in root (%llu) is not "
2860 "a directory"), ORPHANAGE, lino, ino);
2861 goto do_junkit;
2bd0ea18 2862 }
64c54486 2863 /*
6c39a3cb
BN
2864 * if this is a dup, it will be picked up below,
2865 * otherwise, mark it as the orphanage for later.
0f012a4c 2866 */
6c39a3cb
BN
2867 if (!orphanage_ino)
2868 orphanage_ino = lino;
2869 }
2870 /*
2871 * check for duplicate names in directory.
2872 */
2873 if (!dir_hash_add(hashtab,
2874 (xfs_dir2_dataptr_t)(sf_entry - &sf->list[0]),
2875 lino, sf_entry->namelen, sf_entry->name)) {
2876 do_warn(_("entry \"%s\" (ino %llu) in dir %llu is a "
2877 "duplicate name"), fname, lino, ino);
2878 goto do_junkit;
2879 }
2880 if (!inode_isadir(irec, ino_offset)) {
2bd0ea18
NS
2881 /*
2882 * check easy case first, regular inode, just bump
2883 * the link count and continue
2884 */
2885 add_inode_reached(irec, ino_offset);
2886
2887 next_sfe = (xfs_dir_sf_entry_t *)
2888 ((__psint_t) sf_entry +
2889 XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry));
2890 continue;
2891 } else {
2892 parent = get_inode_parent(irec, ino_offset);
2893
2894 /*
2895 * bump up the link counts in parent and child.
2896 * directory but if the link doesn't agree with
2897 * the .. in the child, blow out the entry
2898 */
2899 if (is_inode_reached(irec, ino_offset)) {
2900 junkit = 1;
6c39a3cb
BN
2901 do_warn(_("entry \"%s\" in dir %llu references "
2902 "already connected dir ino %llu,\n"),
2bd0ea18
NS
2903 fname, ino, lino);
2904 } else if (parent == ino) {
2905 add_inode_reached(irec, ino_offset);
2906 add_inode_ref(current_irec, current_ino_offset);
6fa00c33
BN
2907 } else if (parent == NULLFSINO) {
2908 /* ".." was missing, but this entry refers to it,
2909 so, set it as the parent and mark for rebuild */
2910 do_warn(_("entry \"%s\" in dir ino %llu doesn't have a"
2911 " .. entry, will set it in ino %llu.\n"),
2912 fname, ino, lino);
2913 set_inode_parent(irec, ino_offset, ino);
2914 add_inode_reached(irec, ino_offset);
2915 add_inode_ref(current_irec, current_ino_offset);
2bd0ea18
NS
2916 } else {
2917 junkit = 1;
6c39a3cb
BN
2918 do_warn(_("entry \"%s\" in dir %llu not "
2919 "consistent with .. value (%llu) in "
2920 "dir ino %llu"),
2bd0ea18
NS
2921 fname, ino, parent, lino);
2922 }
2923 }
2bd0ea18 2924 if (junkit) {
6c39a3cb
BN
2925do_junkit:
2926 if (lino == orphanage_ino)
2927 orphanage_ino = 0;
2bd0ea18
NS
2928 if (!no_modify) {
2929 tmp_elen = XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry);
2930 tmp_sfe = (xfs_dir_sf_entry_t *)
2931 ((__psint_t) sf_entry + tmp_elen);
2932 tmp_len = max_size - ((__psint_t) tmp_sfe
2933 - (__psint_t) sf);
2934 max_size -= tmp_elen;
2935 bytes_deleted += tmp_elen;
2936
2937 memmove(sf_entry, tmp_sfe, tmp_len);
2938
2939 INT_MOD(sf->hdr.count, ARCH_CONVERT, -1);
2940 bzero((void *) ((__psint_t) sf_entry + tmp_len),
2941 tmp_elen);
2942
2943 /*
2944 * set the tmp value to the current
2945 * pointer so we'll process the entry
2946 * we just moved up
2947 */
2948 tmp_sfe = sf_entry;
2949
2950 /*
2951 * WARNING: drop the index i by one
2952 * so it matches the decremented count for
2953 * accurate comparisons in the loop test
2954 */
2955 i--;
2956
2957 *ino_dirty = 1;
2958
6c39a3cb
BN
2959 if (verbose)
2960 do_warn(_("junking entry\n"));
2961 else
2962 do_warn("\n");
2bd0ea18 2963 } else {
6c39a3cb 2964 do_warn(_("would junk entry\n"), fname);
2bd0ea18
NS
2965 }
2966 }
2967
2968 /*
2969 * go onto next entry unless we've just junked an
2970 * entry in which the current entry pointer points
2971 * to an unprocessed entry. have to take into entries
2972 * with bad namelen into account in no modify mode since we
2973 * calculate size based on next_sfe.
2974 */
2975 ASSERT(no_modify || bad_sfnamelen == 0);
2976
2977 next_sfe = (tmp_sfe == NULL)
2978 ? (xfs_dir_sf_entry_t *) ((__psint_t) sf_entry
2979 + ((!bad_sfnamelen)
2980 ? XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry)
2981 : sizeof(xfs_dir_sf_entry_t) - 1
2982 + namelen))
2983 : tmp_sfe;
2984 }
2985 }
2986
2987 /*
2988 * sync up sizes if required
2989 */
2990 if (*ino_dirty) {
2991 ASSERT(bytes_deleted > 0);
2992 ASSERT(!no_modify);
2993 libxfs_idata_realloc(ip, -bytes_deleted, XFS_DATA_FORK);
2994 ip->i_d.di_size -= bytes_deleted;
2995 }
2996
2997 if (ip->i_d.di_size != ip->i_df.if_bytes) {
2998 ASSERT(ip->i_df.if_bytes == (xfs_fsize_t)
2999 ((__psint_t) next_sfe - (__psint_t) sf));
3000 ip->i_d.di_size = (xfs_fsize_t)
3001 ((__psint_t) next_sfe - (__psint_t) sf);
3002 do_warn(
507f4e33 3003 _("setting size to %lld bytes to reflect junked entries\n"),
2bd0ea18
NS
3004 ip->i_d.di_size);
3005 *ino_dirty = 1;
3006 }
3007}
3008
3009/* ARGSUSED */
2556c98b 3010static void
2bd0ea18
NS
3011prune_sf_dir_entry(xfs_mount_t *mp, xfs_ino_t ino, xfs_inode_t *ip)
3012{
3013 /* REFERENCED */
3014 xfs_ino_t lino;
3015 xfs_dir_shortform_t *sf;
3016 xfs_dir_sf_entry_t *sf_entry, *next_sfe, *tmp_sfe;
3017 xfs_ifork_t *ifp;
3018 int max_size;
3019 int i;
3020 int tmp_len;
3021 int tmp_elen;
3022 int bytes_deleted;
3023 char fname[MAXNAMELEN + 1];
3024
3025 ifp = &ip->i_df;
3026 sf = (xfs_dir_shortform_t *) ifp->if_u1.if_data;
3027 bytes_deleted = 0;
3028
3029 max_size = ifp->if_bytes;
3030 ASSERT(ip->i_d.di_size <= ifp->if_bytes);
3031
3032 /*
3033 * now run through entries and delete every bad entry
3034 */
3035 sf_entry = next_sfe = &sf->list[0];
3036
3037 for (i = 0; i < INT_GET(sf->hdr.count, ARCH_CONVERT) && max_size >
3038 (__psint_t)next_sfe - (__psint_t)sf;
3039 sf_entry = next_sfe, i++) {
3040 tmp_sfe = NULL;
3041
46eca962 3042 XFS_DIR_SF_GET_DIRINO(&sf_entry->inumber, &lino);
2bd0ea18
NS
3043
3044 bcopy(sf_entry->name, fname, sf_entry->namelen);
3045 fname[sf_entry->namelen] = '\0';
3046
3047 if (sf_entry->name[0] == '/') {
3048 if (!no_modify) {
3049 tmp_elen = XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry);
3050 tmp_sfe = (xfs_dir_sf_entry_t *)
3051 ((__psint_t) sf_entry + tmp_elen);
3052 tmp_len = max_size - ((__psint_t) tmp_sfe
3053 - (__psint_t) sf);
3054 max_size -= tmp_elen;
3055 bytes_deleted += tmp_elen;
3056
3057 memmove(sf_entry, tmp_sfe, tmp_len);
3058
3059 INT_MOD(sf->hdr.count, ARCH_CONVERT, -1);
3060 bzero((void *) ((__psint_t) sf_entry + tmp_len),
3061 tmp_elen);
3062
3063 /*
3064 * set the tmp value to the current
3065 * pointer so we'll process the entry
3066 * we just moved up
3067 */
3068 tmp_sfe = sf_entry;
3069
3070 /*
3071 * WARNING: drop the index i by one
3072 * so it matches the decremented count for
3073 * accurate comparisons in the loop test
3074 */
3075 i--;
3076 }
3077 }
3078 next_sfe = (tmp_sfe == NULL)
3079 ? (xfs_dir_sf_entry_t *) ((__psint_t) sf_entry +
3080 XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry))
3081 : tmp_sfe;
3082 }
3083
3084 /*
3085 * sync up sizes if required
3086 */
3087 if (bytes_deleted > 0) {
3088 libxfs_idata_realloc(ip, -bytes_deleted, XFS_DATA_FORK);
3089 ip->i_d.di_size -= bytes_deleted;
3090 }
3091
3092 if (ip->i_d.di_size != ip->i_df.if_bytes) {
3093 ASSERT(ip->i_df.if_bytes == (xfs_fsize_t)
3094 ((__psint_t) next_sfe - (__psint_t) sf));
3095 ip->i_d.di_size = (xfs_fsize_t)
3096 ((__psint_t) next_sfe - (__psint_t) sf);
3097 do_warn(
507f4e33 3098 _("setting size to %lld bytes to reflect junked entries\n"),
2bd0ea18
NS
3099 ip->i_d.di_size);
3100 }
3101}
3102
3103/*
3104 * shortform directory v2 processing routines -- entry verification and
3105 * bad entry deletion (pruning).
3106 */
2556c98b 3107static void
2bd0ea18
NS
3108shortform_dir2_entry_check(xfs_mount_t *mp,
3109 xfs_ino_t ino,
3110 xfs_inode_t *ip,
3111 int *ino_dirty,
2bd0ea18 3112 ino_tree_node_t *current_irec,
64c54486 3113 int current_ino_offset,
33165ec3 3114 dir_hash_tab_t *hashtab)
2bd0ea18
NS
3115{
3116 xfs_ino_t lino;
3117 xfs_ino_t parent;
3118 xfs_dir2_sf_t *sfp;
3119 xfs_dir2_sf_entry_t *sfep, *next_sfep, *tmp_sfep;
3120 xfs_ifork_t *ifp;
3121 ino_tree_node_t *irec;
3122 int max_size;
3123 int ino_offset;
3124 int i;
3125 int junkit;
3126 int tmp_len;
3127 int tmp_elen;
3128 int bad_sfnamelen;
3129 int namelen;
3130 int bytes_deleted;
3131 char fname[MAXNAMELEN + 1];
3132 int i8;
3133
3134 ifp = &ip->i_df;
3135 sfp = (xfs_dir2_sf_t *) ifp->if_u1.if_data;
3136 *ino_dirty = 0;
e55d768a 3137 bytes_deleted = 0;
2bd0ea18
NS
3138
3139 max_size = ifp->if_bytes;
3140 ASSERT(ip->i_d.di_size <= ifp->if_bytes);
3141
3142 /*
3143 * no '.' entry in shortform dirs, just bump up ref count by 1
3144 * '..' was already (or will be) accounted for and checked when
3145 * the directory is reached or will be taken care of when the
3146 * directory is moved to orphanage.
3147 */
3148 add_inode_ref(current_irec, current_ino_offset);
3149
e55d768a
NS
3150 /*
3151 * Initialise i8 counter -- the parent inode number counts as well.
3152 */
46eca962 3153 i8 = (XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent) > XFS_DIR2_MAX_SHORT_INUM);
e55d768a 3154
2bd0ea18
NS
3155 /*
3156 * now run through entries, stop at first bad entry, don't need
3157 * to skip over '..' since that's encoded in its own field and
3158 * no need to worry about '.' since it doesn't exist.
3159 */
3160 sfep = next_sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
3161
3162 for (i = 0; i < INT_GET(sfp->hdr.count, ARCH_CONVERT) && max_size >
3163 (__psint_t)next_sfep - (__psint_t)sfp;
3164 sfep = next_sfep, i++) {
3165 junkit = 0;
3166 bad_sfnamelen = 0;
3167 tmp_sfep = NULL;
3168
46eca962 3169 lino = XFS_DIR2_SF_GET_INUMBER(sfp, XFS_DIR2_SF_INUMBERP(sfep));
2bd0ea18
NS
3170
3171 namelen = sfep->namelen;
3172
3173 ASSERT(no_modify || namelen > 0);
3174
3175 if (no_modify && namelen == 0) {
3176 /*
3177 * if we're really lucky, this is
3178 * the last entry in which case we
3179 * can use the dir size to set the
3180 * namelen value. otherwise, forget
3181 * it because we're not going to be
3182 * able to find the next entry.
3183 */
3184 bad_sfnamelen = 1;
3185
3186 if (i == INT_GET(sfp->hdr.count, ARCH_CONVERT) - 1) {
3187 namelen = ip->i_d.di_size -
3188 ((__psint_t) &sfep->name[0] -
3189 (__psint_t) sfp);
3190 } else {
3191 /*
3192 * don't process the rest of the directory,
3193 * break out of processing loop
3194 */
3195 break;
3196 }
3197 } else if (no_modify && (__psint_t) sfep - (__psint_t) sfp +
3198 + XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp, sfep)
3199 > ip->i_d.di_size) {
3200 bad_sfnamelen = 1;
3201
3202 if (i == INT_GET(sfp->hdr.count, ARCH_CONVERT) - 1) {
3203 namelen = ip->i_d.di_size -
3204 ((__psint_t) &sfep->name[0] -
3205 (__psint_t) sfp);
3206 } else {
3207 /*
3208 * don't process the rest of the directory,
3209 * break out of processing loop
3210 */
3211 break;
3212 }
3213 }
3214
3215 bcopy(sfep->name, fname, sfep->namelen);
3216 fname[sfep->namelen] = '\0';
3217
3218 ASSERT(no_modify || (lino != NULLFSINO && lino != 0));
3219 ASSERT(no_modify || !verify_inum(mp, lino));
3220
e55d768a
NS
3221 /*
3222 * Also skip entries with bogus inode numbers if we're
3223 * in no modify mode.
3224 */
3225
3226 if (no_modify && verify_inum(mp, lino)) {
2bd0ea18
NS
3227 next_sfep = (xfs_dir2_sf_entry_t *)
3228 ((__psint_t) sfep +
3229 XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp, sfep));
3230 continue;
3231 }
3232
3233 irec = find_inode_rec(XFS_INO_TO_AGNO(mp, lino),
3234 XFS_INO_TO_AGINO(mp, lino));
3235
6c39a3cb 3236 if (irec == NULL) {
507f4e33 3237 do_warn(_("entry \"%s\" in shortform directory %llu "
6c39a3cb 3238 "references non-existent inode %llu"),
2bd0ea18 3239 fname, ino, lino);
6c39a3cb 3240 goto do_junkit;
2bd0ea18
NS
3241 }
3242
2bd0ea18
NS
3243 ino_offset = XFS_INO_TO_AGINO(mp, lino) - irec->ino_startnum;
3244
3245 /*
3246 * if it's a free inode, blow out the entry.
3247 * by now, any inode that we think is free
3248 * really is free.
3249 */
3250 if (is_inode_free(irec, ino_offset)) {
6c39a3cb
BN
3251 do_warn(_("entry \"%s\" in shortform directory "
3252 "inode %llu points to free inode %llu"),
3253 fname, ino, lino);
3254 goto do_junkit;
3255 }
3256 /*
3257 * check if this inode is lost+found dir in the root
3258 */
3259 if (ino == mp->m_sb.sb_rootino && strcmp(fname, ORPHANAGE) == 0) {
2bd0ea18 3260 /*
6c39a3cb 3261 * if it's not a directory, trash it
2bd0ea18 3262 */
6c39a3cb
BN
3263 if (!inode_isadir(irec, ino_offset)) {
3264 do_warn(_("%s (ino %llu) in root (%llu) is not "
3265 "a directory"), ORPHANAGE, lino, ino);
3266 goto do_junkit;
2bd0ea18 3267 }
64c54486 3268 /*
6c39a3cb
BN
3269 * if this is a dup, it will be picked up below,
3270 * otherwise, mark it as the orphanage for later.
0f012a4c 3271 */
6c39a3cb
BN
3272 if (!orphanage_ino)
3273 orphanage_ino = lino;
3274 }
3275 /*
3276 * check for duplicate names in directory.
3277 */
3278 if (!dir_hash_add(hashtab, (xfs_dir2_dataptr_t)
3279 (sfep - XFS_DIR2_SF_FIRSTENTRY(sfp)),
3280 lino, sfep->namelen, sfep->name)) {
3281 do_warn(_("entry \"%s\" (ino %llu) in dir %llu is a "
3282 "duplicate name"), fname, lino, ino);
3283 goto do_junkit;
3284 }
3285 if (!inode_isadir(irec, ino_offset)) {
2bd0ea18
NS
3286 /*
3287 * check easy case first, regular inode, just bump
e55d768a 3288 * the link count
2bd0ea18
NS
3289 */
3290 add_inode_reached(irec, ino_offset);
2bd0ea18
NS
3291 } else {
3292 parent = get_inode_parent(irec, ino_offset);
3293
3294 /*
3295 * bump up the link counts in parent and child.
3296 * directory but if the link doesn't agree with
3297 * the .. in the child, blow out the entry
3298 */
3299 if (is_inode_reached(irec, ino_offset)) {
3300 junkit = 1;
507f4e33
NS
3301 do_warn(_("entry \"%s\" in directory inode %llu"
3302 " references already connected inode "
3303 "%llu,\n"),
2bd0ea18
NS
3304 fname, ino, lino);
3305 } else if (parent == ino) {
3306 add_inode_reached(irec, ino_offset);
3307 add_inode_ref(current_irec, current_ino_offset);
6fa00c33
BN
3308 } else if (parent == NULLFSINO) {
3309 /* ".." was missing, but this entry refers to it,
3310 so, set it as the parent and mark for rebuild */
3311 do_warn(_("entry \"%s\" in dir ino %llu doesn't have a"
3312 " .. entry, will set it in ino %llu.\n"),
3313 fname, ino, lino);
3314 set_inode_parent(irec, ino_offset, ino);
3315 add_inode_reached(irec, ino_offset);
3316 add_inode_ref(current_irec, current_ino_offset);
2bd0ea18
NS
3317 } else {
3318 junkit = 1;
507f4e33
NS
3319 do_warn(_("entry \"%s\" in directory inode %llu"
3320 " not consistent with .. value (%llu)"
3321 " in inode %llu,\n"),
2bd0ea18
NS
3322 fname, ino, parent, lino);
3323 }
3324 }
3325
3326 if (junkit) {
6c39a3cb
BN
3327do_junkit:
3328 if (lino == orphanage_ino)
3329 orphanage_ino = 0;
2bd0ea18
NS
3330 if (!no_modify) {
3331 tmp_elen = XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp, sfep);
3332 tmp_sfep = (xfs_dir2_sf_entry_t *)
3333 ((__psint_t) sfep + tmp_elen);
3334 tmp_len = max_size - ((__psint_t) tmp_sfep
3335 - (__psint_t) sfp);
3336 max_size -= tmp_elen;
3337 bytes_deleted += tmp_elen;
3338
3339 memmove(sfep, tmp_sfep, tmp_len);
3340
3341 INT_MOD(sfp->hdr.count, ARCH_CONVERT, -1);
3342 bzero((void *) ((__psint_t) sfep + tmp_len),
3343 tmp_elen);
3344
3345 /*
3346 * set the tmp value to the current
3347 * pointer so we'll process the entry
3348 * we just moved up
3349 */
3350 tmp_sfep = sfep;
3351
3352 /*
3353 * WARNING: drop the index i by one
3354 * so it matches the decremented count for
3355 * accurate comparisons in the loop test
3356 */
3357 i--;
3358
3359 *ino_dirty = 1;
3360
6c39a3cb
BN
3361 if (verbose)
3362 do_warn(_("junking entry\n"));
3363 else
3364 do_warn("\n");
2bd0ea18 3365 } else {
6c39a3cb 3366 do_warn(_("would junk entry\n"));
2bd0ea18
NS
3367 }
3368 } else if (lino > XFS_DIR2_MAX_SHORT_INUM)
3369 i8++;
3370
3371 /*
3372 * go onto next entry unless we've just junked an
3373 * entry in which the current entry pointer points
3374 * to an unprocessed entry. have to take into entries
3375 * with bad namelen into account in no modify mode since we
3376 * calculate size based on next_sfep.
3377 */
3378 ASSERT(no_modify || bad_sfnamelen == 0);
3379
3380 next_sfep = (tmp_sfep == NULL)
3381 ? (xfs_dir2_sf_entry_t *) ((__psint_t) sfep
3382 + ((!bad_sfnamelen)
3383 ? XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp, sfep)
3384 : XFS_DIR2_SF_ENTSIZE_BYNAME(sfp, namelen)))
3385 : tmp_sfep;
3386 }
3387
3388 if (sfp->hdr.i8count != i8) {
3389 if (no_modify) {
507f4e33 3390 do_warn(_("would fix i8count in inode %llu\n"), ino);
2bd0ea18
NS
3391 } else {
3392 if (i8 == 0) {
3393 tmp_sfep = next_sfep;
3394 process_sf_dir2_fixi8(sfp, &tmp_sfep);
3395 bytes_deleted +=
3396 (__psint_t)next_sfep -
3397 (__psint_t)tmp_sfep;
3398 next_sfep = tmp_sfep;
3399 } else
3400 sfp->hdr.i8count = i8;
3401 *ino_dirty = 1;
507f4e33 3402 do_warn(_("fixing i8count in inode %llu\n"), ino);
2bd0ea18
NS
3403 }
3404 }
3405
3406 /*
3407 * sync up sizes if required
3408 */
3409 if (*ino_dirty) {
3410 ASSERT(bytes_deleted > 0);
3411 ASSERT(!no_modify);
3412 libxfs_idata_realloc(ip, -bytes_deleted, XFS_DATA_FORK);
3413 ip->i_d.di_size -= bytes_deleted;
3414 }
3415
3416 if (ip->i_d.di_size != ip->i_df.if_bytes) {
3417 ASSERT(ip->i_df.if_bytes == (xfs_fsize_t)
3418 ((__psint_t) next_sfep - (__psint_t) sfp));
3419 ip->i_d.di_size = (xfs_fsize_t)
3420 ((__psint_t) next_sfep - (__psint_t) sfp);
507f4e33
NS
3421 do_warn(_("setting size to %lld bytes to reflect junked "
3422 "entries\n"),
2bd0ea18
NS
3423 ip->i_d.di_size);
3424 *ino_dirty = 1;
3425 }
3426}
3427
3428/*
2556c98b 3429 * processes all reachable inodes in directories
2bd0ea18 3430 */
2556c98b
BN
3431static void
3432process_dir_inode(
3433 xfs_mount_t *mp,
3434 xfs_ino_t ino,
3435 ino_tree_node_t *irec,
3436 int ino_offset)
2bd0ea18
NS
3437{
3438 xfs_bmap_free_t flist;
3439 xfs_fsblock_t first;
2bd0ea18
NS
3440 xfs_inode_t *ip;
3441 xfs_trans_t *tp;
3442 xfs_dahash_t hashval;
33165ec3 3443 dir_hash_tab_t *hashtab;
2556c98b 3444 int need_dot, committed;
2bd0ea18
NS
3445 int dirty, num_illegal, error, nres;
3446
3447 /*
2bd0ea18
NS
3448 * open up directory inode, check all entries,
3449 * then call prune_dir_entries to remove all
3450 * remaining illegal directory entries.
3451 */
3452
2556c98b 3453 ASSERT(!is_inode_refchecked(ino, irec, ino_offset));
2bd0ea18 3454
2556c98b
BN
3455 error = libxfs_iget(mp, NULL, ino, 0, &ip, 0);
3456 if (error) {
3457 if (!no_modify)
3458 do_error(_("couldn't map inode %llu, err = %d\n"),
3459 ino, error);
3460 else {
3461 do_warn(_("couldn't map inode %llu, err = %d\n"),
3462 ino, error);
2bd0ea18 3463 /*
2556c98b
BN
3464 * see below for what we're doing if this
3465 * is root. Why do we need to do this here?
3466 * to ensure that the root doesn't show up
3467 * as being disconnected in the no_modify case.
2bd0ea18 3468 */
2556c98b
BN
3469 if (mp->m_sb.sb_rootino == ino) {
3470 add_inode_reached(irec, 0);
3471 add_inode_ref(irec, 0);
3472 }
2bd0ea18
NS
3473 }
3474
2556c98b
BN
3475 add_inode_refchecked(ino, irec, 0);
3476 return;
3477 }
2bd0ea18 3478
2556c98b 3479 need_dot = dirty = num_illegal = 0;
64c54486 3480
2556c98b 3481 if (mp->m_sb.sb_rootino == ino) {
2bd0ea18 3482 /*
2556c98b
BN
3483 * mark root inode reached and bump up
3484 * link count for root inode to account
3485 * for '..' entry since the root inode is
3486 * never reached by a parent. we know
3487 * that root's '..' is always good --
3488 * guaranteed by phase 3 and/or below.
2bd0ea18 3489 */
2556c98b
BN
3490 add_inode_reached(irec, ino_offset);
3491 }
3492
3493 add_inode_refchecked(ino, irec, ino_offset);
3494
3495 hashtab = dir_hash_init(ip->i_d.di_size);
3496
3497 /*
3498 * look for bogus entries
3499 */
3500 switch (ip->i_d.di_format) {
2bd0ea18
NS
3501 case XFS_DINODE_FMT_EXTENTS:
3502 case XFS_DINODE_FMT_BTREE:
3503 /*
3504 * also check for missing '.' in longform dirs.
3505 * missing .. entries are added if required when
3506 * the directory is connected to lost+found. but
3507 * we need to create '.' entries here.
3508 */
3509 if (XFS_SB_VERSION_HASDIRV2(&mp->m_sb))
3510 longform_dir2_entry_check(mp, ino, ip,
3511 &num_illegal, &need_dot,
2556c98b 3512 irec, ino_offset,
33165ec3 3513 hashtab);
2bd0ea18
NS
3514 else
3515 longform_dir_entry_check(mp, ino, ip,
3516 &num_illegal, &need_dot,
2556c98b 3517 irec, ino_offset,
33165ec3 3518 hashtab);
2bd0ea18 3519 break;
2556c98b 3520
2bd0ea18
NS
3521 case XFS_DINODE_FMT_LOCAL:
3522 tp = libxfs_trans_alloc(mp, 0);
3523 /*
3524 * using the remove reservation is overkill
3525 * since at most we'll only need to log the
3526 * inode but it's easier than wedging a
3527 * new define in ourselves.
3528 */
3529 nres = no_modify ? 0 : XFS_REMOVE_SPACE_RES(mp);
3530 error = libxfs_trans_reserve(tp, nres,
3531 XFS_REMOVE_LOG_RES(mp), 0,
3532 XFS_TRANS_PERM_LOG_RES,
3533 XFS_REMOVE_LOG_COUNT);
3534 if (error)
3535 res_failed(error);
3536
3537 libxfs_trans_ijoin(tp, ip, 0);
3538 libxfs_trans_ihold(tp, ip);
3539
3540 if (XFS_SB_VERSION_HASDIRV2(&mp->m_sb))
3541 shortform_dir2_entry_check(mp, ino, ip, &dirty,
2556c98b 3542 irec, ino_offset,
33165ec3 3543 hashtab);
2bd0ea18
NS
3544 else
3545 shortform_dir_entry_check(mp, ino, ip, &dirty,
2556c98b 3546 irec, ino_offset,
33165ec3 3547 hashtab);
2bd0ea18 3548
27527004 3549 ASSERT(dirty == 0 || (dirty && !no_modify));
2bd0ea18
NS
3550 if (dirty) {
3551 libxfs_trans_log_inode(tp, ip,
3552 XFS_ILOG_CORE | XFS_ILOG_DDATA);
2556c98b
BN
3553 libxfs_trans_commit(tp,
3554 XFS_TRANS_RELEASE_LOG_RES |
3555 XFS_TRANS_SYNC, 0);
2bd0ea18 3556 } else {
2556c98b
BN
3557 libxfs_trans_cancel(tp,
3558 XFS_TRANS_RELEASE_LOG_RES);
2bd0ea18
NS
3559 }
3560 break;
2556c98b 3561
2bd0ea18
NS
3562 default:
3563 break;
2556c98b
BN
3564 }
3565 dir_hash_done(hashtab);
2bd0ea18 3566
2556c98b 3567 hashval = 0;
2bd0ea18 3568
2556c98b
BN
3569 /*
3570 * if we have to create a .. for /, do it now *before*
3571 * we delete the bogus entries, otherwise the directory
3572 * could transform into a shortform dir which would
3573 * probably cause the simulation to choke. Even
3574 * if the illegal entries get shifted around, it's ok
3575 * because the entries are structurally intact and in
3576 * in hash-value order so the simulation won't get confused
3577 * if it has to move them around.
3578 */
3579 if (!no_modify && need_root_dotdot && ino == mp->m_sb.sb_rootino) {
3580 ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_LOCAL);
2bd0ea18 3581
2556c98b 3582 do_warn(_("recreating root directory .. entry\n"));
2bd0ea18 3583
2556c98b
BN
3584 tp = libxfs_trans_alloc(mp, 0);
3585 ASSERT(tp != NULL);
2bd0ea18 3586
2556c98b
BN
3587 nres = XFS_MKDIR_SPACE_RES(mp, 2);
3588 error = libxfs_trans_reserve(tp, nres, XFS_MKDIR_LOG_RES(mp),
3589 0, XFS_TRANS_PERM_LOG_RES, XFS_MKDIR_LOG_COUNT);
3590 if (error)
3591 res_failed(error);
2bd0ea18 3592
2556c98b
BN
3593 libxfs_trans_ijoin(tp, ip, 0);
3594 libxfs_trans_ihold(tp, ip);
2bd0ea18 3595
2556c98b 3596 XFS_BMAP_INIT(&flist, &first);
2bd0ea18 3597
2556c98b
BN
3598 error = dir_createname(mp, tp, ip, "..", 2, ip->i_ino, &first,
3599 &flist, nres);
3600 if (error)
3601 do_error(_("can't make \"..\" entry in root inode "
3602 "%llu, createname error %d\n"), ino, error);
2bd0ea18 3603
2556c98b 3604 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
2bd0ea18 3605
2556c98b
BN
3606 error = libxfs_bmap_finish(&tp, &flist, first, &committed);
3607 ASSERT(error == 0);
3608 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES |
3609 XFS_TRANS_SYNC, 0);
2bd0ea18 3610
2556c98b
BN
3611 need_root_dotdot = 0;
3612 } else if (need_root_dotdot && ino == mp->m_sb.sb_rootino) {
3613 do_warn(_("would recreate root directory .. entry\n"));
3614 }
2bd0ea18 3615
2556c98b
BN
3616 /*
3617 * delete any illegal entries -- which should only exist
3618 * if the directory is a longform directory. bogus
3619 * shortform directory entries were deleted in phase 4.
3620 */
3621 if (!no_modify && num_illegal > 0) {
3622 ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_LOCAL);
3623 ASSERT(!XFS_SB_VERSION_HASDIRV2(&mp->m_sb));
3624
3625 while (num_illegal > 0 && ip->i_d.di_format !=
3626 XFS_DINODE_FMT_LOCAL) {
3627 prune_lf_dir_entry(mp, ino, ip, &hashval);
3628 num_illegal--;
2bd0ea18
NS
3629 }
3630
3631 /*
2556c98b
BN
3632 * handle case where we've deleted so many
3633 * entries that the directory has changed from
3634 * a longform to a shortform directory. have
3635 * to allocate a transaction since we're working
3636 * with the incore data fork.
3637 */
3638 if (num_illegal > 0) {
3639 ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_LOCAL);
3640 tp = libxfs_trans_alloc(mp, 0);
2bd0ea18 3641 /*
2556c98b
BN
3642 * using the remove reservation is overkill
3643 * since at most we'll only need to log the
3644 * inode but it's easier than wedging a
3645 * new define in ourselves. 10 block fs
3646 * space reservation is also overkill but
3647 * what the heck...
3648 */
3649 nres = XFS_REMOVE_SPACE_RES(mp);
3650 error = libxfs_trans_reserve(tp, nres,
3651 XFS_REMOVE_LOG_RES(mp), 0,
3652 XFS_TRANS_PERM_LOG_RES,
3653 XFS_REMOVE_LOG_COUNT);
3654 if (error)
3655 res_failed(error);
2bd0ea18 3656
2556c98b
BN
3657 libxfs_trans_ijoin(tp, ip, 0);
3658 libxfs_trans_ihold(tp, ip);
2bd0ea18 3659
2556c98b 3660 prune_sf_dir_entry(mp, ino, ip);
2bd0ea18 3661
2556c98b
BN
3662 libxfs_trans_log_inode(tp, ip,
3663 XFS_ILOG_CORE | XFS_ILOG_DDATA);
3664 ASSERT(error == 0);
3665 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES
3666 |XFS_TRANS_SYNC, 0);
2bd0ea18 3667 }
2556c98b 3668 }
2bd0ea18 3669
2556c98b
BN
3670 /*
3671 * if we need to create the '.' entry, do so only if
3672 * the directory is a longform dir. it it's been
3673 * turned into a shortform dir, then the inode is ok
3674 * since shortform dirs have no '.' entry and the inode
3675 * has already been committed by prune_lf_dir_entry().
3676 */
3677 if (need_dot) {
2bd0ea18 3678 /*
2556c98b
BN
3679 * bump up our link count but don't
3680 * bump up the inode link count. chances
3681 * are good that even though we lost '.'
3682 * the inode link counts reflect '.' so
3683 * leave the inode link count alone and if
3684 * it turns out to be wrong, we'll catch
3685 * that in phase 7.
2bd0ea18 3686 */
2556c98b
BN
3687 add_inode_ref(irec, ino_offset);
3688
3689 if (no_modify) {
3690 do_warn(_("would create missing \".\" entry in dir ino %llu\n"),
3691 ino);
3692 } else if (ip->i_d.di_format != XFS_DINODE_FMT_LOCAL) {
2bd0ea18 3693 /*
2556c98b 3694 * need to create . entry in longform dir.
2bd0ea18 3695 */
2556c98b
BN
3696 do_warn(_("creating missing \".\" entry in dir ino %llu\n"),
3697 ino);
2bd0ea18 3698
2556c98b
BN
3699 tp = libxfs_trans_alloc(mp, 0);
3700 ASSERT(tp != NULL);
2bd0ea18 3701
2556c98b
BN
3702 nres = XFS_MKDIR_SPACE_RES(mp, 1);
3703 error = libxfs_trans_reserve(tp, nres,
3704 XFS_MKDIR_LOG_RES(mp),
3705 0,
3706 XFS_TRANS_PERM_LOG_RES,
3707 XFS_MKDIR_LOG_COUNT);
2bd0ea18 3708
2556c98b
BN
3709 if (error)
3710 res_failed(error);
2bd0ea18 3711
2556c98b
BN
3712 libxfs_trans_ijoin(tp, ip, 0);
3713 libxfs_trans_ihold(tp, ip);
2bd0ea18 3714
2556c98b 3715 XFS_BMAP_INIT(&flist, &first);
2bd0ea18 3716
2556c98b
BN
3717 if ((error = dir_createname(mp, tp, ip, ".",
3718 1, ip->i_ino, &first, &flist,
3719 nres)))
3720 do_error(_("can't make \".\" entry in dir ino "
3721 "%llu, createname error %d\n"),
3722 ino, error);
2bd0ea18 3723
2556c98b 3724 libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
2bd0ea18 3725
2556c98b
BN
3726 error = libxfs_bmap_finish(&tp, &flist, first,
3727 &committed);
3728 ASSERT(error == 0);
3729 libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES
3730 |XFS_TRANS_SYNC, 0);
2bd0ea18 3731 }
2bd0ea18 3732 }
2556c98b
BN
3733
3734 libxfs_iput(ip, 0);
2bd0ea18
NS
3735}
3736
3737/*
3738 * mark realtime bitmap and summary inodes as reached.
3739 * quota inode will be marked here as well
3740 */
3741void
3742mark_standalone_inodes(xfs_mount_t *mp)
3743{
3744 ino_tree_node_t *irec;
3745 int offset;
3746
3747 irec = find_inode_rec(XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rbmino),
3748 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rbmino));
3749
3750 ASSERT(irec != NULL);
3751
3752 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rbmino) -
3753 irec->ino_startnum;
3754
3755 add_inode_reached(irec, offset);
3756
3757 irec = find_inode_rec(XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rsumino),
3758 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rsumino));
3759
dfc130f3 3760 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rsumino) -
2bd0ea18
NS
3761 irec->ino_startnum;
3762
3763 ASSERT(irec != NULL);
3764
3765 add_inode_reached(irec, offset);
3766
3767 if (fs_quotas) {
3768 if (mp->m_sb.sb_uquotino
3769 && mp->m_sb.sb_uquotino != NULLFSINO) {
3770 irec = find_inode_rec(XFS_INO_TO_AGNO(mp,
3771 mp->m_sb.sb_uquotino),
3772 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_uquotino));
3773 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_uquotino)
3774 - irec->ino_startnum;
3775 add_inode_reached(irec, offset);
3776 }
b36eef04
NS
3777 if (mp->m_sb.sb_gquotino
3778 && mp->m_sb.sb_gquotino != NULLFSINO) {
2bd0ea18 3779 irec = find_inode_rec(XFS_INO_TO_AGNO(mp,
b36eef04
NS
3780 mp->m_sb.sb_gquotino),
3781 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_gquotino));
3782 offset = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_gquotino)
2bd0ea18
NS
3783 - irec->ino_startnum;
3784 add_inode_reached(irec, offset);
3785 }
3786 }
3787}
3788
6c39a3cb
BN
3789static void
3790check_for_orphaned_inodes(
3791 xfs_mount_t *mp,
2556c98b 3792 xfs_agnumber_t agno,
6c39a3cb
BN
3793 ino_tree_node_t *irec)
3794{
3795 int i;
6c39a3cb
BN
3796 xfs_ino_t ino;
3797
3798 for (i = 0; i < XFS_INODES_PER_CHUNK; i++) {
3799 ASSERT(is_inode_confirmed(irec, i));
3800 if (is_inode_free(irec, i))
3801 continue;
3802
2556c98b
BN
3803 if (is_inode_reached(irec, i))
3804 continue;
3805
3806 ASSERT(inode_isadir(irec, i) ||
3807 num_inode_references(irec, i) == 0);
3808
3809 ino = XFS_AGINO_TO_INO(mp, agno, i + irec->ino_startnum);
3810 if (inode_isadir(irec, i))
3811 do_warn(_("disconnected dir inode %llu, "), ino);
3812 else
3813 do_warn(_("disconnected inode %llu, "), ino);
3814 if (!no_modify) {
3815 if (!orphanage_ino)
3816 orphanage_ino = mk_orphanage(mp);
3817 do_warn(_("moving to %s\n"), ORPHANAGE);
3818 mv_orphanage(mp, ino, inode_isadir(irec, i));
3819 } else {
3820 do_warn(_("would move to %s\n"), ORPHANAGE);
6c39a3cb 3821 }
2556c98b
BN
3822 /*
3823 * for read-only case, even though the inode isn't
3824 * really reachable, set the flag (and bump our link
3825 * count) anyway to fool phase 7
3826 */
3827 add_inode_reached(irec, i);
6c39a3cb
BN
3828 }
3829}
3830
a1d54891 3831static void
2556c98b
BN
3832traverse_function(
3833 work_queue_t *wq,
3834 xfs_agnumber_t agno,
3835 void *arg)
a1d54891 3836{
2556c98b
BN
3837 ino_tree_node_t *irec;
3838 int i;
3839 prefetch_args_t *pf_args = arg;
3840
3841 wait_for_inode_prefetch(pf_args);
a1d54891
MV
3842
3843 if (verbose)
3844 do_log(_(" - agno = %d\n"), agno);
3845
2556c98b
BN
3846 for (irec = findfirst_inode_rec(agno); irec; irec = next_ino_rec(irec)) {
3847 if (irec->ino_isa_dir == 0)
3848 continue;
a1d54891 3849
2556c98b
BN
3850 if (pf_args)
3851 sem_post(&pf_args->ra_count);
a1d54891 3852
2556c98b
BN
3853 for (i = 0; i < XFS_INODES_PER_CHUNK; i++) {
3854 if (inode_isadir(irec, i))
3855 process_dir_inode(wq->mp,
3856 XFS_AGINO_TO_INO(wq->mp, agno,
3857 irec->ino_startnum + i), irec, i);
a1d54891 3858 }
a1d54891 3859 }
2556c98b 3860 cleanup_inode_prefetch(pf_args);
a1d54891
MV
3861}
3862
3863static void
2556c98b
BN
3864traverse_ags(
3865 xfs_mount_t *mp)
a1d54891
MV
3866{
3867 int i;
69ec88b5 3868 work_queue_t queue;
2556c98b
BN
3869 prefetch_args_t *pf_args[2];
3870
69ec88b5
BN
3871 /*
3872 * we always do prefetch for phase 6 as it will fill in the gaps
3873 * not read during phase 3 prefetch.
3874 */
3875 queue.mp = mp;
3876 pf_args[0] = start_inode_prefetch(0, 1, NULL);
3877 for (i = 0; i < glob_agcount; i++) {
3878 pf_args[(~i) & 1] = start_inode_prefetch(i + 1, 1,
3879 pf_args[i & 1]);
3880 traverse_function(&queue, i, pf_args[i & 1]);
a1d54891
MV
3881 }
3882}
3883
2bd0ea18
NS
3884void
3885phase6(xfs_mount_t *mp)
3886{
2bd0ea18 3887 ino_tree_node_t *irec;
2bd0ea18 3888 int i;
2bd0ea18 3889
9f064b7e
NS
3890 bzero(&zerocr, sizeof(struct cred));
3891 bzero(&zerofsx, sizeof(struct fsxattr));
6c39a3cb 3892 orphanage_ino = 0;
2bd0ea18 3893
507f4e33 3894 do_log(_("Phase 6 - check inode connectivity...\n"));
2bd0ea18
NS
3895
3896 if (!no_modify)
3897 teardown_bmap_finish(mp);
3898 else
3899 teardown_bmap(mp);
3900
3901 incore_ext_teardown(mp);
3902
0f012a4c 3903 add_ino_ex_data(mp);
2bd0ea18
NS
3904
3905 /*
3906 * verify existence of root directory - if we have to
3907 * make one, it's ok for the incore data structs not to
3908 * know about it since everything about it (and the other
3909 * inodes in its chunk if a new chunk was created) are ok
3910 */
3911 if (need_root_inode) {
3912 if (!no_modify) {
507f4e33 3913 do_warn(_("reinitializing root directory\n"));
2bd0ea18
NS
3914 mk_root_dir(mp);
3915 need_root_inode = 0;
3916 need_root_dotdot = 0;
3917 } else {
507f4e33 3918 do_warn(_("would reinitialize root directory\n"));
2bd0ea18
NS
3919 }
3920 }
3921
3922 if (need_rbmino) {
3923 if (!no_modify) {
507f4e33 3924 do_warn(_("reinitializing realtime bitmap inode\n"));
2bd0ea18
NS
3925 mk_rbmino(mp);
3926 need_rbmino = 0;
3927 } else {
507f4e33 3928 do_warn(_("would reinitialize realtime bitmap inode\n"));
2bd0ea18
NS
3929 }
3930 }
3931
3932 if (need_rsumino) {
3933 if (!no_modify) {
507f4e33 3934 do_warn(_("reinitializing realtime summary inode\n"));
2bd0ea18
NS
3935 mk_rsumino(mp);
3936 need_rsumino = 0;
3937 } else {
507f4e33 3938 do_warn(_("would reinitialize realtime summary inode\n"));
2bd0ea18
NS
3939 }
3940 }
3941
3942 if (!no_modify) {
3943 do_log(
507f4e33 3944_(" - resetting contents of realtime bitmap and summary inodes\n"));
2bd0ea18
NS
3945 if (fill_rbmino(mp)) {
3946 do_warn(
507f4e33 3947 _("Warning: realtime bitmap may be inconsistent\n"));
2bd0ea18
NS
3948 }
3949
3950 if (fill_rsumino(mp)) {
3951 do_warn(
507f4e33 3952 _("Warning: realtime bitmap may be inconsistent\n"));
2bd0ea18
NS
3953 }
3954 }
3955
2bd0ea18
NS
3956 mark_standalone_inodes(mp);
3957
69ec88b5 3958 do_log(_(" - traversing filesystem ...\n"));
2bd0ea18
NS
3959
3960 irec = find_inode_rec(XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino),
3961 XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino));
3962
3963 /*
3964 * we always have a root inode, even if it's free...
3965 * if the root is free, forget it, lost+found is already gone
3966 */
3967 if (is_inode_free(irec, 0) || !inode_isadir(irec, 0)) {
3968 need_root_inode = 1;
3969 }
3970
3971 /*
2556c98b 3972 * then process all inodes by walking incore inode tree
2bd0ea18 3973 */
2556c98b 3974 traverse_ags(mp);
2bd0ea18 3975
69ec88b5
BN
3976 do_log(_(" - traversal finished ...\n"));
3977 do_log(_(" - moving disconnected inodes to %s ...\n"),
6c39a3cb 3978 ORPHANAGE);
2bd0ea18
NS
3979
3980 /*
3981 * move all disconnected inodes to the orphanage
3982 */
3983 for (i = 0; i < glob_agcount; i++) {
3984 irec = findfirst_inode_rec(i);
2bd0ea18 3985 while (irec != NULL) {
2556c98b 3986 check_for_orphaned_inodes(mp, i, irec);
2bd0ea18
NS
3987 irec = next_ino_rec(irec);
3988 }
3989 }
3990}