1 /* $NetBSD: pass1.c,v 1.28 2006/11/09 19:36:36 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/param.h>
34 #include <sys/mount.h>
37 #include <ufs/ufs/inode.h>
38 #include <ufs/ufs/dir.h>
40 #include <ufs/lfs/lfs.h>
59 extern ufs_daddr_t
*din_table
;
62 static ufs_daddr_t dupblk
;
63 static int i_d_cmp(const void *, const void *);
71 i_d_cmp(const void *va
, const void *vb
)
73 const struct ino_daddr
*a
, *b
;
75 a
= *((const struct ino_daddr
*const *) va
);
76 b
= *((const struct ino_daddr
*const *) vb
);
78 if (a
->daddr
== b
->daddr
) {
79 return (a
->ino
- b
->ino
);
81 if (a
->daddr
> b
->daddr
) {
93 struct ufs1_dinode
*tinode
;
96 struct ino_daddr
**dins
;
99 * Find all allocated blocks, initialize numdirs.
101 memset(&idesc
, 0, sizeof(struct inodesc
));
102 idesc
.id_type
= ADDR
;
103 idesc
.id_func
= pass1check
;
106 n_files
= n_blks
= 0;
109 printf("creating sorted inode address table...\n");
111 dins
= ecalloc(maxino
, sizeof(*dins
));
112 for (i
= 0; i
< maxino
; i
++) {
113 dins
[i
] = emalloc(sizeof(**dins
));
115 if (i
== fs
->lfs_ifile
)
116 dins
[i
]->daddr
= fs
->lfs_idaddr
;
118 LFS_IENTRY(ifp
, fs
, i
, bp
);
119 dins
[i
]->daddr
= ifp
->if_daddr
;
123 qsort(dins
, maxino
, sizeof(*dins
), i_d_cmp
);
125 /* find a value for numdirs, fill in din_table */
127 printf("counting dirs...\n");
129 for (i
= 0; i
< maxino
; i
++) {
130 inumber
= dins
[i
]->ino
;
131 if (inumber
== 0 || dins
[i
]->daddr
== 0)
133 tinode
= ginode(inumber
);
134 if (tinode
&& (tinode
->di_mode
& IFMT
) == IFDIR
)
140 listmax
= numdirs
+ 10;
141 inpsort
= ecalloc(listmax
, sizeof(struct inoinfo
*));
142 inphead
= ecalloc(numdirs
, sizeof(struct inoinfo
*));
144 printf("counting blocks...\n");
146 for (i
= 0; i
< maxino
; i
++) {
147 inumber
= dins
[i
]->ino
;
148 if (inumber
== 0 || dins
[i
]->daddr
== 0) {
149 statemap
[inumber
] = USTATE
;
152 if (dins
[i
]->daddr
!= LFS_UNUSED_DADDR
) {
153 checkinode(inumber
, &idesc
);
155 statemap
[inumber
] = USTATE
;
163 checkinode(ino_t inumber
, struct inodesc
* idesc
)
165 struct ufs1_dinode
*dp
;
173 vp
= vget(fs
, inumber
);
180 statemap
[inumber
] = USTATE
;
183 mode
= dp
->di_mode
& IFMT
;
185 /* XXX - LFS doesn't have this particular problem (?) */
187 if (memcmp(dp
->di_db
, zino
.di_db
, NDADDR
* sizeof(ufs_daddr_t
)) ||
188 memcmp(dp
->di_ib
, zino
.di_ib
, NIADDR
* sizeof(ufs_daddr_t
)) ||
189 dp
->di_mode
|| dp
->di_size
) {
190 pwarn("mode=o%o, ifmt=o%o\n", dp
->di_mode
, mode
);
191 pfatal("PARTIALLY ALLOCATED INODE I=%llu",
192 (unsigned long long)inumber
);
193 if (reply("CLEAR") == 1) {
194 vp
= vget(fs
, inumber
);
199 statemap
[inumber
] = USTATE
;
203 if (/* dp->di_size < 0 || */
204 dp
->di_size
+ fs
->lfs_bsize
- 1 < dp
->di_size
) {
206 printf("bad size %llu:",
207 (unsigned long long) dp
->di_size
);
210 if (!preen
&& mode
== IFMT
&& reply("HOLD BAD BLOCK") == 1) {
211 vp
= vget(fs
, inumber
);
213 dp
->di_size
= fs
->lfs_fsize
;
214 dp
->di_mode
= IFREG
| 0600;
217 ndb
= howmany(dp
->di_size
, fs
->lfs_bsize
);
220 printf("bad size %llu ndb %d:",
221 (unsigned long long) dp
->di_size
, ndb
);
224 if (mode
== IFBLK
|| mode
== IFCHR
)
228 * Fake ndb value so direct/indirect block checks below
229 * will detect any garbage after symlink string.
231 if (dp
->di_size
< fs
->lfs_maxsymlinklen
||
232 (fs
->lfs_maxsymlinklen
== 0 && dp
->di_blocks
== 0)) {
233 ndb
= howmany(dp
->di_size
, sizeof(ufs_daddr_t
));
236 for (ndb
= 1; j
> 1; j
--)
242 for (j
= ndb
; j
< NDADDR
; j
++)
243 if (dp
->di_db
[j
] != 0) {
245 printf("bad direct addr for size %lld lbn %d: 0x%x\n",
246 (long long)dp
->di_size
, j
, (unsigned)dp
->di_db
[j
]);
249 for (j
= 0, ndb
-= NDADDR
; ndb
> 0; j
++)
251 for (; j
< NIADDR
; j
++)
252 if (dp
->di_ib
[j
] != 0) {
254 printf("bad indirect addr for size %lld # %d: 0x%x\n",
255 (long long)dp
->di_size
, j
, (unsigned)dp
->di_ib
[j
]);
258 if (ftypeok(dp
) == 0)
261 lncntp
[inumber
] = dp
->di_nlink
;
262 if (dp
->di_nlink
<= 0) {
263 zlnp
= emalloc(sizeof *zlnp
);
264 zlnp
->zlncnt
= inumber
;
265 zlnp
->next
= zlnhead
;
269 if (dp
->di_size
== 0)
270 statemap
[inumber
] = DCLEAR
;
272 statemap
[inumber
] = DSTATE
;
273 cacheino(dp
, inumber
);
275 statemap
[inumber
] = FSTATE
;
278 * Check for an orphaned file. These happen when the cleaner has
279 * to rewrite blocks from a file whose directory operation (removal)
282 if (dp
->di_nlink
<= 0) {
283 LFS_IENTRY(ifp
, fs
, inumber
, bp
);
284 if (ifp
->if_nextfree
== LFS_ORPHAN_NEXTFREE
) {
285 statemap
[inumber
] = (mode
== IFDIR
? DCLEAR
: FCLEAR
);
286 /* Add this to our list of orphans */
287 zlnp
= emalloc(sizeof *zlnp
);
288 zlnp
->zlncnt
= inumber
;
289 zlnp
->next
= orphead
;
295 typemap
[inumber
] = IFTODT(mode
);
297 idesc
->id_number
= inumber
;
298 (void) ckinode(VTOD(vp
), idesc
);
299 if (dp
->di_blocks
!= idesc
->id_entryno
) {
300 pwarn("INCORRECT BLOCK COUNT I=%llu (%d SHOULD BE %d)",
301 (unsigned long long)inumber
, dp
->di_blocks
,
304 printf(" (CORRECTED)\n");
305 else if (reply("CORRECT") == 0)
307 VTOI(vp
)->i_ffs1_blocks
= idesc
->id_entryno
;
312 pfatal("UNKNOWN FILE TYPE I=%llu", (unsigned long long)inumber
);
313 statemap
[inumber
] = FCLEAR
;
314 if (reply("CLEAR") == 1) {
315 statemap
[inumber
] = USTATE
;
316 vp
= vget(fs
, inumber
);
323 pass1check(struct inodesc
*idesc
)
327 daddr_t blkno
= idesc
->id_blkno
;
331 if ((anyout
= chkrange(blkno
, fragstofsb(fs
, idesc
->id_numfrags
))) != 0) {
332 blkerror(idesc
->id_number
, "BAD", blkno
);
333 if (badblk
++ >= MAXBAD
) {
334 pwarn("EXCESSIVE BAD BLKS I=%llu",
335 (unsigned long long)idesc
->id_number
);
337 printf(" (SKIPPING)\n");
338 else if (reply("CONTINUE") == 0)
339 err(EEXIT
, "%s", "");
342 } else if (!testbmap(blkno
)) {
343 seg_table
[dtosn(fs
, blkno
)].su_nbytes
+= idesc
->id_numfrags
* fs
->lfs_fsize
;
345 for (ndblks
= fragstofsb(fs
, idesc
->id_numfrags
); ndblks
> 0; blkno
++, ndblks
--) {
346 if (anyout
&& chkrange(blkno
, 1)) {
348 } else if (!testbmap(blkno
)) {
350 #ifndef VERBOSE_BLOCKMAP
353 setbmap(blkno
, idesc
->id_number
);
356 blkerror(idesc
->id_number
, "DUP", blkno
);
357 #ifdef VERBOSE_BLOCKMAP
358 pwarn("(lbn %lld: Holder is %lld)\n",
359 (long long)idesc
->id_lblkno
,
360 (long long)testbmap(blkno
));
362 if (dupblk
++ >= MAXDUP
) {
363 pwarn("EXCESSIVE DUP BLKS I=%llu",
364 (unsigned long long)idesc
->id_number
);
366 printf(" (SKIPPING)\n");
367 else if (reply("CONTINUE") == 0)
368 err(EEXIT
, "%s", "");
371 new = emalloc(sizeof(struct dups
));
374 duplist
= muldup
= new;
377 new->next
= muldup
->next
;
380 for (dlp
= duplist
; dlp
!= muldup
; dlp
= dlp
->next
)
381 if (dlp
->dup
== blkno
)
383 if (dlp
== muldup
&& dlp
->dup
!= blkno
)
387 * count the number of blocks found in id_entryno