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