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