]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - repair/dinode.c
Update copyright dates
[thirdparty/xfsprogs-dev.git] / repair / dinode.c
1 /*
2 * Copyright (c) 2000-2001 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 "protos.h"
39 #include "err_protos.h"
40 #include "dir.h"
41 #include "dir2.h"
42 #include "dinode.h"
43 #include "scan.h"
44 #include "versions.h"
45 #include "attr_repair.h"
46 #include "bmap.h"
47
48 /*
49 * inode clearing routines
50 */
51
52 /*
53 * return the offset into the inode where the attribute fork starts
54 */
55 /* ARGSUSED */
56 int
57 calc_attr_offset(xfs_mount_t *mp, xfs_dinode_t *dino)
58 {
59 xfs_dinode_core_t *dinoc = &dino->di_core;
60 int offset = ((__psint_t) &dino->di_u)
61 - (__psint_t)dino;
62
63 /*
64 * don't worry about alignment when calculating offset
65 * because the data fork is already 8-byte aligned
66 */
67 switch (dinoc->di_format) {
68 case XFS_DINODE_FMT_DEV:
69 offset += sizeof(dev_t);
70 break;
71 case XFS_DINODE_FMT_LOCAL:
72 offset += INT_GET(dinoc->di_size, ARCH_CONVERT);
73 break;
74 case XFS_DINODE_FMT_UUID:
75 offset += sizeof(uuid_t);
76 break;
77 case XFS_DINODE_FMT_EXTENTS:
78 offset += INT_GET(dinoc->di_nextents, ARCH_CONVERT) * sizeof(xfs_bmbt_rec_32_t);
79 break;
80 case XFS_DINODE_FMT_BTREE:
81 offset += INT_GET(dino->di_u.di_bmbt.bb_numrecs, ARCH_CONVERT) * sizeof(xfs_bmbt_rec_32_t);
82 break;
83 default:
84 do_error("Unknown inode format.\n");
85 abort();
86 break;
87 }
88
89 return(offset);
90 }
91
92 /* ARGSUSED */
93 int
94 clear_dinode_attr(xfs_mount_t *mp, xfs_dinode_t *dino, xfs_ino_t ino_num)
95 {
96 xfs_dinode_core_t *dinoc = &dino->di_core;
97
98 ASSERT(dinoc->di_forkoff != 0);
99
100 if (!no_modify)
101 fprintf(stderr, "clearing inode %llu attributes \n",
102 (unsigned long long)ino_num);
103 else
104 fprintf(stderr, "would have cleared inode %llu attributes\n",
105 (unsigned long long)ino_num);
106
107 if (INT_GET(dinoc->di_anextents, ARCH_CONVERT) != 0) {
108 if (no_modify)
109 return(1);
110 INT_ZERO(dinoc->di_anextents, ARCH_CONVERT);
111 }
112
113 if (dinoc->di_aformat != XFS_DINODE_FMT_EXTENTS) {
114 if (no_modify)
115 return(1);
116 dinoc->di_aformat = XFS_DINODE_FMT_EXTENTS;
117 }
118
119 /* get rid of the fork by clearing forkoff */
120
121 /* Originally, when the attr repair code was added, the fork was cleared
122 * by turning it into shortform status. This meant clearing the
123 * hdr.totsize/count fields and also changing aformat to LOCAL
124 * (vs EXTENTS). Over various fixes, the aformat and forkoff have
125 * been updated to not show an attribute fork at all, however.
126 * It could be possible that resetting totsize/count are not needed,
127 * but just to be safe, leave it in for now.
128 */
129
130 if (!no_modify) {
131 xfs_attr_shortform_t *asf = (xfs_attr_shortform_t *)
132 XFS_DFORK_APTR_ARCH(dino, ARCH_CONVERT);
133 INT_SET(asf->hdr.totsize, ARCH_CONVERT,
134 sizeof(xfs_attr_sf_hdr_t));
135 INT_SET(asf->hdr.count, ARCH_CONVERT, 0);
136 dinoc->di_forkoff = 0; /* got to do this after asf is set */
137 }
138
139 /*
140 * always returns 1 since the fork gets zapped
141 */
142 return(1);
143 }
144
145 /* ARGSUSED */
146 int
147 clear_dinode_core(xfs_dinode_core_t *dinoc, xfs_ino_t ino_num)
148 {
149 int dirty = 0;
150
151 if (INT_GET(dinoc->di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC) {
152 dirty = 1;
153
154 if (no_modify)
155 return(1);
156
157 INT_SET(dinoc->di_magic, ARCH_CONVERT, XFS_DINODE_MAGIC);
158 }
159
160 if (!XFS_DINODE_GOOD_VERSION(dinoc->di_version) ||
161 (!fs_inode_nlink && dinoc->di_version > XFS_DINODE_VERSION_1)) {
162 dirty = 1;
163
164 if (no_modify)
165 return(1);
166
167 dinoc->di_version = (fs_inode_nlink) ? XFS_DINODE_VERSION_2
168 : XFS_DINODE_VERSION_1;
169 }
170
171 if (INT_GET(dinoc->di_mode, ARCH_CONVERT) != 0) {
172 dirty = 1;
173
174 if (no_modify)
175 return(1);
176
177 INT_ZERO(dinoc->di_mode, ARCH_CONVERT);
178 }
179
180 if (INT_GET(dinoc->di_flags, ARCH_CONVERT) != 0) {
181 dirty = 1;
182
183 if (no_modify)
184 return(1);
185
186 INT_ZERO(dinoc->di_flags, ARCH_CONVERT);
187 }
188
189 if (INT_GET(dinoc->di_dmevmask, ARCH_CONVERT) != 0) {
190 dirty = 1;
191
192 if (no_modify)
193 return(1);
194
195 INT_ZERO(dinoc->di_dmevmask, ARCH_CONVERT);
196 }
197
198 if (dinoc->di_forkoff != 0) {
199 dirty = 1;
200
201 if (no_modify)
202 return(1);
203
204 dinoc->di_forkoff = 0;
205 }
206
207 if (dinoc->di_format != XFS_DINODE_FMT_EXTENTS) {
208 dirty = 1;
209
210 if (no_modify)
211 return(1);
212
213 dinoc->di_format = XFS_DINODE_FMT_EXTENTS;
214 }
215
216 if (dinoc->di_aformat != XFS_DINODE_FMT_EXTENTS) {
217 dirty = 1;
218
219 if (no_modify)
220 return(1);
221
222 dinoc->di_aformat = XFS_DINODE_FMT_EXTENTS;
223 }
224
225 if (INT_GET(dinoc->di_size, ARCH_CONVERT) != 0) {
226 dirty = 1;
227
228 if (no_modify)
229 return(1);
230
231 INT_ZERO(dinoc->di_size, ARCH_CONVERT);
232 }
233
234 if (INT_GET(dinoc->di_nblocks, ARCH_CONVERT) != 0) {
235 dirty = 1;
236
237 if (no_modify)
238 return(1);
239
240 INT_ZERO(dinoc->di_nblocks, ARCH_CONVERT);
241 }
242
243 if (INT_GET(dinoc->di_onlink, ARCH_CONVERT) != 0) {
244 dirty = 1;
245
246 if (no_modify)
247 return(1);
248
249 INT_ZERO(dinoc->di_onlink, ARCH_CONVERT);
250 }
251
252 if (INT_GET(dinoc->di_nextents, ARCH_CONVERT) != 0) {
253 dirty = 1;
254
255 if (no_modify)
256 return(1);
257
258 INT_ZERO(dinoc->di_nextents, ARCH_CONVERT);
259 }
260
261 if (INT_GET(dinoc->di_anextents, ARCH_CONVERT) != 0) {
262 dirty = 1;
263
264 if (no_modify)
265 return(1);
266
267 INT_ZERO(dinoc->di_anextents, ARCH_CONVERT);
268 }
269
270 if (dinoc->di_version > XFS_DINODE_VERSION_1 &&
271 INT_GET(dinoc->di_nlink, ARCH_CONVERT) != 0) {
272 dirty = 1;
273
274 if (no_modify)
275 return(1);
276
277 INT_ZERO(dinoc->di_nlink, ARCH_CONVERT);
278 }
279
280 return(dirty);
281 }
282
283 /* ARGSUSED */
284 int
285 clear_dinode_unlinked(xfs_mount_t *mp, xfs_dinode_t *dino)
286 {
287
288 if (dino->di_next_unlinked != NULLAGINO) {
289 if (!no_modify)
290 dino->di_next_unlinked = NULLAGINO;
291 return(1);
292 }
293
294 return(0);
295 }
296
297 /*
298 * this clears the unlinked list too so it should not be called
299 * until after the agi unlinked lists are walked in phase 3.
300 * returns > zero if the inode has been altered while being cleared
301 */
302 int
303 clear_dinode(xfs_mount_t *mp, xfs_dinode_t *dino, xfs_ino_t ino_num)
304 {
305 int dirty;
306
307 dirty = clear_dinode_core(&dino->di_core, ino_num);
308 dirty += clear_dinode_unlinked(mp, dino);
309
310 /* and clear the forks */
311
312 if (dirty && !no_modify)
313 bzero(&dino->di_u, XFS_LITINO(mp));
314
315 return(dirty);
316 }
317
318
319 /*
320 * misc. inode-related utility routines
321 */
322
323 /*
324 * returns 0 if inode number is valid, 1 if bogus
325 */
326 int
327 verify_inum(xfs_mount_t *mp,
328 xfs_ino_t ino)
329 {
330 xfs_agnumber_t agno;
331 xfs_agino_t agino;
332 xfs_agblock_t agbno;
333 xfs_sb_t *sbp = &mp->m_sb;;
334
335 /* range check ag #, ag block. range-checking offset is pointless */
336
337 agno = XFS_INO_TO_AGNO(mp, ino);
338 agino = XFS_INO_TO_AGINO(mp, ino);
339 agbno = XFS_AGINO_TO_AGBNO(mp, agino);
340
341 if (ino == 0 || ino == NULLFSINO)
342 return(1);
343
344 if (ino != XFS_AGINO_TO_INO(mp, agno, agino))
345 return(1);
346
347 if (agno >= sbp->sb_agcount ||
348 (agno < sbp->sb_agcount && agbno >= sbp->sb_agblocks) ||
349 (agno == sbp->sb_agcount && agbno >= sbp->sb_dblocks -
350 (sbp->sb_agcount-1) * sbp->sb_agblocks) ||
351 (agbno == 0))
352 return(1);
353
354 return(0);
355 }
356
357 /*
358 * have a separate routine to ensure that we don't accidentally
359 * lose illegally set bits in the agino by turning it into an FSINO
360 * to feed to the above routine
361 */
362 int
363 verify_aginum(xfs_mount_t *mp,
364 xfs_agnumber_t agno,
365 xfs_agino_t agino)
366 {
367 xfs_agblock_t agbno;
368 xfs_sb_t *sbp = &mp->m_sb;;
369
370 /* range check ag #, ag block. range-checking offset is pointless */
371
372 if (agino == 0 || agino == NULLAGINO)
373 return(1);
374
375 /*
376 * agino's can't be too close to NULLAGINO because the min blocksize
377 * is 9 bits and at most 1 bit of that gets used for the inode offset
378 * so if the agino gets shifted by the # of offset bits and compared
379 * to the legal agbno values, a bogus agino will be too large. there
380 * will be extra bits set at the top that shouldn't be set.
381 */
382 agbno = XFS_AGINO_TO_AGBNO(mp, agino);
383
384 if (agno >= sbp->sb_agcount ||
385 (agno < sbp->sb_agcount && agbno >= sbp->sb_agblocks) ||
386 (agno == sbp->sb_agcount && agbno >= sbp->sb_dblocks -
387 (sbp->sb_agcount-1) * sbp->sb_agblocks) ||
388 (agbno == 0))
389 return(1);
390
391 return(0);
392 }
393
394 /*
395 * return 1 if block number is good, 0 if out of range
396 */
397 int
398 verify_dfsbno(xfs_mount_t *mp,
399 xfs_dfsbno_t fsbno)
400 {
401 xfs_agnumber_t agno;
402 xfs_agblock_t agbno;
403 xfs_sb_t *sbp = &mp->m_sb;;
404
405 /* range check ag #, ag block. range-checking offset is pointless */
406
407 agno = XFS_FSB_TO_AGNO(mp, fsbno);
408 agbno = XFS_FSB_TO_AGBNO(mp, fsbno);
409
410 if (agno >= sbp->sb_agcount ||
411 (agno < sbp->sb_agcount && agbno >= sbp->sb_agblocks) ||
412 (agno == sbp->sb_agcount && agbno >= sbp->sb_dblocks -
413 (sbp->sb_agcount-1) * sbp->sb_agblocks))
414 return(0);
415
416 return(1);
417 }
418
419 int
420 verify_agbno(xfs_mount_t *mp,
421 xfs_agnumber_t agno,
422 xfs_agblock_t agbno)
423 {
424 xfs_sb_t *sbp = &mp->m_sb;;
425
426 /* range check ag #, ag block. range-checking offset is pointless */
427
428 if (agno >= sbp->sb_agcount ||
429 (agno < sbp->sb_agcount && agbno >= sbp->sb_agblocks) ||
430 (agno == sbp->sb_agcount && agbno >= sbp->sb_dblocks -
431 (sbp->sb_agcount-1) * sbp->sb_agblocks))
432 return(0);
433
434 return(1);
435 }
436
437 void
438 convert_extent(
439 xfs_bmbt_rec_32_t *rp,
440 xfs_dfiloff_t *op, /* starting offset (blockno in file) */
441 xfs_dfsbno_t *sp, /* starting block (fs blockno) */
442 xfs_dfilblks_t *cp, /* blockcount */
443 int *fp) /* extent flag */
444 {
445 xfs_bmbt_irec_t irec, *s = &irec;
446 xfs_bmbt_rec_t rpcopy, *p = &rpcopy;
447
448 memcpy(&rpcopy, rp, sizeof(rpcopy));
449 /* Just use the extent parsing routine from the kernel */
450 libxfs_bmbt_get_all(p, s);
451
452 if (fs_has_extflgbit) {
453 if (s->br_state == XFS_EXT_UNWRITTEN) {
454 *fp = 1;
455 } else {
456 *fp = 0;
457 }
458 } else {
459 *fp = 0;
460 }
461 *op = s->br_startoff;
462 *sp = s->br_startblock;
463 *cp = s->br_blockcount;
464 }
465
466 /*
467 * return address of block fblock if it's within the range described
468 * by the extent list. Otherwise, returns a null address.
469 */
470 /* ARGSUSED */
471 xfs_dfsbno_t
472 get_bmbt_reclist(
473 xfs_mount_t *mp,
474 xfs_bmbt_rec_32_t *rp,
475 int numrecs,
476 xfs_dfiloff_t fblock)
477 {
478 int i;
479 xfs_dfilblks_t cnt;
480 xfs_dfiloff_t off_bno;
481 xfs_dfsbno_t start;
482 int flag;
483
484 for (i = 0; i < numrecs; i++, rp++) {
485 convert_extent(rp, &off_bno, &start, &cnt, &flag);
486 if (off_bno >= fblock && off_bno + cnt < fblock)
487 return(start + fblock - off_bno);
488 }
489
490 return(NULLDFSBNO);
491 }
492
493 /*
494 * return 1 if inode should be cleared, 0 otherwise
495 * if check_dups should be set to 1, that implies that
496 * the primary purpose of this call is to see if the
497 * file overlaps with any duplicate extents (in the
498 * duplicate extent list).
499 */
500 /* ARGSUSED */
501 int
502 process_bmbt_reclist_int(
503 xfs_mount_t *mp,
504 xfs_bmbt_rec_32_t *rp,
505 int numrecs,
506 int type,
507 xfs_ino_t ino,
508 xfs_drfsbno_t *tot,
509 blkmap_t **blkmapp,
510 xfs_dfiloff_t *first_key,
511 xfs_dfiloff_t *last_key,
512 int check_dups,
513 int whichfork)
514 {
515 xfs_dfsbno_t b;
516 xfs_drtbno_t ext;
517 xfs_dfilblks_t c; /* count */
518 xfs_dfilblks_t cp = 0; /* prev count */
519 xfs_dfsbno_t s; /* start */
520 xfs_dfsbno_t sp = 0; /* prev start */
521 xfs_dfiloff_t o = 0; /* offset */
522 xfs_dfiloff_t op = 0; /* prev offset */
523 char *ftype;
524 char *forkname;
525 int i;
526 int state;
527 int flag; /* extent flag */
528
529 if (whichfork == XFS_DATA_FORK)
530 forkname = "data";
531 else
532 forkname = "attr";
533
534 if (type == XR_INO_RTDATA)
535 ftype = "real-time";
536 else
537 ftype = "regular";
538
539 for (i = 0; i < numrecs; i++, rp++) {
540 convert_extent(rp, &o, &s, &c, &flag);
541 if (i == 0)
542 *last_key = *first_key = o;
543 else
544 *last_key = o;
545 if (i > 0 && op + cp > o) {
546 do_warn(
547 "bmap rec out of order, inode %llu entry %d [o s c] [%llu %llu %llu], %d [%llu %llu %llu]\n",
548 ino, i, o, s, c, i-1, op, sp, cp);
549 return(1);
550 }
551 op = o;
552 cp = c;
553 sp = s;
554
555 /*
556 * check numeric validity of the extent
557 */
558 if (c == 0) {
559 do_warn(
560 "zero length extent (off = %llu, fsbno = %llu) in ino %llu\n",
561 o, s, ino);
562 return(1);
563 }
564 if (type == XR_INO_RTDATA) {
565 if (s >= mp->m_sb.sb_rblocks) {
566 do_warn(
567 "inode %llu - bad rt extent starting block number %llu, offset %llu\n",
568 ino, s, o);
569 return(1);
570 }
571 if (s + c - 1 >= mp->m_sb.sb_rblocks) {
572 do_warn(
573 "inode %llu - bad rt extent last block number %llu, offset %llu\n",
574 ino, s + c - 1, o);
575 return(1);
576 }
577 if (s + c - 1 < s) {
578 do_warn(
579 "inode %llu - bad rt extent overflows - start %llu, end %llu, offset %llu\n",
580 ino, s, s + c - 1, o);
581 return(1);
582 }
583 } else {
584 if (!verify_dfsbno(mp, s)) {
585 do_warn(
586 "inode %llu - bad extent starting block number %llu, offset %llu\n",
587 ino, s, o);
588 return(1);
589 }
590 if (!verify_dfsbno(mp, s + c - 1)) {
591 do_warn(
592 "inode %llu - bad extent last block number %llu, offset %llu\n",
593 ino, s + c - 1, o);
594 return(1);
595 }
596 if (s + c - 1 < s) {
597 do_warn(
598 "inode %llu - bad extent overflows - start %llu, end %llu, offset %llu\n",
599 ino, s, s + c - 1, o);
600 return(1);
601 }
602 if (o >= fs_max_file_offset) {
603 do_warn(
604 "inode %llu - extent offset too large - start %llu, count %llu, offset %llu\n",
605 ino, s, c, o);
606 return(1);
607 }
608 }
609
610 /*
611 * realtime file data fork
612 */
613 if (type == XR_INO_RTDATA && whichfork == XFS_DATA_FORK) {
614 /*
615 * XXX - verify that the blocks listed in the record
616 * are multiples of an extent
617 */
618 if (XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb) == 0
619 && (s % mp->m_sb.sb_rextsize != 0 ||
620 c % mp->m_sb.sb_rextsize != 0)) {
621 do_warn(
622 "malformed rt inode extent [%llu %llu] (fs rtext size = %u)\n",
623 s, c, mp->m_sb.sb_rextsize);
624 return(1);
625 }
626
627 /*
628 * XXX - set the appropriate number of extents
629 */
630 for (b = s; b < s + c; b += mp->m_sb.sb_rextsize) {
631 ext = (xfs_drtbno_t) b / mp->m_sb.sb_rextsize;
632
633 if (check_dups == 1) {
634 if (search_rt_dup_extent(mp, ext)) {
635 do_warn(
636 "data fork in rt ino %llu claims dup rt extent, off - %llu, start - %llu, count %llu\n",
637 ino, o, s, c);
638 return(1);
639 }
640 continue;
641 }
642
643 state = get_rtbno_state(mp, ext);
644
645 switch (state) {
646 case XR_E_FREE:
647 /* XXX - turn this back on after we
648 run process_rtbitmap() in phase2
649 do_warn(
650 "%s fork in rt ino %llu claims free rt block %llu\n",
651 forkname, ino, ext);
652 */
653 /* fall through ... */
654 case XR_E_UNKNOWN:
655 set_rtbno_state(mp, ext, XR_E_INUSE);
656 break;
657 case XR_E_BAD_STATE:
658 do_error(
659 "bad state in rt block map %llu\n", ext);
660 abort();
661 break;
662 case XR_E_FS_MAP:
663 case XR_E_INO:
664 case XR_E_INUSE_FS:
665 do_error(
666 "%s fork in rt inode %llu found metadata block %llu in %s bmap\n",
667 forkname, ino, ext, ftype);
668 case XR_E_INUSE:
669 case XR_E_MULT:
670 set_rtbno_state(mp, ext, XR_E_MULT);
671 do_warn(
672 "%s fork in rt inode %llu claims used rt block %llu\n",
673 forkname, ino, ext);
674 return(1);
675 case XR_E_FREE1:
676 default:
677 do_error(
678 "illegal state %d in %s block map %llu\n",
679 state, ftype, b);
680 }
681 }
682
683 /*
684 * bump up the block counter
685 */
686 *tot += c;
687
688 /*
689 * skip rest of loop processing since that's
690 * all for regular file forks and attr forks
691 */
692 continue;
693 }
694
695
696 /*
697 * regular file data fork or attribute fork
698 */
699 if (blkmapp && *blkmapp)
700 blkmap_set_ext(blkmapp, o, s, c);
701 for (b = s; b < s + c; b++) {
702 if (check_dups == 1) {
703 /*
704 * if we're just checking the bmap for dups,
705 * return if we find one, otherwise, continue
706 * checking each entry without setting the
707 * block bitmap
708 */
709 if (search_dup_extent(mp,
710 XFS_FSB_TO_AGNO(mp, b),
711 XFS_FSB_TO_AGBNO(mp, b))) {
712 do_warn(
713 "%s fork in ino %llu claims dup extent, off - %llu, start - %llu, cnt %llu\n",
714 forkname, ino, o, s, c);
715 return(1);
716 }
717 continue;
718 }
719
720 /* FIX FOR BUG 653709 -- EKN
721 * realtime attribute fork, should be valid block number
722 * in regular data space, not realtime partion.
723 */
724 if (type == XR_INO_RTDATA && whichfork == XFS_ATTR_FORK) {
725 if (mp->m_sb.sb_agcount < XFS_FSB_TO_AGNO(mp, b))
726 return(1);
727 }
728
729 state = get_fsbno_state(mp, b);
730 switch (state) {
731 case XR_E_FREE:
732 case XR_E_FREE1:
733 do_warn(
734 "%s fork in ino %llu claims free block %llu\n",
735 forkname, ino, (__uint64_t) b);
736 /* fall through ... */
737 case XR_E_UNKNOWN:
738 set_fsbno_state(mp, b, XR_E_INUSE);
739 break;
740 case XR_E_BAD_STATE:
741 do_error("bad state in block map %llu\n", b);
742 abort();
743 break;
744 case XR_E_FS_MAP:
745 case XR_E_INO:
746 case XR_E_INUSE_FS:
747 do_warn(
748 "%s fork in inode %llu claims metadata block %llu\n",
749 forkname, ino, (__uint64_t) b);
750 return(1);
751 case XR_E_INUSE:
752 case XR_E_MULT:
753 set_fsbno_state(mp, b, XR_E_MULT);
754 do_warn(
755 "%s fork in %s inode %llu claims used block %llu\n",
756 forkname, ftype, ino, (__uint64_t) b);
757 return(1);
758 default:
759 do_error("illegal state %d in block map %llu\n",
760 state, b);
761 abort();
762 }
763 }
764 *tot += c;
765 }
766
767 return(0);
768 }
769
770 /*
771 * return 1 if inode should be cleared, 0 otherwise, sets block bitmap
772 * as a side-effect
773 */
774 int
775 process_bmbt_reclist(
776 xfs_mount_t *mp,
777 xfs_bmbt_rec_32_t *rp,
778 int numrecs,
779 int type,
780 xfs_ino_t ino,
781 xfs_drfsbno_t *tot,
782 blkmap_t **blkmapp,
783 xfs_dfiloff_t *first_key,
784 xfs_dfiloff_t *last_key,
785 int whichfork)
786 {
787 return(process_bmbt_reclist_int(mp, rp, numrecs, type, ino, tot,
788 blkmapp, first_key, last_key, 0,
789 whichfork));
790 }
791
792 /*
793 * return 1 if inode should be cleared, 0 otherwise, does not set
794 * block bitmap
795 */
796 int
797 scan_bmbt_reclist(
798 xfs_mount_t *mp,
799 xfs_bmbt_rec_32_t *rp,
800 int numrecs,
801 int type,
802 xfs_ino_t ino,
803 xfs_drfsbno_t *tot,
804 int whichfork)
805 {
806 xfs_dfiloff_t first_key = 0;
807 xfs_dfiloff_t last_key = 0;
808
809 return(process_bmbt_reclist_int(mp, rp, numrecs, type, ino, tot,
810 NULL, &first_key, &last_key, 1,
811 whichfork));
812 }
813
814 /*
815 * these two are meant for routines that read and work with inodes
816 * one at a time where the inodes may be in any order (like walking
817 * the unlinked lists to look for inodes). the caller is responsible
818 * for writing/releasing the buffer.
819 */
820 xfs_buf_t *
821 get_agino_buf(xfs_mount_t *mp,
822 xfs_agnumber_t agno,
823 xfs_agino_t agino,
824 xfs_dinode_t **dipp)
825 {
826 ino_tree_node_t *irec;
827 xfs_buf_t *bp;
828 int size;
829
830 if ((irec = find_inode_rec(agno, agino)) == NULL)
831 return(NULL);
832
833 size = XFS_FSB_TO_BB(mp, MAX(1, XFS_INODES_PER_CHUNK/inodes_per_block));
834 bp = libxfs_readbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, agno,
835 XFS_AGINO_TO_AGBNO(mp, irec->ino_startnum)), size, 0);
836 if (!bp) {
837 do_warn("cannot read inode (%u/%u), disk block %lld\n",
838 agno, irec->ino_startnum,
839 XFS_AGB_TO_DADDR(mp, agno,
840 XFS_AGINO_TO_AGBNO(mp, irec->ino_startnum)));
841 return(NULL);
842 }
843
844 *dipp = XFS_MAKE_IPTR(mp, bp, agino -
845 XFS_OFFBNO_TO_AGINO(mp, XFS_AGINO_TO_AGBNO(mp,
846 irec->ino_startnum),
847 0));
848
849 return(bp);
850 }
851
852 /*
853 * these next routines return the filesystem blockno of the
854 * block containing the block "bno" in the file whose bmap
855 * tree (or extent list) is rooted by "rootblock".
856 *
857 * the next routines are utility routines for the third
858 * routine, get_bmapi().
859 */
860 /* ARGSUSED */
861 xfs_dfsbno_t
862 getfunc_extlist(xfs_mount_t *mp,
863 xfs_ino_t ino,
864 xfs_dinode_t *dip,
865 xfs_dfiloff_t bno,
866 int whichfork)
867 {
868 xfs_dfiloff_t fbno;
869 xfs_dfilblks_t bcnt;
870 xfs_dfsbno_t fsbno;
871 xfs_dfsbno_t final_fsbno = NULLDFSBNO;
872 xfs_bmbt_rec_32_t *rootblock = (xfs_bmbt_rec_32_t *)
873 XFS_DFORK_PTR_ARCH(dip, whichfork, ARCH_CONVERT);
874 xfs_extnum_t nextents = XFS_DFORK_NEXTENTS_ARCH(dip, whichfork, ARCH_CONVERT);
875 int i;
876 int flag;
877
878 for (i = 0; i < nextents; i++) {
879 convert_extent(rootblock + i, &fbno, &fsbno, &bcnt, &flag);
880
881 if (fbno <= bno && bno < fbno + bcnt) {
882 final_fsbno = bno - fbno + fsbno;
883 break;
884 }
885 }
886
887 return(final_fsbno);
888 }
889
890 xfs_dfsbno_t
891 getfunc_btree(xfs_mount_t *mp,
892 xfs_ino_t ino,
893 xfs_dinode_t *dip,
894 xfs_dfiloff_t bno,
895 int whichfork)
896 {
897 int i;
898 int prev_level;
899 int flag;
900 int found;
901 xfs_bmbt_rec_32_t *rec;
902 xfs_bmbt_ptr_t *pp;
903 xfs_bmbt_key_t *key;
904 xfs_bmdr_key_t *rkey;
905 xfs_bmdr_ptr_t *rp;
906 xfs_dfiloff_t fbno;
907 xfs_dfsbno_t fsbno;
908 xfs_dfilblks_t bcnt;
909 xfs_buf_t *bp;
910 xfs_dfsbno_t final_fsbno = NULLDFSBNO;
911 xfs_bmbt_block_t *block;
912 xfs_bmdr_block_t *rootblock = (xfs_bmdr_block_t *)
913 XFS_DFORK_PTR_ARCH(dip, whichfork, ARCH_CONVERT);
914
915 ASSERT(rootblock->bb_level != 0);
916 /*
917 * deal with root block, it's got a slightly different
918 * header structure than interior nodes. We know that
919 * a btree should have at least 2 levels otherwise it
920 * would be an extent list.
921 */
922 rkey = XFS_BTREE_KEY_ADDR(
923 XFS_DFORK_SIZE_ARCH(dip, mp, whichfork, ARCH_CONVERT),
924 xfs_bmdr, rootblock, 1,
925 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE_ARCH(dip,
926 mp, whichfork, ARCH_CONVERT),
927 xfs_bmdr, 1));
928 rp = XFS_BTREE_PTR_ADDR(
929 XFS_DFORK_SIZE_ARCH(dip, mp, whichfork, ARCH_CONVERT),
930 xfs_bmdr, rootblock, 1,
931 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE_ARCH(dip,
932 mp, whichfork, ARCH_CONVERT),
933 xfs_bmdr, 1));
934 for (found = -1, i = 0; i < rootblock->bb_numrecs - 1; i++) {
935 if (rkey[i].br_startoff <= bno
936 && bno < rkey[i+1].br_startoff) {
937 found = i;
938 break;
939 }
940 }
941 if (i == rootblock->bb_numrecs - 1 && bno >= rkey[i].br_startoff)
942 found = i;
943
944 ASSERT(found != -1);
945
946 fsbno = INT_GET(rp[found], ARCH_CONVERT);
947
948 ASSERT(verify_dfsbno(mp, fsbno));
949
950 bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, fsbno),
951 XFS_FSB_TO_BB(mp, 1), 0);
952 if (!bp) {
953 do_error("cannot read bmap block %llu\n", fsbno);
954 return(NULLDFSBNO);
955 }
956 block = XFS_BUF_TO_BMBT_BLOCK(bp);
957
958 /*
959 * ok, now traverse any interior btree nodes
960 */
961 prev_level = rootblock->bb_level;
962
963 while (INT_GET(block->bb_level, ARCH_CONVERT) > 0) {
964 ASSERT(INT_GET(block->bb_level, ARCH_CONVERT) < prev_level);
965
966 prev_level = INT_GET(block->bb_level, ARCH_CONVERT);
967
968 if (INT_GET(block->bb_numrecs, ARCH_CONVERT) >
969 mp->m_bmap_dmxr[1]) {
970 do_warn("# of bmap records in inode %llu exceeds max "
971 "(%u, max - %u)\n",
972 ino, INT_GET(block->bb_numrecs, ARCH_CONVERT),
973 mp->m_bmap_dmxr[1]);
974 libxfs_putbuf(bp);
975 return(NULLDFSBNO);
976 }
977 if (verbose && INT_GET(block->bb_numrecs, ARCH_CONVERT) <
978 mp->m_bmap_dmnr[1]) {
979 do_warn("- # of bmap records in inode %llu < than min "
980 "(%u, min - %u), proceeding ...\n",
981 ino, INT_GET(block->bb_numrecs, ARCH_CONVERT),
982 mp->m_bmap_dmnr[1]);
983 }
984 key = XFS_BTREE_KEY_ADDR(mp->m_sb.sb_blocksize,
985 xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]);
986 pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize,
987 xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]);
988 for ( found = -1, i = 0;
989 i < INT_GET(block->bb_numrecs, ARCH_CONVERT) - 1;
990 i++) {
991 if (INT_GET(key[i].br_startoff, ARCH_CONVERT) <= bno &&
992 bno < INT_GET(key[i+1].br_startoff, ARCH_CONVERT)) {
993 found = i;
994 break;
995 }
996 }
997 if (i == INT_GET(block->bb_numrecs, ARCH_CONVERT) - 1 &&
998 bno >= INT_GET(key[i].br_startoff, ARCH_CONVERT))
999 found = i;
1000
1001 ASSERT(found != -1);
1002 fsbno = INT_GET(pp[found], ARCH_CONVERT);
1003
1004 ASSERT(verify_dfsbno(mp, fsbno));
1005
1006 /*
1007 * release current btree block and read in the
1008 * next btree block to be traversed
1009 */
1010 libxfs_putbuf(bp);
1011 bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, fsbno),
1012 XFS_FSB_TO_BB(mp, 1), 0);
1013 if (!bp) {
1014 do_error("cannot read bmap block %llu\n", fsbno);
1015 return(NULLDFSBNO);
1016 }
1017 block = XFS_BUF_TO_BMBT_BLOCK(bp);
1018 }
1019
1020 /*
1021 * current block must be a leaf block
1022 */
1023 ASSERT(INT_GET(block->bb_level, ARCH_CONVERT) == 0);
1024 if (INT_GET(block->bb_numrecs, ARCH_CONVERT) > mp->m_bmap_dmxr[0]) {
1025 do_warn("# of bmap records in inode %llu greater than max "
1026 "(%u, max - %u)\n",
1027 ino, INT_GET(block->bb_numrecs, ARCH_CONVERT),
1028 mp->m_bmap_dmxr[0]);
1029 libxfs_putbuf(bp);
1030 return(NULLDFSBNO);
1031 }
1032 if (verbose && INT_GET(block->bb_numrecs, ARCH_CONVERT) <
1033 mp->m_bmap_dmnr[0])
1034 do_warn("- # of bmap records in inode %llu < min "
1035 "(%u, min - %u), continuing...\n",
1036 ino, INT_GET(block->bb_numrecs, ARCH_CONVERT),
1037 mp->m_bmap_dmnr[0]);
1038
1039 rec = (xfs_bmbt_rec_32_t *)XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize,
1040 xfs_bmbt, block, 1, mp->m_bmap_dmxr[0]);
1041 for (i = 0; i < INT_GET(block->bb_numrecs, ARCH_CONVERT); i++) {
1042 convert_extent(rec + i, &fbno, &fsbno, &bcnt, &flag);
1043
1044 if (fbno <= bno && bno < fbno + bcnt) {
1045 final_fsbno = bno - fbno + fsbno;
1046 break;
1047 }
1048 }
1049 libxfs_putbuf(bp);
1050
1051 if (final_fsbno == NULLDFSBNO)
1052 do_warn("could not map block %llu\n", bno);
1053
1054 return(final_fsbno);
1055 }
1056
1057 /*
1058 * this could be smarter. maybe we should have an open inode
1059 * routine that would get the inode buffer and return back
1060 * an inode handle. I'm betting for the moment that this
1061 * is used only by the directory and attribute checking code
1062 * and that the avl tree find and buffer cache search are
1063 * relatively cheap. If they're too expensive, we'll just
1064 * have to fix this and add an inode handle to the da btree
1065 * cursor.
1066 *
1067 * caller is responsible for checking doubly referenced blocks
1068 * and references to holes
1069 */
1070 xfs_dfsbno_t
1071 get_bmapi(xfs_mount_t *mp, xfs_dinode_t *dino_p,
1072 xfs_ino_t ino_num, xfs_dfiloff_t bno, int whichfork)
1073 {
1074 xfs_dfsbno_t fsbno;
1075
1076 switch (XFS_DFORK_FORMAT_ARCH(dino_p, whichfork, ARCH_CONVERT)) {
1077 case XFS_DINODE_FMT_EXTENTS:
1078 fsbno = getfunc_extlist(mp, ino_num, dino_p, bno, whichfork);
1079 break;
1080 case XFS_DINODE_FMT_BTREE:
1081 fsbno = getfunc_btree(mp, ino_num, dino_p, bno, whichfork);
1082 break;
1083 case XFS_DINODE_FMT_LOCAL:
1084 do_error("get_bmapi() called for local inode %llu\n", ino_num);
1085 fsbno = NULLDFSBNO;
1086 break;
1087 default:
1088 /*
1089 * shouldn't happen
1090 */
1091 do_error("bad inode format for inode %llu\n", ino_num);
1092 fsbno = NULLDFSBNO;
1093 }
1094
1095 return(fsbno);
1096 }
1097
1098 /*
1099 * higher level inode processing stuff starts here:
1100 * first, one utility routine for each type of inode
1101 */
1102
1103 /*
1104 * return 1 if inode should be cleared, 0 otherwise
1105 */
1106 /* ARGSUSED */
1107 int
1108 process_btinode(
1109 xfs_mount_t *mp,
1110 xfs_agnumber_t agno,
1111 xfs_agino_t ino,
1112 xfs_dinode_t *dip,
1113 int type,
1114 int *dirty,
1115 xfs_drfsbno_t *tot,
1116 __uint64_t *nex,
1117 blkmap_t **blkmapp,
1118 int whichfork,
1119 int check_dups)
1120 {
1121 xfs_bmdr_block_t *dib;
1122 xfs_dfiloff_t last_key;
1123 xfs_dfiloff_t first_key = 0;
1124 xfs_ino_t lino;
1125 xfs_bmbt_ptr_t *pp;
1126 xfs_bmbt_key_t *pkey;
1127 char *forkname;
1128 int i;
1129 bmap_cursor_t cursor;
1130
1131 dib = (xfs_bmdr_block_t *)XFS_DFORK_PTR_ARCH(dip, whichfork, ARCH_CONVERT);
1132 lino = XFS_AGINO_TO_INO(mp, agno, ino);
1133 *tot = 0;
1134 *nex = 0;
1135
1136 if (whichfork == XFS_DATA_FORK)
1137 forkname = "data";
1138 else
1139 forkname = "attr";
1140
1141 if (INT_GET(dib->bb_level, ARCH_CONVERT) == 0) {
1142 /*
1143 * This should never happen since a btree inode
1144 * has to have at least one other block in the
1145 * bmap in addition to the root block in the
1146 * inode's data fork.
1147 *
1148 * XXX - if we were going to fix up the inode,
1149 * we'd try to treat the fork as an interior
1150 * node and see if we could get an accurate
1151 * level value from one of the blocks pointed
1152 * to by the pointers in the fork. For now
1153 * though, we just bail (and blow out the inode).
1154 */
1155 do_warn("bad level 0 in inode %llu bmap btree root block\n",
1156 XFS_AGINO_TO_INO(mp, agno, ino));
1157 return(1);
1158 }
1159 /*
1160 * use bmdr/dfork_dsize since the root block is in the data fork
1161 */
1162 init_bm_cursor(&cursor, INT_GET(dib->bb_level, ARCH_CONVERT) + 1);
1163
1164 if (XFS_BMDR_SPACE_CALC(INT_GET(dib->bb_numrecs, ARCH_CONVERT)) >
1165 ((whichfork == XFS_DATA_FORK) ?
1166 XFS_DFORK_DSIZE_ARCH(dip, mp, ARCH_CONVERT) :
1167 XFS_DFORK_ASIZE_ARCH(dip, mp, ARCH_CONVERT))) {
1168 do_warn(
1169 "indicated size of %s btree root (%d bytes) > space in inode %llu %s fork\n",
1170 forkname, XFS_BMDR_SPACE_CALC(INT_GET(dib->bb_numrecs, ARCH_CONVERT)),
1171 lino, forkname);
1172 return(1);
1173 }
1174
1175 pp = XFS_BTREE_PTR_ADDR(XFS_DFORK_SIZE_ARCH(dip, mp, whichfork, ARCH_CONVERT),
1176 xfs_bmdr, dib, 1,
1177 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE_ARCH(dip, mp, whichfork, ARCH_CONVERT),
1178 xfs_bmdr, 0));
1179 pkey = XFS_BTREE_KEY_ADDR(XFS_DFORK_SIZE_ARCH(dip, mp, whichfork, ARCH_CONVERT),
1180 xfs_bmdr, dib, 1,
1181 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE_ARCH(dip, mp, whichfork, ARCH_CONVERT),
1182 xfs_bmdr, 0));
1183
1184 last_key = NULLDFILOFF;
1185
1186 for (i = 0; i < INT_GET(dib->bb_numrecs, ARCH_CONVERT); i++) {
1187 /*
1188 * XXX - if we were going to do more to fix up the inode
1189 * btree, we'd do it right here. For now, if there's a
1190 * problem, we'll bail out and presumably clear the inode.
1191 */
1192 if (!verify_dfsbno(mp, INT_GET(pp[i], ARCH_CONVERT))) {
1193 do_warn("bad bmap btree ptr 0x%llx in ino %llu\n",
1194 INT_GET(pp[i], ARCH_CONVERT), lino);
1195 return(1);
1196 }
1197
1198 if (scan_lbtree((xfs_dfsbno_t)INT_GET(pp[i], ARCH_CONVERT), INT_GET(dib->bb_level, ARCH_CONVERT),
1199 scanfunc_bmap, type, whichfork,
1200 lino, tot, nex, blkmapp, &cursor,
1201 1, check_dups))
1202 return(1);
1203 /*
1204 * fix key (offset) mismatches between the keys in root
1205 * block records and the first key of each child block.
1206 * fixes cases where entries have been shifted between
1207 * blocks but the parent hasn't been updated
1208 */
1209 if (check_dups == 0 &&
1210 cursor.level[INT_GET(dib->bb_level, ARCH_CONVERT)-1].first_key !=
1211 INT_GET(pkey[i].br_startoff, ARCH_CONVERT)) {
1212 if (!no_modify) {
1213 do_warn(
1214 "correcting key in bmbt root (was %llu, now %llu) in inode %llu %s fork\n",
1215 INT_GET(pkey[i].br_startoff, ARCH_CONVERT),
1216 cursor.level[INT_GET(dib->bb_level, ARCH_CONVERT)-1].first_key,
1217 XFS_AGINO_TO_INO(mp, agno, ino),
1218 forkname);
1219 *dirty = 1;
1220 INT_SET(pkey[i].br_startoff, ARCH_CONVERT, cursor.level[INT_GET(dib->bb_level, ARCH_CONVERT)-1].first_key);
1221 } else {
1222 do_warn(
1223 "bad key in bmbt root (is %llu, would reset to %llu) in inode %llu %s fork\n",
1224 INT_GET(pkey[i].br_startoff, ARCH_CONVERT),
1225 cursor.level[INT_GET(dib->bb_level, ARCH_CONVERT)-1].first_key,
1226 XFS_AGINO_TO_INO(mp, agno, ino),
1227 forkname);
1228 }
1229 }
1230 /*
1231 * make sure that keys are in ascending order. blow out
1232 * inode if the ordering doesn't hold
1233 */
1234 if (check_dups == 0) {
1235 if (last_key != NULLDFILOFF && last_key >=
1236 cursor.level[INT_GET(dib->bb_level, ARCH_CONVERT)-1].first_key) {
1237 do_warn(
1238 "out of order bmbt root key %llu in inode %llu %s fork\n",
1239 first_key,
1240 XFS_AGINO_TO_INO(mp, agno, ino),
1241 forkname);
1242 return(1);
1243 }
1244 last_key = cursor.level[INT_GET(dib->bb_level, ARCH_CONVERT)-1].first_key;
1245 }
1246 }
1247 /*
1248 * Check that the last child block's forward sibling pointer
1249 * is NULL.
1250 */
1251 if (check_dups == 0 &&
1252 cursor.level[0].right_fsbno != NULLDFSBNO) {
1253 do_warn(
1254 "bad fwd (right) sibling pointer (saw %llu should be NULLDFSBNO)\n",
1255 cursor.level[0].right_fsbno);
1256 do_warn(
1257 "\tin inode %u (%s fork) bmap btree block %llu\n",
1258 XFS_AGINO_TO_INO(mp, agno, ino), forkname,
1259 cursor.level[0].fsbno);
1260 return(1);
1261 }
1262
1263 return(0);
1264 }
1265
1266 /*
1267 * return 1 if inode should be cleared, 0 otherwise
1268 */
1269 /* ARGSUSED */
1270 int
1271 process_exinode(
1272 xfs_mount_t *mp,
1273 xfs_agnumber_t agno,
1274 xfs_agino_t ino,
1275 xfs_dinode_t *dip,
1276 int type,
1277 int *dirty,
1278 xfs_drfsbno_t *tot,
1279 __uint64_t *nex,
1280 blkmap_t **blkmapp,
1281 int whichfork,
1282 int check_dups)
1283 {
1284 xfs_ino_t lino;
1285 xfs_bmbt_rec_32_t *rp;
1286 xfs_dfiloff_t first_key;
1287 xfs_dfiloff_t last_key;
1288
1289 lino = XFS_AGINO_TO_INO(mp, agno, ino);
1290 rp = (xfs_bmbt_rec_32_t *)XFS_DFORK_PTR_ARCH(dip, whichfork, ARCH_CONVERT);
1291 *tot = 0;
1292 *nex = XFS_DFORK_NEXTENTS_ARCH(dip, whichfork, ARCH_CONVERT);
1293 /*
1294 * XXX - if we were going to fix up the btree record,
1295 * we'd do it right here. For now, if there's a problem,
1296 * we'll bail out and presumably clear the inode.
1297 */
1298 if (check_dups == 0)
1299 return(process_bmbt_reclist(mp, rp, *nex, type, lino,
1300 tot, blkmapp, &first_key, &last_key,
1301 whichfork));
1302 else
1303 return(scan_bmbt_reclist(mp, rp, *nex, type, lino, tot,
1304 whichfork));
1305 }
1306
1307 /*
1308 * return 1 if inode should be cleared, 0 otherwise
1309 */
1310 /* ARGSUSED */
1311 int
1312 process_lclinode(
1313 xfs_mount_t *mp,
1314 xfs_agnumber_t agno,
1315 xfs_agino_t ino,
1316 xfs_dinode_t *dip,
1317 int type,
1318 int *dirty,
1319 xfs_drfsbno_t *tot,
1320 __uint64_t *nex,
1321 blkmap_t **blkmapp,
1322 int whichfork,
1323 int check_dups)
1324 {
1325 xfs_attr_shortform_t *asf;
1326 xfs_dinode_core_t *dic;
1327 xfs_ino_t lino;
1328
1329 *tot = 0;
1330 *nex = 0; /* local inodes have 0 extents */
1331
1332 dic = &dip->di_core;
1333 lino = XFS_AGINO_TO_INO(mp, agno, ino);
1334 if (whichfork == XFS_DATA_FORK &&
1335 INT_GET(dic->di_size, ARCH_CONVERT) > XFS_DFORK_DSIZE_ARCH(dip, mp, ARCH_CONVERT)) {
1336 do_warn(
1337 "local inode %llu data fork is too large (size = %lld, max = %d)\n",
1338 lino, INT_GET(dic->di_size, ARCH_CONVERT), XFS_DFORK_DSIZE_ARCH(dip, mp, ARCH_CONVERT));
1339 return(1);
1340 } else if (whichfork == XFS_ATTR_FORK) {
1341 asf = (xfs_attr_shortform_t *) XFS_DFORK_APTR_ARCH(dip, ARCH_CONVERT);
1342 if (INT_GET(asf->hdr.totsize, ARCH_CONVERT) > XFS_DFORK_ASIZE_ARCH(dip, mp, ARCH_CONVERT)) {
1343 do_warn(
1344 "local inode %llu attr fork too large (size %d, max = %d)\n",
1345 lino, INT_GET(asf->hdr.totsize, ARCH_CONVERT),
1346 XFS_DFORK_ASIZE_ARCH(dip, mp, ARCH_CONVERT));
1347 return(1);
1348 }
1349 if (INT_GET(asf->hdr.totsize, ARCH_CONVERT) < sizeof(xfs_attr_sf_hdr_t)) {
1350 do_warn(
1351 "local inode %llu attr too small (size = %d, min size = %d)\n",
1352 lino, INT_GET(asf->hdr.totsize, ARCH_CONVERT),
1353 sizeof(xfs_attr_sf_hdr_t));
1354 return(1);
1355 }
1356 }
1357
1358 return(0);
1359 }
1360
1361 int
1362 process_symlink_extlist(xfs_mount_t *mp, xfs_ino_t lino, xfs_dinode_t *dino)
1363 {
1364 xfs_dfsbno_t start; /* start */
1365 xfs_dfilblks_t cnt; /* count */
1366 xfs_dfiloff_t offset; /* offset */
1367 xfs_dfiloff_t expected_offset;
1368 xfs_bmbt_rec_32_t *rp;
1369 int numrecs;
1370 int i;
1371 int max_blocks;
1372 int whichfork = XFS_DATA_FORK;
1373 int flag;
1374
1375 if (INT_GET(dino->di_core.di_size, ARCH_CONVERT) <= XFS_DFORK_SIZE_ARCH(dino, mp, whichfork, ARCH_CONVERT)) {
1376 if (dino->di_core.di_format == XFS_DINODE_FMT_LOCAL) {
1377 return(0);
1378 } else {
1379 do_warn(
1380 "mismatch between format (%d) and size (%lld) in symlink ino %llu\n",
1381 dino->di_core.di_format,
1382 INT_GET(dino->di_core.di_size, ARCH_CONVERT),
1383 lino);
1384 return(1);
1385 }
1386 } else if (dino->di_core.di_format == XFS_DINODE_FMT_LOCAL) {
1387 do_warn(
1388 "mismatch between format (%d) and size (%lld) in symlink inode %llu\n",
1389 dino->di_core.di_format,
1390 INT_GET(dino->di_core.di_size, ARCH_CONVERT),
1391 lino);
1392 return(1);
1393 }
1394
1395 rp = (xfs_bmbt_rec_32_t *)XFS_DFORK_PTR_ARCH(dino, whichfork, ARCH_CONVERT);
1396 numrecs = XFS_DFORK_NEXTENTS_ARCH(dino, whichfork, ARCH_CONVERT);
1397
1398 /*
1399 * the max # of extents in a symlink inode is equal to the
1400 * number of max # of blocks required to store the symlink
1401 */
1402 if (numrecs > max_symlink_blocks) {
1403 do_warn(
1404 "bad number of extents (%d) in symlink %llu data fork\n",
1405 numrecs, lino);
1406 return(1);
1407 }
1408
1409 max_blocks = max_symlink_blocks;
1410 expected_offset = 0;
1411
1412 for (i = 0; numrecs > 0; i++, numrecs--) {
1413 convert_extent(rp, &offset, &start, &cnt, &flag);
1414
1415 if (offset != expected_offset) {
1416 do_warn(
1417 "bad extent #%d offset (%llu) in symlink %llu data fork\n",
1418 i, offset, lino);
1419 return(1);
1420 }
1421 if (cnt == 0 || cnt > max_blocks) {
1422 do_warn(
1423 "bad extent #%d count (%llu) in symlink %llu data fork\n",
1424 i, cnt, lino);
1425 return(1);
1426 }
1427
1428 max_blocks -= cnt;
1429 expected_offset += cnt;
1430 }
1431
1432 return(0);
1433 }
1434
1435 /*
1436 * takes a name and length and returns 1 if the name contains
1437 * a \0, returns 0 otherwise
1438 */
1439 int
1440 null_check(char *name, int length)
1441 {
1442 int i;
1443
1444 ASSERT(length < MAXPATHLEN);
1445
1446 for (i = 0; i < length; i++, name++) {
1447 if (*name == '\0')
1448 return(1);
1449 }
1450
1451 return(0);
1452 }
1453
1454 /*
1455 * like usual, returns 0 if everything's ok and 1 if something's
1456 * bogus
1457 */
1458 int
1459 process_symlink(xfs_mount_t *mp, xfs_ino_t lino, xfs_dinode_t *dino,
1460 blkmap_t *blkmap)
1461 {
1462 xfs_dfsbno_t fsbno;
1463 xfs_dinode_core_t *dinoc = &dino->di_core;
1464 xfs_buf_t *bp = NULL;
1465 char *symlink, *cptr, *buf_data;
1466 int i, size, amountdone;
1467 char data[MAXPATHLEN];
1468
1469 /*
1470 * check size against kernel symlink limits. we know
1471 * size is consistent with inode storage format -- e.g.
1472 * the inode is structurally ok so we don't have to check
1473 * for that
1474 */
1475 if (INT_GET(dinoc->di_size, ARCH_CONVERT) >= MAXPATHLEN) {
1476 do_warn("symlink in inode %llu too long (%lld chars)\n",
1477 lino, INT_GET(dinoc->di_size, ARCH_CONVERT));
1478 return(1);
1479 }
1480
1481 /*
1482 * have to check symlink component by component.
1483 * get symlink contents into data area
1484 */
1485 symlink = &data[0];
1486 if (INT_GET(dinoc->di_size, ARCH_CONVERT)
1487 <= XFS_DFORK_DSIZE_ARCH(dino, mp, ARCH_CONVERT)) {
1488 /*
1489 * local symlink, just copy the symlink out of the
1490 * inode into the data area
1491 */
1492 bcopy((char *)XFS_DFORK_DPTR_ARCH(dino, ARCH_CONVERT),
1493 symlink, INT_GET(dinoc->di_size, ARCH_CONVERT));
1494 } else {
1495 /*
1496 * stored in a meta-data file, have to bmap one block
1497 * at a time and copy the symlink into the data area
1498 */
1499 i = size = amountdone = 0;
1500 cptr = symlink;
1501
1502 while (amountdone < INT_GET(dinoc->di_size, ARCH_CONVERT)) {
1503 fsbno = blkmap_get(blkmap, i);
1504 if (fsbno != NULLDFSBNO)
1505 bp = libxfs_readbuf(mp->m_dev,
1506 XFS_FSB_TO_DADDR(mp, fsbno),
1507 XFS_FSB_TO_BB(mp, 1), 0);
1508 if (!bp || fsbno == NULLDFSBNO) {
1509 do_warn("cannot read inode %llu, file block %d,"
1510 " disk block %llu\n", lino, i, fsbno);
1511 return(1);
1512 }
1513
1514 buf_data = (char *)XFS_BUF_PTR(bp);
1515 size = MIN(INT_GET(dinoc->di_size, ARCH_CONVERT)
1516 - amountdone, (int)XFS_FSB_TO_BB(mp, 1)*BBSIZE);
1517 bcopy(buf_data, cptr, size);
1518 cptr += size;
1519 amountdone += size;
1520 i++;
1521 libxfs_putbuf(bp);
1522 }
1523 }
1524 data[INT_GET(dinoc->di_size, ARCH_CONVERT)] = '\0';
1525
1526 /*
1527 * check for nulls
1528 */
1529 if (null_check(symlink, (int) INT_GET(dinoc->di_size, ARCH_CONVERT))) {
1530 do_warn("found illegal null character in symlink inode %llu\n",
1531 lino);
1532 return(1);
1533 }
1534
1535 /*
1536 * check for any component being too long
1537 */
1538 if (INT_GET(dinoc->di_size, ARCH_CONVERT) >= MAXNAMELEN) {
1539 cptr = strchr(symlink, '/');
1540
1541 while (cptr != NULL) {
1542 if (cptr - symlink >= MAXNAMELEN) {
1543 do_warn(
1544 "component of symlink in inode %llu too long\n",
1545 lino);
1546 return(1);
1547 }
1548 symlink = cptr + 1;
1549 cptr = strchr(symlink, '/');
1550 }
1551
1552 if (strlen(symlink) >= MAXNAMELEN) {
1553 do_warn("component of symlink in inode %llu too long\n",
1554 lino);
1555 return(1);
1556 }
1557 }
1558
1559 return(0);
1560 }
1561
1562 /*
1563 * called to process the set of misc inode special inode types
1564 * that have no associated data storage (fifos, pipes, devices, etc.).
1565 */
1566 /* ARGSUSED */
1567 int
1568 process_misc_ino_types(xfs_mount_t *mp,
1569 xfs_dinode_t *dino,
1570 xfs_ino_t lino,
1571 int type)
1572 {
1573 /*
1574 * disallow mountpoint inodes until such time as the
1575 * kernel actually allows them to be created (will
1576 * probably require a superblock version rev, sigh).
1577 */
1578 if (type == XR_INO_MOUNTPOINT) {
1579 do_warn("inode %llu has bad inode type (IFMNT)\n", lino);
1580 return(1);
1581 }
1582
1583 /*
1584 * must also have a zero size
1585 */
1586 if (INT_GET(dino->di_core.di_size, ARCH_CONVERT) != 0) {
1587 switch (type) {
1588 case XR_INO_CHRDEV:
1589 do_warn("size of character device inode %llu != 0 "
1590 "(%lld bytes)\n", lino,
1591 INT_GET(dino->di_core.di_size, ARCH_CONVERT));
1592 break;
1593 case XR_INO_BLKDEV:
1594 do_warn("size of block device inode %llu != 0 "
1595 "(%lld bytes)\n", lino,
1596 INT_GET(dino->di_core.di_size, ARCH_CONVERT));
1597 break;
1598 case XR_INO_SOCK:
1599 do_warn("size of socket inode %llu != 0 "
1600 "(%lld bytes)\n", lino,
1601 INT_GET(dino->di_core.di_size, ARCH_CONVERT));
1602 break;
1603 case XR_INO_FIFO:
1604 do_warn("size of fifo inode %llu != 0 "
1605 "(%lld bytes)\n", lino,
1606 INT_GET(dino->di_core.di_size, ARCH_CONVERT));
1607 break;
1608 default:
1609 do_warn("Internal error - process_misc_ino_types, "
1610 "illegal type %d\n", type);
1611 abort();
1612 }
1613
1614 return(1);
1615 }
1616
1617 return(0);
1618 }
1619
1620 int
1621 process_misc_ino_types_blocks(xfs_drfsbno_t totblocks, xfs_ino_t lino, int type)
1622 {
1623 /*
1624 * you can not enforce all misc types have zero data fork blocks
1625 * by checking dino->di_core.di_nblocks because atotblocks (attribute
1626 * blocks) are part of nblocks. We must check this later when atotblocks
1627 * has been calculated or by doing a simple check that anExtents == 0.
1628 * We must also guarantee that totblocks is 0. Thus nblocks checking
1629 * will be done later in process_dinode_int for misc types.
1630 */
1631
1632 if (totblocks != 0) {
1633 switch (type) {
1634 case XR_INO_CHRDEV:
1635 do_warn(
1636 "size of character device inode %llu != 0 (%llu blocks)\n",
1637 lino, totblocks);
1638 break;
1639 case XR_INO_BLKDEV:
1640 do_warn(
1641 "size of block device inode %llu != 0 (%llu blocks)\n",
1642 lino, totblocks);
1643 break;
1644 case XR_INO_SOCK:
1645 do_warn(
1646 "size of socket inode %llu != 0 (%llu blocks)\n",
1647 lino, totblocks);
1648 break;
1649 case XR_INO_FIFO:
1650 do_warn(
1651 "size of fifo inode %llu != 0 (%llu blocks)\n",
1652 lino, totblocks);
1653 break;
1654 default:
1655 return(0);
1656 }
1657 return(1);
1658 }
1659 return (0);
1660 }
1661
1662 /*
1663 * returns 0 if the inode is ok, 1 if the inode is corrupt
1664 * check_dups can be set to 1 *only* when called by the
1665 * first pass of the duplicate block checking of phase 4.
1666 * *dirty is set > 0 if the dinode has been altered and
1667 * needs to be written out.
1668 *
1669 * for detailed, info, look at process_dinode() comments.
1670 */
1671 /* ARGSUSED */
1672 int
1673 process_dinode_int(xfs_mount_t *mp,
1674 xfs_dinode_t *dino,
1675 xfs_agnumber_t agno,
1676 xfs_agino_t ino,
1677 int was_free, /* 1 if inode is currently free */
1678 int *dirty, /* out == > 0 if inode is now dirty */
1679 int *cleared, /* out == 1 if inode was cleared */
1680 int *used, /* out == 1 if inode is in use */
1681 int verify_mode, /* 1 == verify but don't modify inode */
1682 int uncertain, /* 1 == inode is uncertain */
1683 int ino_discovery, /* 1 == check dirs for unknown inodes */
1684 int check_dups, /* 1 == check if inode claims
1685 * duplicate blocks */
1686 int extra_attr_check, /* 1 == do attribute format and value checks */
1687 int *isa_dir, /* out == 1 if inode is a directory */
1688 xfs_ino_t *parent) /* out -- parent if ino is a dir */
1689 {
1690 xfs_drfsbno_t totblocks = 0;
1691 xfs_drfsbno_t atotblocks = 0;
1692 xfs_dinode_core_t *dinoc;
1693 char *rstring;
1694 int type;
1695 int rtype;
1696 int do_rt;
1697 int err;
1698 int retval = 0;
1699 __uint64_t nextents;
1700 __uint64_t anextents;
1701 xfs_ino_t lino;
1702 const int is_free = 0;
1703 const int is_used = 1;
1704 int repair = 0;
1705 blkmap_t *ablkmap = NULL;
1706 blkmap_t *dblkmap = NULL;
1707 static char okfmts[] = {
1708 0, /* free inode */
1709 1 << XFS_DINODE_FMT_DEV, /* FIFO */
1710 1 << XFS_DINODE_FMT_DEV, /* CHR */
1711 0, /* type 3 unused */
1712 (1 << XFS_DINODE_FMT_LOCAL) |
1713 (1 << XFS_DINODE_FMT_EXTENTS) |
1714 (1 << XFS_DINODE_FMT_BTREE), /* DIR */
1715 0, /* type 5 unused */
1716 1 << XFS_DINODE_FMT_DEV, /* BLK */
1717 0, /* type 7 unused */
1718 (1 << XFS_DINODE_FMT_EXTENTS) |
1719 (1 << XFS_DINODE_FMT_BTREE), /* REG */
1720 0, /* type 9 unused */
1721 (1 << XFS_DINODE_FMT_LOCAL) |
1722 (1 << XFS_DINODE_FMT_EXTENTS), /* LNK */
1723 0, /* type 11 unused */
1724 1 << XFS_DINODE_FMT_DEV, /* SOCK */
1725 0, /* type 13 unused */
1726 1 << XFS_DINODE_FMT_UUID, /* MNT */
1727 0 /* type 15 unused */
1728 };
1729
1730 retval = 0;
1731 totblocks = atotblocks = 0;
1732 *dirty = *isa_dir = *cleared = 0;
1733 *used = is_used;
1734 type = rtype = XR_INO_UNKNOWN;
1735 rstring = NULL;
1736 do_rt = 0;
1737
1738 dinoc = &dino->di_core;
1739 lino = XFS_AGINO_TO_INO(mp, agno, ino);
1740
1741 /*
1742 * if in verify mode, don't modify the inode.
1743 *
1744 * if correcting, reset stuff that has known values
1745 *
1746 * if in uncertain mode, be silent on errors since we're
1747 * trying to find out if these are inodes as opposed
1748 * to assuming that they are. Just return the appropriate
1749 * return code in that case.
1750 */
1751
1752 if (INT_GET(dinoc->di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC) {
1753 retval++;
1754 if (!verify_mode) {
1755 do_warn("bad magic number 0x%x on inode %llu, ",
1756 INT_GET(dinoc->di_magic, ARCH_CONVERT), lino);
1757 if (!no_modify) {
1758 do_warn("resetting magic number\n");
1759 *dirty = 1;
1760 INT_SET(dinoc->di_magic, ARCH_CONVERT, XFS_DINODE_MAGIC);
1761 } else {
1762 do_warn("would reset magic number\n");
1763 }
1764 } else if (!uncertain) {
1765 do_warn("bad magic number 0x%x on inode %llu\n",
1766 INT_GET(dinoc->di_magic, ARCH_CONVERT), lino);
1767 }
1768 }
1769
1770 if (!XFS_DINODE_GOOD_VERSION(dinoc->di_version) ||
1771 (!fs_inode_nlink && dinoc->di_version > XFS_DINODE_VERSION_1)) {
1772 retval++;
1773 if (!verify_mode) {
1774 do_warn("bad version number 0x%x on inode %llu, ",
1775 dinoc->di_version, lino);
1776 if (!no_modify) {
1777 do_warn("resetting version number\n");
1778 *dirty = 1;
1779 dinoc->di_version = (fs_inode_nlink) ?
1780 XFS_DINODE_VERSION_2 :
1781 XFS_DINODE_VERSION_1;
1782 } else {
1783 do_warn("would reset version number\n");
1784 }
1785 } else if (!uncertain) {
1786 do_warn("bad version number 0x%x on inode %llu\n",
1787 dinoc->di_version, lino);
1788 }
1789 }
1790
1791 /*
1792 * blow out of here if the inode size is < 0
1793 */
1794 if (INT_GET(dinoc->di_size, ARCH_CONVERT) < 0) {
1795 retval++;
1796 if (!verify_mode) {
1797 do_warn("bad (negative) size %lld on inode %llu\n",
1798 INT_GET(dinoc->di_size, ARCH_CONVERT), lino);
1799 if (!no_modify) {
1800 *dirty += clear_dinode(mp, dino, lino);
1801 *cleared = 1;
1802 } else {
1803 *dirty = 1;
1804 *cleared = 1;
1805 }
1806 *used = is_free;
1807 } else if (!uncertain) {
1808 do_warn("bad (negative) size %lld on inode %llu\n",
1809 INT_GET(dinoc->di_size, ARCH_CONVERT), lino);
1810 }
1811
1812 return(1);
1813 }
1814
1815 /*
1816 * was_free value is not meaningful if we're in verify mode
1817 */
1818 if (!verify_mode && INT_GET(dinoc->di_mode, ARCH_CONVERT) == 0 && was_free == 1) {
1819 /*
1820 * easy case, inode free -- inode and map agree, clear
1821 * it just in case to ensure that format, etc. are
1822 * set correctly
1823 */
1824 if (!no_modify) {
1825 err = clear_dinode(mp, dino, lino);
1826 if (err) {
1827 *dirty = 1;
1828 *cleared = 1;
1829 }
1830 }
1831 *used = is_free;
1832 return(0);
1833 } else if (!verify_mode && INT_GET(dinoc->di_mode, ARCH_CONVERT) == 0 && was_free == 0) {
1834 /*
1835 * the inode looks free but the map says it's in use.
1836 * clear the inode just to be safe and mark the inode
1837 * free.
1838 */
1839 do_warn("imap claims a free inode %llu is in use, ", lino);
1840
1841 if (!no_modify) {
1842 do_warn("correcting imap and clearing inode\n");
1843
1844 err = clear_dinode(mp, dino, lino);
1845 if (err) {
1846 retval++;
1847 *dirty = 1;
1848 *cleared = 1;
1849 }
1850 } else {
1851 do_warn("would correct imap and clear inode\n");
1852
1853 *dirty = 1;
1854 *cleared = 1;
1855 }
1856
1857 *used = is_free;
1858
1859 return(retval > 0 ? 1 : 0);
1860 }
1861
1862 /*
1863 * because of the lack of any write ordering guarantee, it's
1864 * possible that the core got updated but the forks didn't.
1865 * so rather than be ambitious (and probably incorrect),
1866 * if there's an inconsistency, we get conservative and
1867 * just pitch the file. blow off checking formats of
1868 * free inodes since technically any format is legal
1869 * as we reset the inode when we re-use it.
1870 */
1871 if (INT_GET(dinoc->di_mode, ARCH_CONVERT) != 0 &&
1872 ((((INT_GET(dinoc->di_mode, ARCH_CONVERT) & IFMT) >> 12) > 15) ||
1873 dinoc->di_format < XFS_DINODE_FMT_DEV ||
1874 dinoc->di_format > XFS_DINODE_FMT_UUID ||
1875 (!(okfmts[(INT_GET(dinoc->di_mode, ARCH_CONVERT) & IFMT) >> 12] &
1876 (1 << dinoc->di_format))))) {
1877 /* bad inode format */
1878 retval++;
1879 if (!uncertain)
1880 do_warn("bad inode format in inode %llu\n", lino);
1881 if (!verify_mode) {
1882 if (!no_modify) {
1883 *dirty += clear_dinode(mp, dino, lino);
1884 ASSERT(*dirty > 0);
1885 }
1886 }
1887 *cleared = 1;
1888 *used = is_free;
1889
1890 return(retval > 0 ? 1 : 0);
1891 }
1892
1893 if (verify_mode)
1894 return(retval > 0 ? 1 : 0);
1895
1896 /*
1897 * clear the next unlinked field if necessary on a good
1898 * inode only during phase 4 -- when checking for inodes
1899 * referencing duplicate blocks. then it's safe because
1900 * we've done the inode discovery and have found all the inodes
1901 * we're going to find. check_dups is set to 1 only during
1902 * phase 4. Ugly.
1903 */
1904 if (check_dups && !no_modify)
1905 *dirty += clear_dinode_unlinked(mp, dino);
1906
1907 /* set type and map type info */
1908
1909 switch (INT_GET(dinoc->di_mode, ARCH_CONVERT) & IFMT) {
1910 case IFDIR:
1911 type = XR_INO_DIR;
1912 *isa_dir = 1;
1913 break;
1914 case IFREG:
1915 if (INT_GET(dinoc->di_flags, ARCH_CONVERT) & XFS_DIFLAG_REALTIME)
1916 type = XR_INO_RTDATA;
1917 else if (lino == mp->m_sb.sb_rbmino)
1918 type = XR_INO_RTBITMAP;
1919 else if (lino == mp->m_sb.sb_rsumino)
1920 type = XR_INO_RTSUM;
1921 else
1922 type = XR_INO_DATA;
1923 break;
1924 case IFLNK:
1925 type = XR_INO_SYMLINK;
1926 break;
1927 case IFCHR:
1928 type = XR_INO_CHRDEV;
1929 break;
1930 case IFBLK:
1931 type = XR_INO_BLKDEV;
1932 break;
1933 case IFSOCK:
1934 type = XR_INO_SOCK;
1935 break;
1936 case IFIFO:
1937 type = XR_INO_FIFO;
1938 break;
1939 case IFMNT:
1940 type = XR_INO_MOUNTPOINT;
1941 break;
1942 default:
1943 type = XR_INO_UNKNOWN;
1944 do_warn("Unexpected inode type %#o inode %llu\n",
1945 (int) (INT_GET(dinoc->di_mode, ARCH_CONVERT) & IFMT), lino);
1946 abort();
1947 break;
1948 }
1949
1950 /*
1951 * type checks for root, realtime inodes, and quota inodes
1952 */
1953 if (lino == mp->m_sb.sb_rootino && type != XR_INO_DIR) {
1954 do_warn("bad inode type for root inode %llu, ", lino);
1955 type = XR_INO_DIR;
1956
1957 if (!no_modify) {
1958 do_warn("resetting to directory\n");
1959 INT_MOD_EXPR(dinoc->di_mode, ARCH_CONVERT, &= ~(INT_GET(dinoc->di_mode, ARCH_CONVERT) & IFMT));
1960 INT_MOD_EXPR(dinoc->di_mode, ARCH_CONVERT, |= INT_GET(dinoc->di_mode, ARCH_CONVERT) & IFDIR);
1961 } else {
1962 do_warn("would reset to directory\n");
1963 }
1964 } else if (lino == mp->m_sb.sb_rsumino) {
1965 do_rt = 1;
1966 rstring = "summary";
1967 rtype = XR_INO_RTSUM;
1968 } else if (lino == mp->m_sb.sb_rbmino) {
1969 do_rt = 1;
1970 rstring = "bitmap";
1971 rtype = XR_INO_RTBITMAP;
1972 } else if (lino == mp->m_sb.sb_uquotino) {
1973 if (type != XR_INO_DATA) {
1974 do_warn("user quota inode has bad type 0x%x\n",
1975 INT_GET(dinoc->di_mode, ARCH_CONVERT) & IFMT);
1976
1977 if (!no_modify) {
1978 *dirty += clear_dinode(mp, dino, lino);
1979 ASSERT(*dirty > 0);
1980 }
1981
1982 *cleared = 1;
1983 *used = is_free;
1984 *isa_dir = 0;
1985
1986 mp->m_sb.sb_uquotino = NULLFSINO;
1987
1988 return(1);
1989 }
1990 } else if (lino == mp->m_sb.sb_gquotino) {
1991 if (type != XR_INO_DATA) {
1992 do_warn("group quota inode has bad type 0x%x\n",
1993 INT_GET(dinoc->di_mode, ARCH_CONVERT) & IFMT);
1994
1995 if (!no_modify) {
1996 *dirty += clear_dinode(mp, dino, lino);
1997 ASSERT(*dirty > 0);
1998 }
1999
2000 *cleared = 1;
2001 *used = is_free;
2002 *isa_dir = 0;
2003
2004 mp->m_sb.sb_gquotino = NULLFSINO;
2005
2006 return(1);
2007 }
2008 }
2009
2010 if (do_rt && type != rtype) {
2011 type = XR_INO_DATA;
2012
2013 do_warn("bad inode type for realtime %s inode %llu, ",
2014 rstring, lino);
2015
2016 if (!no_modify) {
2017 do_warn("resetting to regular file\n");
2018 INT_MOD_EXPR(dinoc->di_mode, ARCH_CONVERT, &= ~(INT_GET(dinoc->di_mode, ARCH_CONVERT) & IFMT));
2019 INT_MOD_EXPR(dinoc->di_mode, ARCH_CONVERT, |= INT_GET(dinoc->di_mode, ARCH_CONVERT) & IFREG);
2020 } else {
2021 do_warn("would reset to regular file\n");
2022 }
2023 }
2024
2025 /*
2026 * only realtime inodes should have extsize set
2027 */
2028 if (type != XR_INO_RTDATA && INT_GET(dinoc->di_extsize, ARCH_CONVERT) != 0) {
2029 do_warn(
2030 "bad non-zero extent size value %u for non-realtime inode %llu, ",
2031 INT_GET(dinoc->di_extsize, ARCH_CONVERT), lino);
2032
2033 if (!no_modify) {
2034 do_warn("resetting to zero\n");
2035 INT_ZERO(dinoc->di_extsize, ARCH_CONVERT);
2036 *dirty = 1;
2037 } else {
2038 do_warn("would reset to zero\n");
2039 }
2040 }
2041
2042 /*
2043 * for realtime inodes, check sizes to see that
2044 * they are consistent with the # of realtime blocks.
2045 * also, verify that they contain only one extent and
2046 * are extent format files. If anything's wrong, clear
2047 * the inode -- we'll recreate it in phase 6.
2048 */
2049 if (do_rt && INT_GET(dinoc->di_size, ARCH_CONVERT)
2050 != mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize) {
2051 do_warn("bad size %llu for realtime %s inode %llu\n",
2052 INT_GET(dinoc->di_size, ARCH_CONVERT), rstring, lino);
2053
2054 if (!no_modify) {
2055 *dirty += clear_dinode(mp, dino, lino);
2056 ASSERT(*dirty > 0);
2057 }
2058
2059 *cleared = 1;
2060 *used = is_free;
2061 *isa_dir = 0;
2062
2063 return(1);
2064 }
2065
2066 if (do_rt && mp->m_sb.sb_rblocks == 0 && INT_GET(dinoc->di_nextents, ARCH_CONVERT) != 0) {
2067 do_warn("bad # of extents (%u) for realtime %s inode %llu\n",
2068 INT_GET(dinoc->di_nextents, ARCH_CONVERT), rstring, lino);
2069
2070 if (!no_modify) {
2071 *dirty += clear_dinode(mp, dino, lino);
2072 ASSERT(*dirty > 0);
2073 }
2074
2075 *cleared = 1;
2076 *used = is_free;
2077 *isa_dir = 0;
2078
2079 return(1);
2080 }
2081
2082 /*
2083 * Setup nextents and anextents for blkmap_alloc calls.
2084 */
2085 nextents = INT_GET(dinoc->di_nextents, ARCH_CONVERT);
2086 if (nextents > INT_GET(dinoc->di_nblocks, ARCH_CONVERT) || nextents > XFS_MAX_INCORE_EXTENTS)
2087 nextents = 1;
2088 anextents = INT_GET(dinoc->di_anextents, ARCH_CONVERT);
2089 if (anextents > INT_GET(dinoc->di_nblocks, ARCH_CONVERT) || anextents > XFS_MAX_INCORE_EXTENTS)
2090 anextents = 1;
2091
2092 /*
2093 * general size/consistency checks:
2094 *
2095 * if the size <= size of the data fork, directories must be
2096 * local inodes unlike regular files which would be extent inodes.
2097 * all the other mentioned types have to have a zero size value.
2098 *
2099 * if the size and format don't match, get out now rather than
2100 * risk trying to process a non-existent extents or btree
2101 * type data fork.
2102 */
2103 switch (type) {
2104 case XR_INO_DIR:
2105 if (INT_GET(dinoc->di_size, ARCH_CONVERT) <= XFS_DFORK_DSIZE_ARCH(dino, mp, ARCH_CONVERT)
2106 && dinoc->di_format != XFS_DINODE_FMT_LOCAL) {
2107 do_warn(
2108 "mismatch between format (%d) and size (%lld) in directory ino %llu\n",
2109 dinoc->di_format,
2110 INT_GET(dinoc->di_size, ARCH_CONVERT),
2111 lino);
2112
2113 if (!no_modify) {
2114 *dirty += clear_dinode(mp,
2115 dino, lino);
2116 ASSERT(*dirty > 0);
2117 }
2118
2119 *cleared = 1;
2120 *used = is_free;
2121 *isa_dir = 0;
2122
2123 return(1);
2124 }
2125 if (dinoc->di_format != XFS_DINODE_FMT_LOCAL)
2126 dblkmap = blkmap_alloc(nextents);
2127 break;
2128 case XR_INO_SYMLINK:
2129 if (process_symlink_extlist(mp, lino, dino)) {
2130 do_warn("bad data fork in symlink %llu\n", lino);
2131
2132 if (!no_modify) {
2133 *dirty += clear_dinode(mp,
2134 dino, lino);
2135 ASSERT(*dirty > 0);
2136 }
2137
2138 *cleared = 1;
2139 *used = is_free;
2140 *isa_dir = 0;
2141
2142 return(1);
2143 }
2144 if (dinoc->di_format != XFS_DINODE_FMT_LOCAL)
2145 dblkmap = blkmap_alloc(nextents);
2146 break;
2147 case XR_INO_CHRDEV: /* fall through to FIFO case ... */
2148 case XR_INO_BLKDEV: /* fall through to FIFO case ... */
2149 case XR_INO_SOCK: /* fall through to FIFO case ... */
2150 case XR_INO_MOUNTPOINT: /* fall through to FIFO case ... */
2151 case XR_INO_FIFO:
2152 if (process_misc_ino_types(mp, dino, lino, type)) {
2153 if (!no_modify) {
2154 *dirty += clear_dinode(mp, dino, lino);
2155 ASSERT(*dirty > 0);
2156 }
2157
2158 *cleared = 1;
2159 *used = is_free;
2160 *isa_dir = 0;
2161
2162 return(1);
2163 }
2164 break;
2165 case XR_INO_RTDATA:
2166 /*
2167 * if we have no realtime blocks, any inode claiming
2168 * to be a real-time file is bogus
2169 */
2170 if (mp->m_sb.sb_rblocks == 0) {
2171 do_warn(
2172 "found inode %llu claiming to be a real-time file\n",
2173 lino);
2174
2175 if (!no_modify) {
2176 *dirty += clear_dinode(mp, dino, lino);
2177 ASSERT(*dirty > 0);
2178 }
2179
2180 *cleared = 1;
2181 *used = is_free;
2182 *isa_dir = 0;
2183
2184 return(1);
2185 }
2186 break;
2187 case XR_INO_RTBITMAP:
2188 if (INT_GET(dinoc->di_size, ARCH_CONVERT) != (__int64_t) mp->m_sb.sb_rbmblocks *
2189 mp->m_sb.sb_blocksize) {
2190 do_warn(
2191 "realtime bitmap inode %llu has bad size %lld (should be %lld)\n",
2192 lino, INT_GET(dinoc->di_size, ARCH_CONVERT),
2193 (__int64_t) mp->m_sb.sb_rbmblocks *
2194 mp->m_sb.sb_blocksize);
2195
2196 if (!no_modify) {
2197 *dirty += clear_dinode(mp, dino, lino);
2198 ASSERT(*dirty > 0);
2199 }
2200
2201 *cleared = 1;
2202 *used = is_free;
2203 *isa_dir = 0;
2204
2205 return(1);
2206 }
2207 dblkmap = blkmap_alloc(nextents);
2208 break;
2209 case XR_INO_RTSUM:
2210 if (INT_GET(dinoc->di_size, ARCH_CONVERT) != mp->m_rsumsize) {
2211 do_warn(
2212 "realtime summary inode %llu has bad size %lld (should be %d)\n",
2213 lino, INT_GET(dinoc->di_size, ARCH_CONVERT), mp->m_rsumsize);
2214
2215 if (!no_modify) {
2216 *dirty += clear_dinode(mp, dino, lino);
2217 ASSERT(*dirty > 0);
2218 }
2219
2220 *cleared = 1;
2221 *used = is_free;
2222 *isa_dir = 0;
2223
2224 return(1);
2225 }
2226 dblkmap = blkmap_alloc(nextents);
2227 break;
2228 default:
2229 break;
2230 }
2231
2232 /*
2233 * check for illegal values of forkoff
2234 */
2235 err = 0;
2236 if (dinoc->di_forkoff != 0) {
2237 switch (dinoc->di_format) {
2238 case XFS_DINODE_FMT_DEV:
2239 if (dinoc->di_forkoff !=
2240 (roundup(sizeof(dev_t), 8) >> 3)) {
2241 do_warn(
2242 "bad attr fork offset %d in dev inode %llu, should be %d\n",
2243 (int) dinoc->di_forkoff,
2244 lino,
2245 (int) (roundup(sizeof(dev_t), 8) >> 3));
2246 err = 1;
2247 }
2248 break;
2249 case XFS_DINODE_FMT_UUID:
2250 if (dinoc->di_forkoff !=
2251 (roundup(sizeof(uuid_t), 8) >> 3)) {
2252 do_warn(
2253 "bad attr fork offset %d in uuid inode %llu, should be %d\n",
2254 (int) dinoc->di_forkoff,
2255 lino,
2256 (int)(roundup(sizeof(uuid_t), 8) >> 3));
2257 err = 1;
2258 }
2259 break;
2260 case XFS_DINODE_FMT_LOCAL: /* fall through ... */
2261 case XFS_DINODE_FMT_EXTENTS: /* fall through ... */
2262 case XFS_DINODE_FMT_BTREE:
2263 if (dinoc->di_forkoff != mp->m_attroffset >> 3) {
2264 do_warn(
2265 "bad attr fork offset %d in inode %llu, should be %d\n",
2266 (int) dinoc->di_forkoff,
2267 lino,
2268 (int) (mp->m_attroffset >> 3));
2269 err = 1;
2270 }
2271 break;
2272 default:
2273 do_error("unexpected inode format %d\n",
2274 (int) dinoc->di_format);
2275 break;
2276 }
2277 }
2278
2279 if (err) {
2280 if (!no_modify) {
2281 *dirty += clear_dinode(mp, dino, lino);
2282 ASSERT(*dirty > 0);
2283 }
2284
2285 *cleared = 1;
2286 *used = is_free;
2287 *isa_dir = 0;
2288 blkmap_free(dblkmap);
2289 return(1);
2290 }
2291
2292 /*
2293 * check data fork -- if it's bad, clear the inode
2294 */
2295 nextents = 0;
2296 switch (dinoc->di_format) {
2297 case XFS_DINODE_FMT_LOCAL:
2298 err = process_lclinode(mp, agno, ino, dino, type,
2299 dirty, &totblocks, &nextents, &dblkmap,
2300 XFS_DATA_FORK, check_dups);
2301 break;
2302 case XFS_DINODE_FMT_EXTENTS:
2303 err = process_exinode(mp, agno, ino, dino, type,
2304 dirty, &totblocks, &nextents, &dblkmap,
2305 XFS_DATA_FORK, check_dups);
2306 break;
2307 case XFS_DINODE_FMT_BTREE:
2308 err = process_btinode(mp, agno, ino, dino, type,
2309 dirty, &totblocks, &nextents, &dblkmap,
2310 XFS_DATA_FORK, check_dups);
2311 break;
2312 case XFS_DINODE_FMT_DEV: /* fall through */
2313 case XFS_DINODE_FMT_UUID:
2314 err = 0;
2315 break;
2316 default:
2317 do_error("unknown format %d, ino %llu (mode = %d)\n",
2318 dinoc->di_format, lino, INT_GET(dinoc->di_mode, ARCH_CONVERT));
2319 }
2320
2321 if (err) {
2322 /*
2323 * problem in the data fork, clear out the inode
2324 * and get out
2325 */
2326 do_warn("bad data fork in inode %llu\n", lino);
2327
2328 if (!no_modify) {
2329 *dirty += clear_dinode(mp, dino, lino);
2330 ASSERT(*dirty > 0);
2331 }
2332
2333 *cleared = 1;
2334 *used = is_free;
2335 *isa_dir = 0;
2336 blkmap_free(dblkmap);
2337
2338 return(1);
2339 }
2340
2341 if (check_dups) {
2342 /*
2343 * if check_dups was non-zero, we have to
2344 * re-process data fork to set bitmap since the
2345 * bitmap wasn't set the first time through
2346 */
2347 switch (dinoc->di_format) {
2348 case XFS_DINODE_FMT_LOCAL:
2349 err = process_lclinode(mp, agno, ino, dino, type,
2350 dirty, &totblocks, &nextents, &dblkmap,
2351 XFS_DATA_FORK, 0);
2352 break;
2353 case XFS_DINODE_FMT_EXTENTS:
2354 err = process_exinode(mp, agno, ino, dino, type,
2355 dirty, &totblocks, &nextents, &dblkmap,
2356 XFS_DATA_FORK, 0);
2357 break;
2358 case XFS_DINODE_FMT_BTREE:
2359 err = process_btinode(mp, agno, ino, dino, type,
2360 dirty, &totblocks, &nextents, &dblkmap,
2361 XFS_DATA_FORK, 0);
2362 break;
2363 case XFS_DINODE_FMT_DEV: /* fall through */
2364 case XFS_DINODE_FMT_UUID:
2365 err = 0;
2366 break;
2367 default:
2368 do_error("unknown format %d, ino %llu (mode = %d)\n",
2369 dinoc->di_format, lino, INT_GET(dinoc->di_mode, ARCH_CONVERT));
2370 }
2371
2372 if (no_modify && err != 0) {
2373 *cleared = 1;
2374 *used = is_free;
2375 *isa_dir = 0;
2376 blkmap_free(dblkmap);
2377
2378 return(1);
2379 }
2380
2381 ASSERT(err == 0);
2382 }
2383
2384 /*
2385 * check attribute fork if necessary. attributes are
2386 * always stored in the regular filesystem.
2387 */
2388
2389 if (!XFS_DFORK_Q_ARCH(dino, ARCH_CONVERT) && dinoc->di_aformat != XFS_DINODE_FMT_EXTENTS) {
2390 do_warn("bad attribute format %d in inode %llu, ",
2391 dinoc->di_aformat, lino);
2392 if (!no_modify) {
2393 do_warn("resetting value\n");
2394 dinoc->di_aformat = XFS_DINODE_FMT_EXTENTS;
2395 *dirty = 1;
2396 } else
2397 do_warn("would reset value\n");
2398 anextents = 0;
2399 } else if (XFS_DFORK_Q_ARCH(dino, ARCH_CONVERT)) {
2400 switch (dinoc->di_aformat) {
2401 case XFS_DINODE_FMT_LOCAL:
2402 anextents = 0;
2403 err = process_lclinode(mp, agno, ino, dino,
2404 type, dirty, &atotblocks, &anextents, &ablkmap,
2405 XFS_ATTR_FORK, check_dups);
2406 break;
2407 case XFS_DINODE_FMT_EXTENTS:
2408 ablkmap = blkmap_alloc(anextents);
2409 anextents = 0;
2410 err = process_exinode(mp, agno, ino, dino,
2411 type, dirty, &atotblocks, &anextents, &ablkmap,
2412 XFS_ATTR_FORK, check_dups);
2413 break;
2414 case XFS_DINODE_FMT_BTREE:
2415 ablkmap = blkmap_alloc(anextents);
2416 anextents = 0;
2417 err = process_btinode(mp, agno, ino, dino,
2418 type, dirty, &atotblocks, &anextents, &ablkmap,
2419 XFS_ATTR_FORK, check_dups);
2420 break;
2421 default:
2422 anextents = 0;
2423 do_warn("illegal attribute format %d, ino %llu\n",
2424 dinoc->di_aformat, lino);
2425 err = 1;
2426 break;
2427 }
2428
2429 if (err) {
2430 /*
2431 * clear the attribute fork if necessary. we can't
2432 * clear the inode because we've already put the
2433 * inode space info into the blockmap.
2434 *
2435 * XXX - put the inode onto the "move it" list and
2436 * log the the attribute scrubbing
2437 */
2438 do_warn("bad attribute fork in inode %llu", lino);
2439
2440 if (!no_modify) {
2441 if (delete_attr_ok) {
2442 do_warn(", clearing attr fork\n");
2443 *dirty += clear_dinode_attr(mp,
2444 dino, lino);
2445 } else {
2446 do_warn("\n");
2447 *dirty += clear_dinode(mp,
2448 dino, lino);
2449 }
2450 ASSERT(*dirty > 0);
2451 } else {
2452 do_warn(", would clear attr fork\n");
2453 }
2454
2455 atotblocks = 0;
2456 anextents = 0;
2457
2458 if (delete_attr_ok) {
2459 if (!no_modify)
2460 dinoc->di_aformat = XFS_DINODE_FMT_LOCAL;
2461 } else {
2462 *cleared = 1;
2463 *used = is_free;
2464 *isa_dir = 0;
2465 blkmap_free(dblkmap);
2466 blkmap_free(ablkmap);
2467 }
2468 return(1);
2469
2470 } else if (check_dups) {
2471 switch (dinoc->di_aformat) {
2472 case XFS_DINODE_FMT_LOCAL:
2473 err = process_lclinode(mp, agno, ino, dino,
2474 type, dirty, &atotblocks, &anextents,
2475 &ablkmap, XFS_ATTR_FORK, 0);
2476 break;
2477 case XFS_DINODE_FMT_EXTENTS:
2478 err = process_exinode(mp, agno, ino, dino,
2479 type, dirty, &atotblocks, &anextents,
2480 &ablkmap, XFS_ATTR_FORK, 0);
2481 break;
2482 case XFS_DINODE_FMT_BTREE:
2483 err = process_btinode(mp, agno, ino, dino,
2484 type, dirty, &atotblocks, &anextents,
2485 &ablkmap, XFS_ATTR_FORK, 0);
2486 break;
2487 default:
2488 do_error("illegal attribute fmt %d, ino %llu\n",
2489 dinoc->di_aformat, lino);
2490 }
2491
2492 if (no_modify && err != 0) {
2493 *cleared = 1;
2494 *used = is_free;
2495 *isa_dir = 0;
2496 blkmap_free(dblkmap);
2497 blkmap_free(ablkmap);
2498
2499 return(1);
2500 }
2501
2502 ASSERT(err == 0);
2503 }
2504
2505 /*
2506 * do attribute semantic-based consistency checks now
2507 */
2508
2509 /* get this only in phase 3, not in both phase 3 and 4 */
2510 if (extra_attr_check) {
2511 if ((err = process_attributes(mp, lino, dino, ablkmap,
2512 &repair))) {
2513 do_warn("problem with attribute contents in inode %llu\n",lino);
2514 if(!repair) {
2515 /* clear attributes if not done already */
2516 if (!no_modify) {
2517 *dirty += clear_dinode_attr(
2518 mp, dino, lino);
2519 dinoc->di_aformat =
2520 XFS_DINODE_FMT_LOCAL;
2521 } else {
2522 do_warn("would clear attr fork\n");
2523 }
2524 atotblocks = 0;
2525 anextents = 0;
2526 }
2527 else {
2528 *dirty = 1; /* it's been repaired */
2529 }
2530 }
2531 }
2532 blkmap_free(ablkmap);
2533
2534 } else
2535 anextents = 0;
2536
2537 /*
2538 * enforce totblocks is 0 for misc types
2539 */
2540 if (process_misc_ino_types_blocks(totblocks, lino, type)) {
2541 if (!no_modify) {
2542 *dirty += clear_dinode(mp, dino, lino);
2543 ASSERT(*dirty > 0);
2544 }
2545 *cleared = 1;
2546 *used = is_free;
2547 *isa_dir = 0;
2548 blkmap_free(dblkmap);
2549
2550 return(1);
2551 }
2552
2553 /*
2554 * correct space counters if required
2555 */
2556 if (totblocks + atotblocks != INT_GET(dinoc->di_nblocks, ARCH_CONVERT)) {
2557 if (!no_modify) {
2558 do_warn("correcting nblocks for inode %llu, was %llu - counted %llu\n",
2559 lino, INT_GET(dinoc->di_nblocks, ARCH_CONVERT),
2560 totblocks + atotblocks);
2561 *dirty = 1;
2562 INT_SET(dinoc->di_nblocks, ARCH_CONVERT, totblocks + atotblocks);
2563 } else {
2564 do_warn(
2565 "bad nblocks %llu for inode %llu, would reset to %llu\n",
2566 INT_GET(dinoc->di_nblocks, ARCH_CONVERT), lino,
2567 totblocks + atotblocks);
2568 }
2569 }
2570
2571 if (nextents > MAXEXTNUM) {
2572 do_warn("too many data fork extents (%llu) in inode %llu\n",
2573 nextents, lino);
2574
2575 if (!no_modify) {
2576 *dirty += clear_dinode(mp, dino, lino);
2577 ASSERT(*dirty > 0);
2578 }
2579 *cleared = 1;
2580 *used = is_free;
2581 *isa_dir = 0;
2582 blkmap_free(dblkmap);
2583
2584 return(1);
2585 }
2586 if (nextents != INT_GET(dinoc->di_nextents, ARCH_CONVERT)) {
2587 if (!no_modify) {
2588 do_warn("correcting nextents for inode %llu, was %d - counted %llu\n",
2589 lino, INT_GET(dinoc->di_nextents, ARCH_CONVERT), nextents);
2590 *dirty = 1;
2591 INT_SET(dinoc->di_nextents, ARCH_CONVERT, (xfs_extnum_t) nextents);
2592 } else {
2593 do_warn(
2594 "bad nextents %d for inode %llu, would reset to %llu\n",
2595 INT_GET(dinoc->di_nextents, ARCH_CONVERT), lino, nextents);
2596 }
2597 }
2598
2599 if (anextents > MAXAEXTNUM) {
2600 do_warn("too many attr fork extents (%llu) in inode %llu\n",
2601 anextents, lino);
2602
2603 if (!no_modify) {
2604 *dirty += clear_dinode(mp, dino, lino);
2605 ASSERT(*dirty > 0);
2606 }
2607 *cleared = 1;
2608 *used = is_free;
2609 *isa_dir = 0;
2610 blkmap_free(dblkmap);
2611
2612 return(1);
2613 }
2614 if (anextents != INT_GET(dinoc->di_anextents, ARCH_CONVERT)) {
2615 if (!no_modify) {
2616 do_warn("correcting anextents for inode %llu, was %d - counted %llu\n",
2617 lino, INT_GET(dinoc->di_anextents, ARCH_CONVERT), anextents);
2618 *dirty = 1;
2619 INT_SET(dinoc->di_anextents, ARCH_CONVERT, (xfs_aextnum_t) anextents);
2620 } else {
2621 do_warn(
2622 "bad anextents %d for inode %llu, would reset to %llu\n",
2623 INT_GET(dinoc->di_anextents, ARCH_CONVERT), lino, anextents);
2624 }
2625 }
2626
2627 /*
2628 * do any semantic type-based checking here
2629 */
2630 switch (type) {
2631 case XR_INO_DIR:
2632 if (XFS_SB_VERSION_HASDIRV2(&mp->m_sb))
2633 err = process_dir2(mp, lino, dino, ino_discovery,
2634 dirty, "", parent, dblkmap);
2635 else
2636 err = process_dir(mp, lino, dino, ino_discovery,
2637 dirty, "", parent, dblkmap);
2638 if (err)
2639 do_warn(
2640 "problem with directory contents in inode %llu\n",
2641 lino);
2642 break;
2643 case XR_INO_RTBITMAP:
2644 /* process_rtbitmap XXX */
2645 err = 0;
2646 break;
2647 case XR_INO_RTSUM:
2648 /* process_rtsummary XXX */
2649 err = 0;
2650 break;
2651 case XR_INO_SYMLINK:
2652 if ((err = process_symlink(mp, lino, dino, dblkmap)))
2653 do_warn("problem with symbolic link in inode %llu\n",
2654 lino);
2655 break;
2656 case XR_INO_DATA: /* fall through to FIFO case ... */
2657 case XR_INO_RTDATA: /* fall through to FIFO case ... */
2658 case XR_INO_CHRDEV: /* fall through to FIFO case ... */
2659 case XR_INO_BLKDEV: /* fall through to FIFO case ... */
2660 case XR_INO_SOCK: /* fall through to FIFO case ... */
2661 case XR_INO_FIFO:
2662 err = 0;
2663 break;
2664 default:
2665 printf("Unexpected inode type\n");
2666 abort();
2667 }
2668
2669 blkmap_free(dblkmap);
2670
2671 if (err) {
2672 /*
2673 * problem in the inode type-specific semantic
2674 * checking, clear out the inode and get out
2675 */
2676 if (!no_modify) {
2677 *dirty += clear_dinode(mp, dino, lino);
2678 ASSERT(*dirty > 0);
2679 }
2680 *cleared = 1;
2681 *used = is_free;
2682 *isa_dir = 0;
2683
2684 return(1);
2685 }
2686
2687 /*
2688 * check nlinks feature, if it's a version 1 inode,
2689 * just leave nlinks alone. even if it's set wrong,
2690 * it'll be reset when read in.
2691 */
2692 if (dinoc->di_version > XFS_DINODE_VERSION_1 && !fs_inode_nlink) {
2693 /*
2694 * do we have a fs/inode version mismatch with a valid
2695 * version 2 inode here that has to stay version 2 or
2696 * lose links?
2697 */
2698 if (INT_GET(dinoc->di_nlink, ARCH_CONVERT) > XFS_MAXLINK_1) {
2699 /*
2700 * yes. are nlink inodes allowed?
2701 */
2702 if (fs_inode_nlink_allowed) {
2703 /*
2704 * yes, update status variable which will
2705 * cause sb to be updated later.
2706 */
2707 fs_inode_nlink = 1;
2708 do_warn(
2709 "version 2 inode %llu claims > %u links,",
2710 lino, XFS_MAXLINK_1);
2711 if (!no_modify) {
2712 do_warn(
2713 "updating superblock version number\n");
2714 } else {
2715 do_warn(
2716 "would update superblock version number\n");
2717 }
2718 } else {
2719 /*
2720 * no, have to convert back to onlinks
2721 * even if we lose some links
2722 */
2723 do_warn(
2724 "WARNING: version 2 inode %llu claims > %u links,",
2725 lino, XFS_MAXLINK_1);
2726 if (!no_modify) {
2727 do_warn(
2728 "converting back to version 1,\n\tthis may destroy %d links\n",
2729 INT_GET(dinoc->di_nlink, ARCH_CONVERT)
2730 - XFS_MAXLINK_1);
2731
2732 dinoc->di_version =
2733 XFS_DINODE_VERSION_1;
2734 INT_SET(dinoc->di_nlink, ARCH_CONVERT, XFS_MAXLINK_1);
2735 INT_SET(dinoc->di_onlink, ARCH_CONVERT, XFS_MAXLINK_1);
2736
2737 *dirty = 1;
2738 } else {
2739 do_warn(
2740 "would convert back to version 1,\n\tthis might destroy %d links\n",
2741 INT_GET(dinoc->di_nlink, ARCH_CONVERT)
2742 - XFS_MAXLINK_1);
2743 }
2744 }
2745 } else {
2746 /*
2747 * do we have a v2 inode that we could convert back
2748 * to v1 without losing any links? if we do and
2749 * we have a mismatch between superblock bits and the
2750 * version bit, alter the version bit in this case.
2751 *
2752 * the case where we lost links was handled above.
2753 */
2754 do_warn("found version 2 inode %llu, ", lino);
2755 if (!no_modify) {
2756 do_warn("converting back to version 1\n");
2757
2758 dinoc->di_version =
2759 XFS_DINODE_VERSION_1;
2760 INT_SET(dinoc->di_onlink, ARCH_CONVERT, INT_GET(dinoc->di_nlink, ARCH_CONVERT));
2761
2762 *dirty = 1;
2763 } else {
2764 do_warn("would convert back to version 1\n");
2765 }
2766 }
2767 }
2768
2769 /*
2770 * ok, if it's still a version 2 inode, it's going
2771 * to stay a version 2 inode. it should have a zero
2772 * onlink field, so clear it.
2773 */
2774 if (dinoc->di_version > XFS_DINODE_VERSION_1 &&
2775 INT_GET(dinoc->di_onlink, ARCH_CONVERT) > 0 && fs_inode_nlink > 0) {
2776 if (!no_modify) {
2777 do_warn(
2778 "clearing obsolete nlink field in version 2 inode %llu, was %d, now 0\n",
2779 lino, INT_GET(dinoc->di_onlink, ARCH_CONVERT));
2780 INT_ZERO(dinoc->di_onlink, ARCH_CONVERT);
2781 *dirty = 1;
2782 } else {
2783 do_warn(
2784 "would clear obsolete nlink field in version 2 inode %llu, currently %d\n",
2785 lino, INT_GET(dinoc->di_onlink, ARCH_CONVERT));
2786 *dirty = 1;
2787 }
2788 }
2789
2790 return(retval > 0 ? 1 : 0);
2791 }
2792
2793 /*
2794 * returns 1 if inode is used, 0 if free.
2795 * performs any necessary salvaging actions.
2796 * note that we leave the generation count alone
2797 * because nothing we could set it to would be
2798 * guaranteed to be correct so the best guess for
2799 * the correct value is just to leave it alone.
2800 *
2801 * The trick is detecting empty files. For those,
2802 * the core and the forks should all be in the "empty"
2803 * or zero-length state -- a zero or possibly minimum length
2804 * (in the case of dirs) extent list -- although inline directories
2805 * and symlinks might be handled differently. So it should be
2806 * possible to sanity check them against each other.
2807 *
2808 * If the forks are an empty extent list though, then forget it.
2809 * The file is toast anyway since we can't recover its storage.
2810 *
2811 * Parameters:
2812 * Ins:
2813 * mp -- mount structure
2814 * dino -- pointer to on-disk inode structure
2815 * agno/ino -- inode numbers
2816 * free -- whether the map thinks the inode is free (1 == free)
2817 * ino_discovery -- whether we should examine directory
2818 * contents to discover new inodes
2819 * check_dups -- whether we should check to see if the
2820 * inode references duplicate blocks
2821 * if so, we compare the inode's claimed
2822 * blocks against the contents of the
2823 * duplicate extent list but we don't
2824 * set the bitmap. If not, we set the
2825 * bitmap and try and detect multiply
2826 * claimed blocks using the bitmap.
2827 * Outs:
2828 * dirty -- whether we changed the inode (1 == yes)
2829 * cleared -- whether we cleared the inode (1 == yes). In
2830 * no modify mode, if we would have cleared it
2831 * used -- 1 if the inode is used, 0 if free. In no modify
2832 * mode, whether the inode should be used or free
2833 * isa_dir -- 1 if the inode is a directory, 0 if not. In
2834 * no modify mode, if the inode would be a dir or not.
2835 *
2836 * Return value -- 0 if the inode is good, 1 if it is/was corrupt
2837 */
2838
2839 int
2840 process_dinode(xfs_mount_t *mp,
2841 xfs_dinode_t *dino,
2842 xfs_agnumber_t agno,
2843 xfs_agino_t ino,
2844 int was_free,
2845 int *dirty,
2846 int *cleared,
2847 int *used,
2848 int ino_discovery,
2849 int check_dups,
2850 int extra_attr_check,
2851 int *isa_dir,
2852 xfs_ino_t *parent)
2853 {
2854 const int verify_mode = 0;
2855 const int uncertain = 0;
2856
2857 #ifdef XR_INODE_TRACE
2858 fprintf(stderr, "processing inode %d/%d\n", agno, ino);
2859 #endif
2860 return(process_dinode_int(mp, dino, agno, ino, was_free, dirty,
2861 cleared, used, verify_mode, uncertain,
2862 ino_discovery, check_dups, extra_attr_check,
2863 isa_dir, parent));
2864 }
2865
2866 /*
2867 * a more cursory check, check inode core, *DON'T* check forks
2868 * this basically just verifies whether the inode is an inode
2869 * and whether or not it has been totally trashed. returns 0
2870 * if the inode passes the cursory sanity check, 1 otherwise.
2871 */
2872 int
2873 verify_dinode(xfs_mount_t *mp,
2874 xfs_dinode_t *dino,
2875 xfs_agnumber_t agno,
2876 xfs_agino_t ino)
2877 {
2878 xfs_ino_t parent;
2879 int cleared = 0;
2880 int used = 0;
2881 int dirty = 0;
2882 int isa_dir = 0;
2883 const int verify_mode = 1;
2884 const int check_dups = 0;
2885 const int ino_discovery = 0;
2886 const int uncertain = 0;
2887
2888 return(process_dinode_int(mp, dino, agno, ino, 0, &dirty,
2889 &cleared, &used, verify_mode,
2890 uncertain, ino_discovery, check_dups,
2891 0, &isa_dir, &parent));
2892 }
2893
2894 /*
2895 * like above only for inode on the uncertain list. it sets
2896 * the uncertain flag which makes process_dinode_int quieter.
2897 * returns 0 if the inode passes the cursory sanity check, 1 otherwise.
2898 */
2899 int
2900 verify_uncertain_dinode(xfs_mount_t *mp,
2901 xfs_dinode_t *dino,
2902 xfs_agnumber_t agno,
2903 xfs_agino_t ino)
2904 {
2905 xfs_ino_t parent;
2906 int cleared = 0;
2907 int used = 0;
2908 int dirty = 0;
2909 int isa_dir = 0;
2910 const int verify_mode = 1;
2911 const int check_dups = 0;
2912 const int ino_discovery = 0;
2913 const int uncertain = 1;
2914
2915 return(process_dinode_int(mp, dino, agno, ino, 0, &dirty,
2916 &cleared, &used, verify_mode,
2917 uncertain, ino_discovery, check_dups,
2918 0, &isa_dir, &parent));
2919 }