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