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. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * @(#)pass1.c 8.6 (Berkeley) 4/28/95
34 * $FreeBSD: src/sbin/fsck/pass1.c,v 1.16.2.5 2002/06/23 22:34:58 iedowse Exp $
35 * $DragonFly: src/sbin/fsck/pass1.c,v 1.9 2006/10/12 04:04:03 dillon Exp $
38 #include <sys/param.h>
40 #include <vfs/ufs/dinode.h>
41 #include <vfs/ufs/dir.h>
42 #include <vfs/ufs/fs.h>
49 static ufs_daddr_t badblk
;
50 static ufs_daddr_t dupblk
;
51 static ufs1_ino_t lastino
; /* last inode in use */
53 static void checkinode(ufs1_ino_t inumber
, struct inodesc
*);
60 int c
, i
, cgd
, inosused
;
65 * Set file system reserved blocks in used block map.
67 for (c
= 0; c
< sblock
.fs_ncg
; c
++) {
68 cgd
= cgdmin(&sblock
, c
);
70 i
= cgbase(&sblock
, c
);
72 i
= cgsblock(&sblock
, c
);
77 cgd
= i
+ howmany(sblock
.fs_cssize
, sblock
.fs_fsize
);
81 * Find all allocated blocks.
83 memset(&idesc
, 0, sizeof(struct inodesc
));
85 idesc
.id_func
= pass1check
;
87 for (c
= 0; c
< sblock
.fs_ncg
; c
++) {
88 inumber
= c
* sblock
.fs_ipg
;
90 inosused
= sblock
.fs_ipg
;
92 printf("%s: phase 1: cyl group %d of %d (%d%%)\n",
93 cdevname
, c
, sblock
.fs_ncg
,
94 c
* 100 / sblock
.fs_ncg
);
98 * If we are using soft updates, then we can trust the
99 * cylinder group inode allocation maps to tell us which
100 * inodes are allocated. We will scan the used inode map
101 * to find the inodes that are really in use, and then
102 * read only those inodes in from disk.
104 if (preen
&& usedsoftdep
) {
105 getblk(&cgblk
, cgtod(&sblock
, c
), sblock
.fs_cgsize
);
106 if (!cg_chkmagic(&cgrp
))
107 pfatal("CG %d: BAD MAGIC NUMBER\n", c
);
108 cp
= &cg_inosused(&cgrp
)[(sblock
.fs_ipg
- 1) / NBBY
];
109 for ( ; inosused
> 0; inosused
-= NBBY
, cp
--) {
112 for (i
= 1 << (NBBY
- 1); i
> 0; i
>>= 1) {
123 * Allocate inoinfo structures for the allocated inodes.
125 inostathead
[c
].il_numalloced
= inosused
;
127 inostathead
[c
].il_stat
= 0;
130 info
= calloc((unsigned)inosused
, sizeof(struct inostat
));
132 pfatal("cannot alloc %u bytes for inoinfo\n",
133 (unsigned)(sizeof(struct inostat
) * inosused
));
134 inostathead
[c
].il_stat
= info
;
136 * Scan the allocated inodes.
138 for (i
= 0; i
< inosused
; i
++, inumber
++) {
139 if (inumber
< ROOTINO
) {
140 getnextinode(inumber
);
143 checkinode(inumber
, &idesc
);
146 if (inosused
< sblock
.fs_ipg
|| inumber
== lastino
)
149 * If we were not able to determine in advance which inodes
150 * were in use, then reduce the size of the inoinfo structure
151 * to the size necessary to describe the inodes that we
154 inosused
= lastino
- (c
* sblock
.fs_ipg
);
157 inostathead
[c
].il_numalloced
= inosused
;
159 free(inostathead
[c
].il_stat
);
160 inostathead
[c
].il_stat
= 0;
163 info
= calloc((unsigned)inosused
, sizeof(struct inostat
));
165 pfatal("cannot alloc %u bytes for inoinfo\n",
166 (unsigned)(sizeof(struct inostat
) * inosused
));
167 memmove(info
, inostathead
[c
].il_stat
, inosused
* sizeof(*info
));
168 free(inostathead
[c
].il_stat
);
169 inostathead
[c
].il_stat
= info
;
175 checkinode(ufs1_ino_t inumber
, struct inodesc
*idesc
)
177 struct ufs1_dinode
*dp
;
179 u_int64_t kernmaxfilesize
;
184 dp
= getnextinode(inumber
);
185 mode
= dp
->di_mode
& IFMT
;
187 if (memcmp(dp
->di_db
, zino
.di_db
,
188 NDADDR
* sizeof(ufs_daddr_t
)) ||
189 memcmp(dp
->di_ib
, zino
.di_ib
,
190 NIADDR
* sizeof(ufs_daddr_t
)) ||
191 dp
->di_mode
|| dp
->di_size
) {
192 pfatal("PARTIALLY ALLOCATED INODE I=%lu", inumber
);
193 if (reply("CLEAR") == 1) {
194 dp
= ginode(inumber
);
199 inoinfo(inumber
)->ino_state
= USTATE
;
203 /* This should match the file size limit in ffs_mountfs(). */
204 kernmaxfilesize
= (u_int64_t
)0x40000000 * sblock
.fs_bsize
- 1;
205 if (kernmaxfilesize
> (u_int64_t
)0x80000000u
* PAGE_SIZE
- 1)
206 kernmaxfilesize
= (u_int64_t
)0x80000000u
* PAGE_SIZE
- 1;
207 if (dp
->di_size
> kernmaxfilesize
||
208 dp
->di_size
> sblock
.fs_maxfilesize
||
209 (mode
== IFDIR
&& dp
->di_size
> MAXDIRSIZE
)) {
211 printf("bad size %qu:", dp
->di_size
);
214 if (!preen
&& mode
== IFMT
&& reply("HOLD BAD BLOCK") == 1) {
215 dp
= ginode(inumber
);
216 dp
->di_size
= sblock
.fs_fsize
;
217 dp
->di_mode
= IFREG
|0600;
220 if ((mode
== IFBLK
|| mode
== IFCHR
|| mode
== IFIFO
||
221 mode
== IFSOCK
) && dp
->di_size
!= 0) {
223 printf("bad special-file size %qu:", dp
->di_size
);
226 ndb
= howmany(dp
->di_size
, sblock
.fs_bsize
);
229 printf("bad size %qu ndb %d:",
233 if (mode
== IFBLK
|| mode
== IFCHR
)
237 dp
->di_size
> 0 && dp
->di_size
< MAXSYMLINKLEN
&&
238 dp
->di_blocks
!= 0) {
239 symbuf
= alloca(secsize
);
240 if (bread(fsreadfd
, symbuf
,
241 fsbtodb(&sblock
, dp
->di_db
[0]),
243 errx(EEXIT
, "cannot read symlink");
245 symbuf
[dp
->di_size
] = 0;
246 printf("convert symlink %lu(%s) of size %ld\n",
247 (u_long
)inumber
, symbuf
, (long)dp
->di_size
);
249 dp
= ginode(inumber
);
250 memmove(dp
->di_shortlink
, symbuf
, (long)dp
->di_size
);
255 * Fake ndb value so direct/indirect block checks below
256 * will detect any garbage after symlink string.
258 if (dp
->di_size
< sblock
.fs_maxsymlinklen
) {
259 ndb
= howmany(dp
->di_size
, sizeof(ufs_daddr_t
));
262 for (ndb
= 1; j
> 1; j
--)
263 ndb
*= NINDIR(&sblock
);
268 for (j
= ndb
; j
< NDADDR
; j
++)
269 if (dp
->di_db
[j
] != 0) {
271 printf("bad direct addr: %ld\n",
275 for (j
= 0, ndb
-= NDADDR
; ndb
> 0; j
++)
276 ndb
/= NINDIR(&sblock
);
277 for (; j
< NIADDR
; j
++)
278 if (dp
->di_ib
[j
] != 0) {
280 printf("bad indirect addr: %ld\n",
284 if (ftypeok(dp
) == 0)
287 inoinfo(inumber
)->ino_linkcnt
= dp
->di_nlink
;
288 if (dp
->di_nlink
<= 0) {
289 zlnp
= (struct zlncnt
*)malloc(sizeof *zlnp
);
291 pfatal("LINK COUNT TABLE OVERFLOW");
292 if (reply("CONTINUE") == 0) {
297 zlnp
->zlncnt
= inumber
;
298 zlnp
->next
= zlnhead
;
303 if (dp
->di_size
== 0)
304 inoinfo(inumber
)->ino_state
= DCLEAR
;
306 inoinfo(inumber
)->ino_state
= DSTATE
;
307 cacheino(dp
, inumber
);
310 inoinfo(inumber
)->ino_state
= FSTATE
;
311 inoinfo(inumber
)->ino_type
= IFTODT(mode
);
313 (dp
->di_ouid
!= (u_short
)-1 || dp
->di_ogid
!= (u_short
)-1)) {
314 dp
= ginode(inumber
);
315 dp
->di_uid
= dp
->di_ouid
;
317 dp
->di_gid
= dp
->di_ogid
;
322 idesc
->id_number
= inumber
;
324 idesc
->id_entryno
*= btodb(sblock
.fs_fsize
);
325 if (dp
->di_blocks
!= idesc
->id_entryno
) {
326 pwarn("INCORRECT BLOCK COUNT I=%lu (%ld should be %ld)",
327 inumber
, dp
->di_blocks
, idesc
->id_entryno
);
329 printf(" (CORRECTED)\n");
330 else if (reply("CORRECT") == 0)
332 dp
= ginode(inumber
);
333 dp
->di_blocks
= idesc
->id_entryno
;
338 pfatal("UNKNOWN FILE TYPE I=%lu", inumber
);
339 inoinfo(inumber
)->ino_state
= FCLEAR
;
340 if (reply("CLEAR") == 1) {
341 inoinfo(inumber
)->ino_state
= USTATE
;
342 dp
= ginode(inumber
);
349 pass1check(struct inodesc
*idesc
)
353 ufs_daddr_t blkno
= idesc
->id_blkno
;
357 if ((anyout
= chkrange(blkno
, idesc
->id_numfrags
)) != 0) {
358 blkerror(idesc
->id_number
, "BAD", blkno
);
359 if (badblk
++ >= MAXBAD
) {
360 pwarn("EXCESSIVE BAD BLKS I=%lu",
363 printf(" (SKIPPING)\n");
364 else if (reply("CONTINUE") == 0) {
371 for (nfrags
= idesc
->id_numfrags
; nfrags
> 0; blkno
++, nfrags
--) {
372 if (anyout
&& chkrange(blkno
, 1)) {
374 } else if (!testbmap(blkno
)) {
378 blkerror(idesc
->id_number
, "DUP", blkno
);
379 if (dupblk
++ >= MAXDUP
) {
380 pwarn("EXCESSIVE DUP BLKS I=%lu",
383 printf(" (SKIPPING)\n");
384 else if (reply("CONTINUE") == 0) {
390 new = (struct dups
*)malloc(sizeof(struct dups
));
392 pfatal("DUP TABLE OVERFLOW.");
393 if (reply("CONTINUE") == 0) {
401 duplist
= muldup
= new;
404 new->next
= muldup
->next
;
407 for (dlp
= duplist
; dlp
!= muldup
; dlp
= dlp
->next
)
408 if (dlp
->dup
== blkno
)
410 if (dlp
== muldup
&& dlp
->dup
!= blkno
)
414 * count the number of blocks found in id_entryno