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