pass1.c revision 1.51 1 /* $NetBSD: pass1.c,v 1.51 2013/01/22 09:39:11 dholland Exp $ */
2
3 /*
4 * Copyright (c) 1980, 1986, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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.
18 *
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
29 * SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)pass1.c 8.6 (Berkeley) 4/28/95";
36 #else
37 __RCSID("$NetBSD: pass1.c,v 1.51 2013/01/22 09:39:11 dholland Exp $");
38 #endif
39 #endif /* not lint */
40
41 #include <sys/param.h>
42 #include <sys/stat.h>
43 #include <sys/time.h>
44
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>
50
51 #include <err.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55
56 #include "fsck.h"
57 #include "extern.h"
58 #include "fsutil.h"
59 #include "exitvalues.h"
60
61 static daddr_t badblk;
62 static daddr_t dupblk;
63 static void checkinode(ino_t, struct inodesc *);
64 static ino_t lastino;
65
66 void
67 pass1(void)
68 {
69 ino_t inumber, inosused, ninosused, ii;
70 size_t inospace;
71 int c;
72 daddr_t i, cgd;
73 struct inodesc idesc;
74 struct cg *cgp = cgrp;
75 struct inostat *info;
76 uint8_t *cp;
77
78 /*
79 * Set file system reserved blocks in used block map.
80 */
81 for (c = 0; c < sblock->fs_ncg; c++) {
82 cgd = cgdmin(sblock, c);
83 if (c == 0)
84 i = cgbase(sblock, c);
85 else
86 i = cgsblock(sblock, c);
87 for (; i < cgd; i++)
88 setbmap(i);
89 }
90 i = sblock->fs_csaddr;
91 cgd = i + howmany(sblock->fs_cssize, sblock->fs_fsize);
92 for (; i < cgd; i++)
93 setbmap(i);
94 /*
95 * Find all allocated blocks.
96 */
97 memset(&idesc, 0, sizeof(struct inodesc));
98 idesc.id_func = pass1check;
99 n_files = n_blks = 0;
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);
107 if (is_ufs2)
108 inosused = cgp->cg_initediblk;
109 else
110 inosused = sblock->fs_ipg;
111 if (got_siginfo) {
112 fprintf(stderr,
113 "%s: phase 1: cyl group %d of %d (%d%%)\n",
114 cdevname(), c, sblock->fs_ncg,
115 c * 100 / sblock->fs_ncg);
116 got_siginfo = 0;
117 }
118 #ifdef PROGRESS
119 progress_bar(cdevname(), preen ? NULL : "phase 1",
120 c, sblock->fs_ncg);
121 #endif /* PROGRESS */
122 /*
123 * If we are using soft updates, then we can trust the
124 * cylinder group inode allocation maps to tell us which
125 * inodes are allocated. We will scan the used inode map
126 * to find the inodes that are really in use, and then
127 * read only those inodes in from disk.
128 */
129 if (preen && usedsoftdep) {
130 if (!cg_chkmagic(cgp, 0))
131 pfatal("CG %d: BAD MAGIC NUMBER\n", c);
132 cp = &cg_inosused(cgp, 0)[(inosused - 1) / CHAR_BIT];
133 for ( ; inosused > 0; inosused -= CHAR_BIT, cp--) {
134 if (*cp == 0)
135 continue;
136 for (i = 1 << (CHAR_BIT - 1); i > 0; i >>= 1) {
137 if (*cp & i)
138 break;
139 inosused--;
140 }
141 break;
142 }
143 #ifdef notdef
144 if (inosused < 0)
145 inosused = 0;
146 #endif
147 }
148 /*
149 * Allocate inoinfo structures for the allocated inodes.
150 */
151 inostathead[c].il_numalloced = inosused;
152 if (inosused == 0) {
153 inostathead[c].il_stat = 0;
154 continue;
155 }
156 inospace = inosused * sizeof(*info);
157 if (inospace / sizeof(*info) != inosused) {
158 pfatal("too many inodes %llu\n", (unsigned long long)
159 inosused);
160 exit(FSCK_EXIT_CHECK_FAILED);
161 }
162 info = malloc(inospace);
163 if (info == NULL) {
164 pfatal("cannot alloc %zu bytes for inoinfo\n",
165 inospace);
166 exit(FSCK_EXIT_CHECK_FAILED);
167 }
168 (void)memset(info, 0, inospace);
169 inostathead[c].il_stat = info;
170 /*
171 * Scan the allocated inodes.
172 */
173 for (ii = 0; ii < inosused; ii++, inumber++) {
174 if (inumber < UFS_ROOTINO) {
175 (void)getnextinode(inumber);
176 continue;
177 }
178 checkinode(inumber, &idesc);
179 }
180 lastino += 1;
181 if (inosused < (ino_t)sblock->fs_ipg || inumber == lastino)
182 continue;
183 /*
184 * If we were not able to determine in advance which inodes
185 * were in use, then reduce the size of the inoinfo structure
186 * to the size necessary to describe the inodes that we
187 * really found.
188 */
189 if (lastino < (c * (ino_t)sblock->fs_ipg))
190 ninosused = 0;
191 else
192 ninosused = lastino - (c * sblock->fs_ipg);
193 inostathead[c].il_numalloced = ninosused;
194 if (ninosused == 0) {
195 free(inostathead[c].il_stat);
196 inostathead[c].il_stat = 0;
197 continue;
198 }
199 if (ninosused != inosused) {
200 struct inostat *ninfo;
201 size_t ninospace = ninosused * sizeof(*ninfo);
202 if (ninospace / sizeof(*info) != ninosused) {
203 pfatal("too many inodes %llu\n",
204 (unsigned long long)ninosused);
205 exit(FSCK_EXIT_CHECK_FAILED);
206 }
207 ninfo = realloc(info, ninospace);
208 if (ninfo == NULL) {
209 pfatal("cannot realloc %zu bytes to %zu "
210 "for inoinfo\n", inospace, ninospace);
211 exit(FSCK_EXIT_CHECK_FAILED);
212 }
213 if (ninosused > inosused)
214 (void)memset(&ninfo[inosused], 0, ninospace - inospace);
215 inostathead[c].il_stat = ninfo;
216 }
217 }
218 #ifdef PROGRESS
219 if (!preen)
220 progress_done();
221 #endif /* PROGRESS */
222 freeinodebuf();
223 do_blkswap = 0; /* has been done */
224 }
225
226 static void
227 checkinode(ino_t inumber, struct inodesc *idesc)
228 {
229 union dinode *dp;
230 struct zlncnt *zlnp;
231 daddr_t ndb;
232 int j;
233 mode_t mode;
234 u_int64_t size, kernmaxfilesize;
235 int64_t blocks;
236 char symbuf[MAXBSIZE];
237 struct inostat *info;
238 uid_t uid;
239 gid_t gid;
240
241 dp = getnextinode(inumber);
242 info = inoinfo(inumber);
243 mode = iswap16(DIP(dp, mode)) & IFMT;
244 size = iswap64(DIP(dp, size));
245 uid = iswap32(DIP(dp, uid));
246 gid = iswap32(DIP(dp, gid));
247 if (mode == 0) {
248 if ((is_ufs2 &&
249 (memcmp(dp->dp2.di_db, ufs2_zino.di_db,
250 UFS_NDADDR * sizeof(int64_t)) ||
251 memcmp(dp->dp2.di_ib, ufs2_zino.di_ib,
252 UFS_NIADDR * sizeof(int64_t))))
253 ||
254 (!is_ufs2 &&
255 (memcmp(dp->dp1.di_db, ufs1_zino.di_db,
256 UFS_NDADDR * sizeof(int32_t)) ||
257 memcmp(dp->dp1.di_ib, ufs1_zino.di_ib,
258 UFS_NIADDR * sizeof(int32_t)))) ||
259 mode || size) {
260 pfatal("PARTIALLY ALLOCATED INODE I=%llu",
261 (unsigned long long)inumber);
262 if (reply("CLEAR") == 1) {
263 dp = ginode(inumber);
264 clearinode(dp);
265 inodirty();
266 } else
267 markclean = 0;
268 }
269 info->ino_state = USTATE;
270 return;
271 }
272 lastino = inumber;
273 /* This should match the file size limit in ffs_mountfs(). */
274 if (is_ufs2)
275 kernmaxfilesize = sblock->fs_maxfilesize;
276 else
277 kernmaxfilesize = (u_int64_t)0x80000000 * sblock->fs_bsize - 1;
278 if (size > kernmaxfilesize || size + sblock->fs_bsize - 1 < size ||
279 (mode == IFDIR && size > MAXDIRSIZE)) {
280 if (debug)
281 printf("bad size %llu:",(unsigned long long)size);
282 goto unknown;
283 }
284 if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) {
285 dp = ginode(inumber);
286 DIP_SET(dp, size, iswap64(sblock->fs_fsize));
287 size = sblock->fs_fsize;
288 DIP_SET(dp, mode, iswap16(IFREG|0600));
289 inodirty();
290 }
291 ndb = howmany(size, sblock->fs_bsize);
292 if (ndb < 0) {
293 if (debug)
294 printf("bad size %llu ndb %lld:",
295 (unsigned long long)size, (long long)ndb);
296 goto unknown;
297 }
298 if (mode == IFBLK || mode == IFCHR)
299 ndb++;
300 if (mode == IFLNK) {
301 /*
302 * Note that the old fastlink format always had di_blocks set
303 * to 0. Other than that we no longer use the `spare' field
304 * (which is now the extended uid) for sanity checking, the
305 * new format is the same as the old. We simply ignore the
306 * conversion altogether. - mycroft, 19MAY1994
307 */
308 if (!is_ufs2 && doinglevel2 &&
309 size > 0 && size < UFS1_MAXSYMLINKLEN &&
310 DIP(dp, blocks) != 0) {
311 if (bread(fsreadfd, symbuf,
312 fsbtodb(sblock, iswap32(DIP(dp, db[0]))),
313 (long)secsize) != 0)
314 errexit("cannot read symlink");
315 if (debug) {
316 symbuf[size] = 0;
317 printf("convert symlink %llu(%s) "
318 "of size %lld\n",
319 (unsigned long long)inumber, symbuf,
320 (unsigned long long)size);
321 }
322 dp = ginode(inumber);
323 memmove(dp->dp1.di_db, symbuf, (long)size);
324 DIP_SET(dp, blocks, 0);
325 inodirty();
326 }
327 /*
328 * Fake ndb value so direct/indirect block checks below
329 * will detect any garbage after symlink string.
330 */
331 if ((sblock->fs_maxsymlinklen < 0) ||
332 (size < (uint64_t)sblock->fs_maxsymlinklen) ||
333 (isappleufs && (size < APPLEUFS_MAXSYMLINKLEN)) ||
334 (sblock->fs_maxsymlinklen == 0 && DIP(dp, blocks) == 0)) {
335 if (is_ufs2)
336 ndb = howmany(size, sizeof(int64_t));
337 else
338 ndb = howmany(size, sizeof(int32_t));
339 if (ndb > UFS_NDADDR) {
340 j = ndb - UFS_NDADDR;
341 for (ndb = 1; j > 1; j--)
342 ndb *= NINDIR(sblock);
343 ndb += UFS_NDADDR;
344 }
345 }
346 }
347 if (ndb < UFS_NDADDR) {
348 for (j = ndb; j < UFS_NDADDR; j++)
349 if (DIP(dp, db[j]) != 0) {
350 if (debug) {
351 if (!is_ufs2)
352 printf("bad direct addr ix %d: %d [ndb %lld]\n",
353 j, iswap32(dp->dp1.di_db[j]),
354 (long long)ndb);
355 else
356 printf("bad direct addr ix %d: %lld [ndb %lld]\n",
357 j, (long long)iswap64(dp->dp2.di_db[j]),
358 (long long)ndb);
359 }
360 goto unknown;
361 }
362 }
363
364 for (j = 0, ndb -= UFS_NDADDR; ndb > 0; j++)
365 ndb /= NINDIR(sblock);
366
367 for (; j < UFS_NIADDR; j++)
368 if (DIP(dp, ib[j]) != 0) {
369 if (debug) {
370 if (!is_ufs2)
371 printf("bad indirect addr: %d\n",
372 iswap32(dp->dp1.di_ib[j]));
373 else
374 printf("bad indirect addr: %lld\n",
375 (long long)iswap64(dp->dp2.di_ib[j]));
376 }
377 goto unknown;
378 }
379 if (ftypeok(dp) == 0)
380 goto unknown;
381 n_files++;
382 info->ino_linkcnt = iswap16(DIP(dp, nlink));
383 if (info->ino_linkcnt <= 0) {
384 zlnp = (struct zlncnt *)malloc(sizeof *zlnp);
385 if (zlnp == NULL) {
386 markclean = 0;
387 pfatal("LINK COUNT TABLE OVERFLOW");
388 if (reply("CONTINUE") == 0) {
389 ckfini(1);
390 exit(FSCK_EXIT_CHECK_FAILED);
391 }
392 } else {
393 zlnp->zlncnt = inumber;
394 zlnp->next = zlnhead;
395 zlnhead = zlnp;
396 }
397 }
398 if (mode == IFDIR) {
399 if (size == 0)
400 info->ino_state = DCLEAR;
401 else
402 info->ino_state = DSTATE;
403 cacheino(dp, inumber);
404 countdirs++;
405 } else
406 info->ino_state = FSTATE;
407 info->ino_type = IFTODT(mode);
408 if (!is_ufs2 && doinglevel2 &&
409 (iswap16(dp->dp1.di_ouid) != (u_short)-1 ||
410 iswap16(dp->dp1.di_ogid) != (u_short)-1)) {
411 dp = ginode(inumber);
412 dp->dp1.di_uid = iswap32(iswap16(dp->dp1.di_ouid));
413 dp->dp1.di_ouid = iswap16(-1);
414 dp->dp1.di_gid = iswap32(iswap16(dp->dp1.di_ogid));
415 dp->dp1.di_ogid = iswap16(-1);
416 inodirty();
417 }
418 badblk = dupblk = 0;
419 idesc->id_number = inumber;
420 idesc->id_uid = iswap32(DIP(dp, uid));
421 idesc->id_gid = iswap32(DIP(dp, gid));
422 if (iswap32(DIP(dp, flags)) & SF_SNAPSHOT)
423 idesc->id_type = SNAP;
424 else
425 idesc->id_type = ADDR;
426 (void)ckinode(dp, idesc);
427 #ifdef notyet
428 if (is_ufs2 && iswap32(dp->dp2.di_extsize) > 0) {
429 int ret, offset;
430 idesc->id_type = ADDR;
431 ndb = howmany(iswap32(dp->dp2.di_extsize), sblock->fs_bsize);
432 for (j = 0; j < UFS_NXADDR; j++) {
433 if (--ndb == 0 &&
434 (offset = blkoff(sblock, iswap32(dp->dp2.di_extsize))) != 0)
435 idesc->id_numfrags = numfrags(sblock,
436 fragroundup(sblock, offset));
437 else
438 idesc->id_numfrags = sblock->fs_frag;
439 if (dp->dp2.di_extb[j] == 0)
440 continue;
441 idesc->id_blkno = iswap64(dp->dp2.di_extb[j]);
442 ret = (*idesc->id_func)(idesc);
443 if (ret & STOP)
444 break;
445 }
446 }
447 #endif
448 idesc->id_entryno *= btodb(sblock->fs_fsize);
449 if (is_ufs2)
450 blocks = iswap64(dp->dp2.di_blocks);
451 else
452 blocks = iswap32(dp->dp1.di_blocks);
453 if (blocks != idesc->id_entryno) {
454 pwarn("INCORRECT BLOCK COUNT I=%llu (%lld should be %lld)",
455 (unsigned long long)inumber, (long long)blocks,
456 (long long)idesc->id_entryno);
457 if (preen)
458 printf(" (CORRECTED)\n");
459 else if (reply("CORRECT") == 0) {
460 markclean = 0;
461 return;
462 }
463 dp = ginode(inumber);
464 if (is_ufs2)
465 dp->dp2.di_blocks = iswap64(idesc->id_entryno);
466 else
467 dp->dp1.di_blocks = iswap32((int32_t)idesc->id_entryno);
468 inodirty();
469 }
470 if (idesc->id_type != SNAP)
471 update_uquot(inumber, idesc->id_uid, idesc->id_gid,
472 idesc->id_entryno, 1);
473 return;
474 unknown:
475 pfatal("UNKNOWN FILE TYPE I=%llu", (unsigned long long)inumber);
476 info->ino_state = FCLEAR;
477 if (reply("CLEAR") == 1) {
478 info->ino_state = USTATE;
479 dp = ginode(inumber);
480 clearinode(dp);
481 inodirty();
482 } else
483 markclean = 0;
484 }
485
486 int
487 pass1check(struct inodesc *idesc)
488 {
489 int res = KEEPON;
490 int anyout, nfrags;
491 daddr_t blkno = idesc->id_blkno;
492 struct dups *dlp;
493 struct dups *new;
494
495 if (idesc->id_type == SNAP) {
496 if (blkno == BLK_NOCOPY || blkno == BLK_SNAP)
497 return (KEEPON);
498 }
499 if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) {
500 blkerror(idesc->id_number, "BAD", blkno);
501 if (badblk++ >= MAXBAD) {
502 pwarn("EXCESSIVE BAD BLKS I=%llu",
503 (unsigned long long)idesc->id_number);
504 if (preen)
505 printf(" (SKIPPING)\n");
506 else if (reply("CONTINUE") == 0) {
507 markclean = 0;
508 ckfini(1);
509 exit(FSCK_EXIT_CHECK_FAILED);
510 }
511 return (STOP);
512 }
513 }
514 for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
515 if (anyout && chkrange(blkno, 1)) {
516 res = SKIP;
517 } else if (!testbmap(blkno)) {
518 n_blks++;
519 setbmap(blkno);
520 } else {
521 blkerror(idesc->id_number, "DUP", blkno);
522 if (dupblk++ >= MAXDUP) {
523 pwarn("EXCESSIVE DUP BLKS I=%llu",
524 (unsigned long long)idesc->id_number);
525 if (preen)
526 printf(" (SKIPPING)\n");
527 else if (reply("CONTINUE") == 0) {
528 markclean = 0;
529 ckfini(1);
530 exit(FSCK_EXIT_CHECK_FAILED);
531 }
532 return (STOP);
533 }
534 new = (struct dups *)malloc(sizeof(struct dups));
535 if (new == NULL) {
536 markclean = 0;
537 pfatal("DUP TABLE OVERFLOW.");
538 if (reply("CONTINUE") == 0) {
539 markclean = 0;
540 ckfini(1);
541 exit(FSCK_EXIT_CHECK_FAILED);
542 }
543 return (STOP);
544 }
545 new->dup = blkno;
546 if (muldup == 0) {
547 duplist = muldup = new;
548 new->next = 0;
549 } else {
550 new->next = muldup->next;
551 muldup->next = new;
552 }
553 for (dlp = duplist; dlp != muldup; dlp = dlp->next)
554 if (dlp->dup == blkno)
555 break;
556 if (dlp == muldup && dlp->dup != blkno)
557 muldup = new;
558 }
559 /*
560 * count the number of blocks found in id_entryno
561 */
562 idesc->id_entryno++;
563 }
564 return (res);
565 }
566