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