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