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