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