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