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