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