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