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