2 * Copyright (c) 1980, 1986, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * @(#)pass1.c 8.6 (Berkeley) 4/28/95
30 * $FreeBSD: src/sbin/fsck/pass1.c,v 1.16.2.5 2002/06/23 22:34:58 iedowse Exp $
33 #include <sys/param.h>
35 #include <vfs/ufs/dinode.h>
36 #include <vfs/ufs/dir.h>
37 #include <vfs/ufs/fs.h>
44 static ufs_daddr_t badblk
;
45 static ufs_daddr_t dupblk
;
46 static ufs1_ino_t lastino
; /* last inode in use */
48 static void checkinode(ufs1_ino_t inumber
, struct inodesc
*);
55 int c
, i
, cgd
, inosused
;
60 * Set file system reserved blocks in used block map.
62 for (c
= 0; c
< sblock
.fs_ncg
; c
++) {
63 cgd
= cgdmin(&sblock
, c
);
65 i
= cgbase(&sblock
, c
);
67 i
= cgsblock(&sblock
, c
);
72 cgd
= i
+ howmany(sblock
.fs_cssize
, sblock
.fs_fsize
);
76 * Find all allocated blocks.
78 memset(&idesc
, 0, sizeof(struct inodesc
));
80 idesc
.id_func
= pass1check
;
82 for (c
= 0; c
< sblock
.fs_ncg
; c
++) {
83 inumber
= c
* sblock
.fs_ipg
;
85 inosused
= sblock
.fs_ipg
;
87 printf("%s: phase 1: cyl group %d of %d (%d%%)\n",
88 cdevname
, c
, sblock
.fs_ncg
,
89 c
* 100 / sblock
.fs_ncg
);
93 * If we are using soft updates, then we can trust the
94 * cylinder group inode allocation maps to tell us which
95 * inodes are allocated. We will scan the used inode map
96 * to find the inodes that are really in use, and then
97 * read only those inodes in from disk.
99 if (preen
&& usedsoftdep
) {
100 getblk(&cgblk
, cgtod(&sblock
, c
), sblock
.fs_cgsize
);
101 if (!cg_chkmagic(&cgrp
))
102 pfatal("CG %d: BAD MAGIC NUMBER\n", c
);
103 cp
= &cg_inosused(&cgrp
)[(sblock
.fs_ipg
- 1) / NBBY
];
104 for ( ; inosused
> 0; inosused
-= NBBY
, cp
--) {
107 for (i
= 1 << (NBBY
- 1); i
> 0; i
>>= 1) {
118 * Allocate inoinfo structures for the allocated inodes.
120 inostathead
[c
].il_numalloced
= inosused
;
122 inostathead
[c
].il_stat
= 0;
125 info
= calloc((unsigned)inosused
, sizeof(struct inostat
));
127 pfatal("cannot alloc %u bytes for inoinfo\n",
128 (unsigned)(sizeof(struct inostat
) * inosused
));
129 inostathead
[c
].il_stat
= info
;
131 * Scan the allocated inodes.
133 for (i
= 0; i
< inosused
; i
++, inumber
++) {
134 if (inumber
< ROOTINO
) {
135 getnextinode(inumber
);
138 checkinode(inumber
, &idesc
);
141 if (inosused
< sblock
.fs_ipg
|| inumber
== lastino
)
144 * If we were not able to determine in advance which inodes
145 * were in use, then reduce the size of the inoinfo structure
146 * to the size necessary to describe the inodes that we
149 inosused
= lastino
- (c
* sblock
.fs_ipg
);
152 inostathead
[c
].il_numalloced
= inosused
;
154 free(inostathead
[c
].il_stat
);
155 inostathead
[c
].il_stat
= 0;
158 info
= calloc((unsigned)inosused
, sizeof(struct inostat
));
160 pfatal("cannot alloc %u bytes for inoinfo\n",
161 (unsigned)(sizeof(struct inostat
) * inosused
));
162 memmove(info
, inostathead
[c
].il_stat
, inosused
* sizeof(*info
));
163 free(inostathead
[c
].il_stat
);
164 inostathead
[c
].il_stat
= info
;
170 checkinode(ufs1_ino_t inumber
, struct inodesc
*idesc
)
172 struct ufs1_dinode
*dp
;
174 u_int64_t kernmaxfilesize
;
179 dp
= getnextinode(inumber
);
180 mode
= dp
->di_mode
& IFMT
;
182 if (memcmp(dp
->di_db
, zino
.di_db
,
183 NDADDR
* sizeof(ufs_daddr_t
)) ||
184 memcmp(dp
->di_ib
, zino
.di_ib
,
185 NIADDR
* sizeof(ufs_daddr_t
)) ||
186 dp
->di_mode
|| dp
->di_size
) {
187 pfatal("PARTIALLY ALLOCATED INODE I=%u", inumber
);
188 if (reply("CLEAR") == 1) {
189 dp
= ginode(inumber
);
194 inoinfo(inumber
)->ino_state
= USTATE
;
198 /* This should match the file size limit in ffs_mountfs(). */
199 kernmaxfilesize
= (u_int64_t
)0x40000000 * sblock
.fs_bsize
- 1;
200 if (kernmaxfilesize
> (u_int64_t
)0x80000000u
* PAGE_SIZE
- 1)
201 kernmaxfilesize
= (u_int64_t
)0x80000000u
* PAGE_SIZE
- 1;
202 if (dp
->di_size
> kernmaxfilesize
||
203 dp
->di_size
> sblock
.fs_maxfilesize
||
204 (mode
== IFDIR
&& dp
->di_size
> MAXDIRSIZE
)) {
206 printf("bad size %ju:", (uintmax_t)dp
->di_size
);
209 if (!preen
&& mode
== IFMT
&& reply("HOLD BAD BLOCK") == 1) {
210 dp
= ginode(inumber
);
211 dp
->di_size
= sblock
.fs_fsize
;
212 dp
->di_mode
= IFREG
|0600;
215 if ((mode
== IFBLK
|| mode
== IFCHR
|| mode
== IFIFO
||
216 mode
== IFSOCK
) && dp
->di_size
!= 0) {
218 printf("bad special-file size %ju:", (uintmax_t)dp
->di_size
);
221 ndb
= howmany(dp
->di_size
, sblock
.fs_bsize
);
224 printf("bad size %ju ndb %d:",
225 (uintmax_t)dp
->di_size
, ndb
);
228 if (mode
== IFBLK
|| mode
== IFCHR
)
232 dp
->di_size
> 0 && dp
->di_size
< MAXSYMLINKLEN
&&
233 dp
->di_blocks
!= 0) {
234 symbuf
= alloca(secsize
);
235 if (bread(fsreadfd
, symbuf
,
236 fsbtodb(&sblock
, dp
->di_db
[0]),
238 errx(EEXIT
, "cannot read symlink");
240 symbuf
[dp
->di_size
] = 0;
241 printf("convert symlink %lu(%s) of size %ld\n",
242 (u_long
)inumber
, symbuf
, (long)dp
->di_size
);
244 dp
= ginode(inumber
);
245 memmove(dp
->di_shortlink
, symbuf
, (long)dp
->di_size
);
250 * Fake ndb value so direct/indirect block checks below
251 * will detect any garbage after symlink string.
253 if (dp
->di_size
< sblock
.fs_maxsymlinklen
) {
254 ndb
= howmany(dp
->di_size
, sizeof(ufs_daddr_t
));
257 for (ndb
= 1; j
> 1; j
--)
258 ndb
*= NINDIR(&sblock
);
263 for (j
= ndb
; j
< NDADDR
; j
++)
264 if (dp
->di_db
[j
] != 0) {
266 printf("bad direct addr: %ld\n",
270 for (j
= 0, ndb
-= NDADDR
; ndb
> 0; j
++)
271 ndb
/= NINDIR(&sblock
);
272 for (; j
< NIADDR
; j
++)
273 if (dp
->di_ib
[j
] != 0) {
275 printf("bad indirect addr: %ld\n",
279 if (ftypeok(dp
) == 0)
282 inoinfo(inumber
)->ino_linkcnt
= dp
->di_nlink
;
283 if (dp
->di_nlink
<= 0) {
284 zlnp
= (struct zlncnt
*)malloc(sizeof *zlnp
);
286 pfatal("LINK COUNT TABLE OVERFLOW");
287 if (reply("CONTINUE") == 0) {
292 zlnp
->zlncnt
= inumber
;
293 zlnp
->next
= zlnhead
;
298 if (dp
->di_size
== 0)
299 inoinfo(inumber
)->ino_state
= DCLEAR
;
301 inoinfo(inumber
)->ino_state
= DSTATE
;
302 cacheino(dp
, inumber
);
305 inoinfo(inumber
)->ino_state
= FSTATE
;
306 inoinfo(inumber
)->ino_type
= IFTODT(mode
);
308 (dp
->di_ouid
!= (u_short
)-1 || dp
->di_ogid
!= (u_short
)-1)) {
309 dp
= ginode(inumber
);
310 dp
->di_uid
= dp
->di_ouid
;
312 dp
->di_gid
= dp
->di_ogid
;
317 idesc
->id_number
= inumber
;
319 idesc
->id_entryno
*= btodb(sblock
.fs_fsize
);
320 if (dp
->di_blocks
!= idesc
->id_entryno
) {
321 pwarn("INCORRECT BLOCK COUNT I=%u (%d should be %d)",
322 inumber
, dp
->di_blocks
, idesc
->id_entryno
);
324 printf(" (CORRECTED)\n");
325 else if (reply("CORRECT") == 0)
327 dp
= ginode(inumber
);
328 dp
->di_blocks
= idesc
->id_entryno
;
333 pfatal("UNKNOWN FILE TYPE I=%u", inumber
);
334 inoinfo(inumber
)->ino_state
= FCLEAR
;
335 if (reply("CLEAR") == 1) {
336 inoinfo(inumber
)->ino_state
= USTATE
;
337 dp
= ginode(inumber
);
344 pass1check(struct inodesc
*idesc
)
348 ufs_daddr_t blkno
= idesc
->id_blkno
;
352 if ((anyout
= chkrange(blkno
, idesc
->id_numfrags
)) != 0) {
353 blkerror(idesc
->id_number
, "BAD", blkno
);
354 if (badblk
++ >= MAXBAD
) {
355 pwarn("EXCESSIVE BAD BLKS I=%u",
358 printf(" (SKIPPING)\n");
359 else if (reply("CONTINUE") == 0) {
366 for (nfrags
= idesc
->id_numfrags
; nfrags
> 0; blkno
++, nfrags
--) {
367 if (anyout
&& chkrange(blkno
, 1)) {
369 } else if (!testbmap(blkno
)) {
373 blkerror(idesc
->id_number
, "DUP", blkno
);
374 if (dupblk
++ >= MAXDUP
) {
375 pwarn("EXCESSIVE DUP BLKS I=%u",
378 printf(" (SKIPPING)\n");
379 else if (reply("CONTINUE") == 0) {
385 new = (struct dups
*)malloc(sizeof(struct dups
));
387 pfatal("DUP TABLE OVERFLOW.");
388 if (reply("CONTINUE") == 0) {
396 duplist
= muldup
= new;
399 new->next
= muldup
->next
;
402 for (dlp
= duplist
; dlp
!= muldup
; dlp
= dlp
->next
)
403 if (dlp
->dup
== blkno
)
405 if (dlp
== muldup
&& dlp
->dup
!= blkno
)
409 * count the number of blocks found in id_entryno