1 /* $NetBSD: pass1.c,v 1.45 2008/10/09 15:50:46 christos Exp $ */
4 * Copyright (c) 1980, 1986, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)pass1.c 8.6 (Berkeley) 4/28/95";
37 __RCSID("$NetBSD: pass1.c,v 1.45 2008/10/09 15:50:46 christos Exp $");
41 #include <sys/param.h>
45 #include <ufs/ufs/dinode.h>
46 #include <ufs/ufs/dir.h>
47 #include <ufs/ffs/fs.h>
48 #include <ufs/ufs/ufs_bswap.h>
49 #include <ufs/ffs/ffs_extern.h>
59 #include "exitvalues.h"
61 static daddr_t badblk
;
62 static daddr_t dupblk
;
63 static void checkinode(ino_t
, struct inodesc
*);
69 ino_t inumber
, inosused
, ninosused
;
74 struct cg
*cgp
= cgrp
;
79 * Set file system reserved blocks in used block map.
81 for (c
= 0; c
< sblock
->fs_ncg
; c
++) {
82 cgd
= cgdmin(sblock
, c
);
84 i
= cgbase(sblock
, c
);
86 i
= cgsblock(sblock
, c
);
90 i
= sblock
->fs_csaddr
;
91 cgd
= i
+ howmany(sblock
->fs_cssize
, sblock
->fs_fsize
);
95 * Find all allocated blocks.
97 memset(&idesc
, 0, sizeof(struct inodesc
));
98 idesc
.id_func
= pass1check
;
100 for (c
= 0; c
< sblock
->fs_ncg
; c
++) {
101 inumber
= c
* sblock
->fs_ipg
;
102 setinodebuf(inumber
);
103 getblk(&cgblk
, cgtod(sblock
, c
), sblock
->fs_cgsize
);
104 memcpy(cgp
, cgblk
.b_un
.b_cg
, sblock
->fs_cgsize
);
105 if((doswap
&& !needswap
) || (!doswap
&& needswap
))
106 ffs_cg_swap(cgblk
.b_un
.b_cg
, cgp
, sblock
);
108 inosused
= cgp
->cg_initediblk
;
110 inosused
= sblock
->fs_ipg
;
112 printf("%s: phase 1: cyl group %d of %d (%d%%)\n",
113 cdevname(), c
, sblock
->fs_ncg
,
114 c
* 100 / sblock
->fs_ncg
);
118 progress_bar(cdevname(), preen
? NULL
: "phase 1",
120 #endif /* PROGRESS */
122 * If we are using soft updates, then we can trust the
123 * cylinder group inode allocation maps to tell us which
124 * inodes are allocated. We will scan the used inode map
125 * to find the inodes that are really in use, and then
126 * read only those inodes in from disk.
128 if (preen
&& usedsoftdep
) {
129 if (!cg_chkmagic(cgp
, 0))
130 pfatal("CG %d: BAD MAGIC NUMBER\n", c
);
131 cp
= &cg_inosused(cgp
, 0)[(inosused
- 1) / CHAR_BIT
];
132 for ( ; inosused
> 0; inosused
-= CHAR_BIT
, cp
--) {
135 for (i
= 1 << (CHAR_BIT
- 1); i
> 0; i
>>= 1) {
148 * Allocate inoinfo structures for the allocated inodes.
150 inostathead
[c
].il_numalloced
= inosused
;
152 inostathead
[c
].il_stat
= 0;
155 inospace
= inosused
* sizeof(*info
);
156 if (inospace
/ sizeof(*info
) != inosused
) {
157 pfatal("too many inodes %llu\n", (unsigned long long)
159 exit(FSCK_EXIT_CHECK_FAILED
);
161 info
= malloc(inospace
);
163 pfatal("cannot alloc %zu bytes for inoinfo\n",
165 exit(FSCK_EXIT_CHECK_FAILED
);
167 (void)memset(info
, 0, inospace
);
168 inostathead
[c
].il_stat
= info
;
170 * Scan the allocated inodes.
172 for (i
= 0; i
< inosused
; i
++, inumber
++) {
173 if (inumber
< ROOTINO
) {
174 (void)getnextinode(inumber
);
177 checkinode(inumber
, &idesc
);
180 if (inosused
< sblock
->fs_ipg
|| inumber
== lastino
)
183 * If we were not able to determine in advance which inodes
184 * were in use, then reduce the size of the inoinfo structure
185 * to the size necessary to describe the inodes that we
188 if (lastino
< (c
* sblock
->fs_ipg
))
191 ninosused
= lastino
- (c
* sblock
->fs_ipg
);
192 inostathead
[c
].il_numalloced
= ninosused
;
193 if (ninosused
== 0) {
194 free(inostathead
[c
].il_stat
);
195 inostathead
[c
].il_stat
= 0;
198 if (ninosused
!= inosused
) {
199 struct inostat
*ninfo
;
200 size_t ninospace
= ninosused
* sizeof(*ninfo
);
201 if (ninospace
/ sizeof(*info
) != ninosused
) {
202 pfatal("too many inodes %llu\n",
203 (unsigned long long)ninosused
);
204 exit(FSCK_EXIT_CHECK_FAILED
);
206 ninfo
= realloc(info
, ninospace
);
208 pfatal("cannot realloc %zu bytes to %zu "
209 "for inoinfo\n", inospace
, ninospace
);
210 exit(FSCK_EXIT_CHECK_FAILED
);
212 if (ninosused
> inosused
)
213 (void)memset(&ninfo
[inosused
], 0, ninospace
- inospace
);
214 inostathead
[c
].il_stat
= ninfo
;
220 #endif /* PROGRESS */
222 do_blkswap
= 0; /* has been done */
226 checkinode(ino_t inumber
, struct inodesc
*idesc
)
233 u_int64_t size
, kernmaxfilesize
;
235 char symbuf
[MAXBSIZE
];
236 struct inostat
*info
;
238 dp
= getnextinode(inumber
);
239 info
= inoinfo(inumber
);
240 mode
= iswap16(DIP(dp
, mode
)) & IFMT
;
241 size
= iswap64(DIP(dp
, size
));
244 (memcmp(dp
->dp2
.di_db
, ufs2_zino
.di_db
,
245 NDADDR
* sizeof(int64_t)) ||
246 memcmp(dp
->dp2
.di_ib
, ufs2_zino
.di_ib
,
247 NIADDR
* sizeof(int64_t))))
250 (memcmp(dp
->dp1
.di_db
, ufs1_zino
.di_db
,
251 NDADDR
* sizeof(int32_t)) ||
252 memcmp(dp
->dp1
.di_ib
, ufs1_zino
.di_ib
,
253 NIADDR
* sizeof(int32_t)))) ||
255 pfatal("PARTIALLY ALLOCATED INODE I=%llu",
256 (unsigned long long)inumber
);
257 if (reply("CLEAR") == 1) {
258 dp
= ginode(inumber
);
264 info
->ino_state
= USTATE
;
268 /* This should match the file size limit in ffs_mountfs(). */
270 kernmaxfilesize
= sblock
->fs_maxfilesize
;
272 kernmaxfilesize
= (u_int64_t
)0x80000000 * sblock
->fs_bsize
- 1;
273 if (size
> kernmaxfilesize
|| size
+ sblock
->fs_bsize
- 1 < size
||
274 (mode
== IFDIR
&& size
> MAXDIRSIZE
)) {
276 printf("bad size %llu:",(unsigned long long)size
);
279 if (!preen
&& mode
== IFMT
&& reply("HOLD BAD BLOCK") == 1) {
280 dp
= ginode(inumber
);
281 DIP_SET(dp
, size
, iswap64(sblock
->fs_fsize
));
282 size
= sblock
->fs_fsize
;
283 DIP_SET(dp
, mode
, iswap16(IFREG
|0600));
286 ndb
= howmany(size
, sblock
->fs_bsize
);
289 printf("bad size %llu ndb %lld:",
290 (unsigned long long)size
, (long long)ndb
);
293 if (mode
== IFBLK
|| mode
== IFCHR
)
297 * Note that the old fastlink format always had di_blocks set
298 * to 0. Other than that we no longer use the `spare' field
299 * (which is now the extended uid) for sanity checking, the
300 * new format is the same as the old. We simply ignore the
301 * conversion altogether. - mycroft, 19MAY1994
303 if (!is_ufs2
&& doinglevel2
&&
304 size
> 0 && size
< MAXSYMLINKLEN_UFS1
&&
305 DIP(dp
, blocks
) != 0) {
306 if (bread(fsreadfd
, symbuf
,
307 fsbtodb(sblock
, iswap32(DIP(dp
, db
[0]))),
309 errexit("cannot read symlink");
312 printf("convert symlink %llu(%s) "
314 (unsigned long long)inumber
, symbuf
,
315 (unsigned long long)size
);
317 dp
= ginode(inumber
);
318 memmove(dp
->dp1
.di_db
, symbuf
, (long)size
);
319 DIP_SET(dp
, blocks
, 0);
323 * Fake ndb value so direct/indirect block checks below
324 * will detect any garbage after symlink string.
326 if ((sblock
->fs_maxsymlinklen
< 0) ||
327 (size
< sblock
->fs_maxsymlinklen
) ||
328 (isappleufs
&& (size
< APPLEUFS_MAXSYMLINKLEN
)) ||
329 (sblock
->fs_maxsymlinklen
== 0 && DIP(dp
, blocks
) == 0)) {
331 ndb
= howmany(size
, sizeof(int64_t));
333 ndb
= howmany(size
, sizeof(int32_t));
336 for (ndb
= 1; j
> 1; j
--)
337 ndb
*= NINDIR(sblock
);
343 for (j
= ndb
; j
< NDADDR
; j
++)
344 if (DIP(dp
, db
[j
]) != 0) {
347 printf("bad direct addr ix %d: %d [ndb %lld]\n",
348 j
, iswap32(dp
->dp1
.di_db
[j
]),
351 printf("bad direct addr ix %d: %lld [ndb %lld]\n",
352 j
, (long long)iswap64(dp
->dp2
.di_db
[j
]),
359 for (j
= 0, ndb
-= NDADDR
; ndb
> 0; j
++)
360 ndb
/= NINDIR(sblock
);
362 for (; j
< NIADDR
; j
++)
363 if (DIP(dp
, ib
[j
]) != 0) {
366 printf("bad indirect addr: %d\n",
367 iswap32(dp
->dp1
.di_ib
[j
]));
369 printf("bad indirect addr: %lld\n",
370 (long long)iswap64(dp
->dp2
.di_ib
[j
]));
374 if (ftypeok(dp
) == 0)
377 info
->ino_linkcnt
= iswap16(DIP(dp
, nlink
));
378 if (info
->ino_linkcnt
<= 0) {
379 zlnp
= (struct zlncnt
*)malloc(sizeof *zlnp
);
382 pfatal("LINK COUNT TABLE OVERFLOW");
383 if (reply("CONTINUE") == 0) {
385 exit(FSCK_EXIT_CHECK_FAILED
);
388 zlnp
->zlncnt
= inumber
;
389 zlnp
->next
= zlnhead
;
395 info
->ino_state
= DCLEAR
;
397 info
->ino_state
= DSTATE
;
398 cacheino(dp
, inumber
);
401 info
->ino_state
= FSTATE
;
402 info
->ino_type
= IFTODT(mode
);
403 if (!is_ufs2
&& doinglevel2
&&
404 (iswap16(dp
->dp1
.di_ouid
) != (u_short
)-1 ||
405 iswap16(dp
->dp1
.di_ogid
) != (u_short
)-1)) {
406 dp
= ginode(inumber
);
407 dp
->dp1
.di_uid
= iswap32(iswap16(dp
->dp1
.di_ouid
));
408 dp
->dp1
.di_ouid
= iswap16(-1);
409 dp
->dp1
.di_gid
= iswap32(iswap16(dp
->dp1
.di_ogid
));
410 dp
->dp1
.di_ogid
= iswap16(-1);
414 idesc
->id_number
= inumber
;
415 if (iswap32(DIP(dp
, flags
)) & SF_SNAPSHOT
)
416 idesc
->id_type
= SNAP
;
418 idesc
->id_type
= ADDR
;
419 (void)ckinode(dp
, idesc
);
421 if (is_ufs2
&& iswap32(dp
->dp2
.di_extsize
) > 0) {
423 idesc
->id_type
= ADDR
;
424 ndb
= howmany(iswap32(dp
->dp2
.di_extsize
), sblock
->fs_bsize
);
425 for (j
= 0; j
< NXADDR
; j
++) {
427 (offset
= blkoff(sblock
, iswap32(dp
->dp2
.di_extsize
))) != 0)
428 idesc
->id_numfrags
= numfrags(sblock
,
429 fragroundup(sblock
, offset
));
431 idesc
->id_numfrags
= sblock
->fs_frag
;
432 if (dp
->dp2
.di_extb
[j
] == 0)
434 idesc
->id_blkno
= iswap64(dp
->dp2
.di_extb
[j
]);
435 ret
= (*idesc
->id_func
)(idesc
);
441 idesc
->id_entryno
*= btodb(sblock
->fs_fsize
);
443 blocks
= iswap64(dp
->dp2
.di_blocks
);
445 blocks
= iswap32(dp
->dp1
.di_blocks
);
446 if (blocks
!= idesc
->id_entryno
) {
447 pwarn("INCORRECT BLOCK COUNT I=%llu (%lld should be %lld)",
448 (unsigned long long)inumber
, (long long)blocks
,
449 (long long)idesc
->id_entryno
);
451 printf(" (CORRECTED)\n");
452 else if (reply("CORRECT") == 0) {
456 dp
= ginode(inumber
);
458 dp
->dp2
.di_blocks
= iswap64(idesc
->id_entryno
);
460 dp
->dp1
.di_blocks
= iswap32((int32_t)idesc
->id_entryno
);
465 pfatal("UNKNOWN FILE TYPE I=%llu", (unsigned long long)inumber
);
466 info
->ino_state
= FCLEAR
;
467 if (reply("CLEAR") == 1) {
468 info
->ino_state
= USTATE
;
469 dp
= ginode(inumber
);
477 pass1check(struct inodesc
*idesc
)
481 daddr_t blkno
= idesc
->id_blkno
;
485 if (idesc
->id_type
== SNAP
) {
486 if (blkno
== BLK_NOCOPY
|| blkno
== BLK_SNAP
)
489 if ((anyout
= chkrange(blkno
, idesc
->id_numfrags
)) != 0) {
490 blkerror(idesc
->id_number
, "BAD", blkno
);
491 if (badblk
++ >= MAXBAD
) {
492 pwarn("EXCESSIVE BAD BLKS I=%llu",
493 (unsigned long long)idesc
->id_number
);
495 printf(" (SKIPPING)\n");
496 else if (reply("CONTINUE") == 0) {
499 exit(FSCK_EXIT_CHECK_FAILED
);
504 for (nfrags
= idesc
->id_numfrags
; nfrags
> 0; blkno
++, nfrags
--) {
505 if (anyout
&& chkrange(blkno
, 1)) {
507 } else if (!testbmap(blkno
)) {
511 blkerror(idesc
->id_number
, "DUP", blkno
);
512 if (dupblk
++ >= MAXDUP
) {
513 pwarn("EXCESSIVE DUP BLKS I=%llu",
514 (unsigned long long)idesc
->id_number
);
516 printf(" (SKIPPING)\n");
517 else if (reply("CONTINUE") == 0) {
520 exit(FSCK_EXIT_CHECK_FAILED
);
524 new = (struct dups
*)malloc(sizeof(struct dups
));
527 pfatal("DUP TABLE OVERFLOW.");
528 if (reply("CONTINUE") == 0) {
531 exit(FSCK_EXIT_CHECK_FAILED
);
537 duplist
= muldup
= new;
540 new->next
= muldup
->next
;
543 for (dlp
= duplist
; dlp
!= muldup
; dlp
= dlp
->next
)
544 if (dlp
->dup
== blkno
)
546 if (dlp
== muldup
&& dlp
->dup
!= blkno
)
550 * count the number of blocks found in id_entryno