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