xref: /csrg-svn/sbin/fsck/pass1.c (revision 53822)
122048Sdist /*
239976Smckusick  * Copyright (c) 1980, 1986 The Regents of the University of California.
339976Smckusick  * All rights reserved.
439976Smckusick  *
542702Sbostic  * %sccs.include.redist.c%
622048Sdist  */
722048Sdist 
816262Smckusick #ifndef lint
9*53822Smckusick static char sccsid[] = "@(#)pass1.c	5.18 (Berkeley) 06/02/92";
1039976Smckusick #endif /* not lint */
1116262Smckusick 
1216262Smckusick #include <sys/param.h>
13*53822Smckusick #include <sys/time.h>
1451532Sbostic #include <ufs/ufs/dinode.h>
1551532Sbostic #include <ufs/ffs/fs.h>
1644934Smckusick #include <stdlib.h>
1744934Smckusick #include <string.h>
1816262Smckusick #include "fsck.h"
1916262Smckusick 
2017937Smckusick static daddr_t badblk;
2117937Smckusick static daddr_t dupblk;
2217937Smckusick int pass1check();
2340021Smckusick struct dinode *getnextinode();
2416262Smckusick 
2516262Smckusick pass1()
2616262Smckusick {
2717937Smckusick 	register int c, i, j;
2839973Smckusick 	register struct dinode *dp;
2921759Smckusick 	struct zlncnt *zlnp;
3039973Smckusick 	int ndb, cgd;
3116262Smckusick 	struct inodesc idesc;
3216262Smckusick 	ino_t inumber;
3316262Smckusick 
3417931Smckusick 	/*
3517931Smckusick 	 * Set file system reserved blocks in used block map.
3617931Smckusick 	 */
3717931Smckusick 	for (c = 0; c < sblock.fs_ncg; c++) {
3817931Smckusick 		cgd = cgdmin(&sblock, c);
3917931Smckusick 		if (c == 0) {
4017931Smckusick 			i = cgbase(&sblock, c);
4117931Smckusick 			cgd += howmany(sblock.fs_cssize, sblock.fs_fsize);
4217931Smckusick 		} else
4317931Smckusick 			i = cgsblock(&sblock, c);
4417931Smckusick 		for (; i < cgd; i++)
4517931Smckusick 			setbmap(i);
4617931Smckusick 	}
4717931Smckusick 	/*
4817931Smckusick 	 * Find all allocated blocks.
4917931Smckusick 	 */
5016262Smckusick 	bzero((char *)&idesc, sizeof(struct inodesc));
5116262Smckusick 	idesc.id_type = ADDR;
5216262Smckusick 	idesc.id_func = pass1check;
5316262Smckusick 	inumber = 0;
5417937Smckusick 	n_files = n_blks = 0;
5540021Smckusick 	resetinodebuf();
5616262Smckusick 	for (c = 0; c < sblock.fs_ncg; c++) {
5716262Smckusick 		for (i = 0; i < sblock.fs_ipg; i++, inumber++) {
5817937Smckusick 			if (inumber < ROOTINO)
5916262Smckusick 				continue;
6040021Smckusick 			dp = getnextinode(inumber);
6139973Smckusick 			if ((dp->di_mode & IFMT) == 0) {
6217937Smckusick 				if (bcmp((char *)dp->di_db, (char *)zino.di_db,
6317937Smckusick 					NDADDR * sizeof(daddr_t)) ||
6417937Smckusick 				    bcmp((char *)dp->di_ib, (char *)zino.di_ib,
6517937Smckusick 					NIADDR * sizeof(daddr_t)) ||
6617937Smckusick 				    dp->di_mode || dp->di_size) {
6744934Smckusick 					pfatal("PARTIALLY ALLOCATED INODE I=%lu",
6816262Smckusick 						inumber);
6916262Smckusick 					if (reply("CLEAR") == 1) {
7040485Smckusick 						dp = ginode(inumber);
7139973Smckusick 						clearinode(dp);
7216262Smckusick 						inodirty();
7316262Smckusick 					}
7416262Smckusick 				}
7517937Smckusick 				statemap[inumber] = USTATE;
7617937Smckusick 				continue;
7716262Smckusick 			}
7817937Smckusick 			lastino = inumber;
7944934Smckusick 			if (/* dp->di_size < 0 || */
8044934Smckusick 			    dp->di_size + sblock.fs_bsize - 1 < dp->di_size) {
8117937Smckusick 				if (debug)
82*53822Smckusick 					printf("bad size %qu:", dp->di_size);
8317937Smckusick 				goto unknown;
8417937Smckusick 			}
8528084Smckusick 			if (!preen && (dp->di_mode & IFMT) == IFMT &&
8628084Smckusick 			    reply("HOLD BAD BLOCK") == 1) {
8740485Smckusick 				dp = ginode(inumber);
8828084Smckusick 				dp->di_size = sblock.fs_fsize;
8928084Smckusick 				dp->di_mode = IFREG|0600;
9028084Smckusick 				inodirty();
9128084Smckusick 			}
9217937Smckusick 			ndb = howmany(dp->di_size, sblock.fs_bsize);
9336952Smckusick 			if (ndb < 0) {
9436952Smckusick 				if (debug)
95*53822Smckusick 					printf("bad size %qu ndb %d:",
9636952Smckusick 						dp->di_size, ndb);
9736952Smckusick 				goto unknown;
9836952Smckusick 			}
9939973Smckusick 			if ((dp->di_mode & IFMT) == IFBLK ||
10039973Smckusick 			    (dp->di_mode & IFMT) == IFCHR)
10117937Smckusick 				ndb++;
10217937Smckusick 			for (j = ndb; j < NDADDR; j++)
10317937Smckusick 				if (dp->di_db[j] != 0) {
10417937Smckusick 					if (debug)
10544934Smckusick 						printf("bad direct addr: %ld\n",
10617937Smckusick 							dp->di_db[j]);
10717937Smckusick 					goto unknown;
10817937Smckusick 				}
10917937Smckusick 			for (j = 0, ndb -= NDADDR; ndb > 0; j++)
11017937Smckusick 				ndb /= NINDIR(&sblock);
11117937Smckusick 			for (; j < NIADDR; j++)
11217937Smckusick 				if (dp->di_ib[j] != 0) {
11317937Smckusick 					if (debug)
11444934Smckusick 						printf("bad indirect addr: %ld\n",
11517937Smckusick 							dp->di_ib[j]);
11617937Smckusick 					goto unknown;
11717937Smckusick 				}
11828084Smckusick 			if (ftypeok(dp) == 0)
11917937Smckusick 				goto unknown;
12017937Smckusick 			n_files++;
12117937Smckusick 			lncntp[inumber] = dp->di_nlink;
12217937Smckusick 			if (dp->di_nlink <= 0) {
12321759Smckusick 				zlnp = (struct zlncnt *)malloc(sizeof *zlnp);
12421759Smckusick 				if (zlnp == NULL) {
12517937Smckusick 					pfatal("LINK COUNT TABLE OVERFLOW");
12617937Smckusick 					if (reply("CONTINUE") == 0)
12717937Smckusick 						errexit("");
12821759Smckusick 				} else {
12921759Smckusick 					zlnp->zlncnt = inumber;
13021759Smckusick 					zlnp->next = zlnhead;
13121759Smckusick 					zlnhead = zlnp;
13217937Smckusick 				}
13317937Smckusick 			}
13439980Smckusick 			if ((dp->di_mode & IFMT) == IFDIR) {
13541135Smckusick 				if (dp->di_size == 0)
13641135Smckusick 					statemap[inumber] = DCLEAR;
13741135Smckusick 				else
13841135Smckusick 					statemap[inumber] = DSTATE;
13939980Smckusick 				cacheino(dp, inumber);
14039980Smckusick 			} else
14139980Smckusick 				statemap[inumber] = FSTATE;
14239973Smckusick 			badblk = dupblk = 0;
14317937Smckusick 			idesc.id_number = inumber;
14417937Smckusick 			(void)ckinode(dp, &idesc);
14517990Smckusick 			idesc.id_entryno *= btodb(sblock.fs_fsize);
14617990Smckusick 			if (dp->di_blocks != idesc.id_entryno) {
14744934Smckusick 				pwarn("INCORRECT BLOCK COUNT I=%lu (%ld should be %ld)",
14817990Smckusick 				    inumber, dp->di_blocks, idesc.id_entryno);
14917937Smckusick 				if (preen)
15017937Smckusick 					printf(" (CORRECTED)\n");
15117937Smckusick 				else if (reply("CORRECT") == 0)
15217937Smckusick 					continue;
15340485Smckusick 				dp = ginode(inumber);
15417990Smckusick 				dp->di_blocks = idesc.id_entryno;
15517937Smckusick 				inodirty();
15617937Smckusick 			}
15717937Smckusick 			continue;
15817937Smckusick 	unknown:
15944934Smckusick 			pfatal("UNKNOWN FILE TYPE I=%lu", inumber);
16026481Smckusick 			statemap[inumber] = FCLEAR;
16117937Smckusick 			if (reply("CLEAR") == 1) {
16226481Smckusick 				statemap[inumber] = USTATE;
16340485Smckusick 				dp = ginode(inumber);
16439973Smckusick 				clearinode(dp);
16517937Smckusick 				inodirty();
16617937Smckusick 			}
16716262Smckusick 		}
16816262Smckusick 	}
16940021Smckusick 	freeinodebuf();
17016262Smckusick }
17116262Smckusick 
17216262Smckusick pass1check(idesc)
17316262Smckusick 	register struct inodesc *idesc;
17416262Smckusick {
17516262Smckusick 	int res = KEEPON;
17616262Smckusick 	int anyout, nfrags;
17716262Smckusick 	daddr_t blkno = idesc->id_blkno;
17821744Smckusick 	register struct dups *dlp;
17921744Smckusick 	struct dups *new;
18016262Smckusick 
18139973Smckusick 	if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) {
18239973Smckusick 		blkerror(idesc->id_number, "BAD", blkno);
18347580Smckusick 		if (badblk++ >= MAXBAD) {
18444934Smckusick 			pwarn("EXCESSIVE BAD BLKS I=%lu",
18517931Smckusick 				idesc->id_number);
18617931Smckusick 			if (preen)
18717931Smckusick 				printf(" (SKIPPING)\n");
18817931Smckusick 			else if (reply("CONTINUE") == 0)
18917931Smckusick 				errexit("");
19017931Smckusick 			return (STOP);
19117931Smckusick 		}
19217931Smckusick 	}
19316262Smckusick 	for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
19439973Smckusick 		if (anyout && chkrange(blkno, 1)) {
19516262Smckusick 			res = SKIP;
19639973Smckusick 		} else if (!testbmap(blkno)) {
19717931Smckusick 			n_blks++;
19817931Smckusick 			setbmap(blkno);
19917931Smckusick 		} else {
20039973Smckusick 			blkerror(idesc->id_number, "DUP", blkno);
20147580Smckusick 			if (dupblk++ >= MAXDUP) {
20244934Smckusick 				pwarn("EXCESSIVE DUP BLKS I=%lu",
20316262Smckusick 					idesc->id_number);
20416262Smckusick 				if (preen)
20516262Smckusick 					printf(" (SKIPPING)\n");
20616262Smckusick 				else if (reply("CONTINUE") == 0)
20716262Smckusick 					errexit("");
20816262Smckusick 				return (STOP);
20916262Smckusick 			}
21021744Smckusick 			new = (struct dups *)malloc(sizeof(struct dups));
21121744Smckusick 			if (new == NULL) {
21216262Smckusick 				pfatal("DUP TABLE OVERFLOW.");
21316262Smckusick 				if (reply("CONTINUE") == 0)
21416262Smckusick 					errexit("");
21516262Smckusick 				return (STOP);
21616262Smckusick 			}
21721744Smckusick 			new->dup = blkno;
21821744Smckusick 			if (muldup == 0) {
21921744Smckusick 				duplist = muldup = new;
22021744Smckusick 				new->next = 0;
22121744Smckusick 			} else {
22221744Smckusick 				new->next = muldup->next;
22321744Smckusick 				muldup->next = new;
22421744Smckusick 			}
22521744Smckusick 			for (dlp = duplist; dlp != muldup; dlp = dlp->next)
22621744Smckusick 				if (dlp->dup == blkno)
22716262Smckusick 					break;
22821744Smckusick 			if (dlp == muldup && dlp->dup != blkno)
22921744Smckusick 				muldup = new;
23016262Smckusick 		}
23117990Smckusick 		/*
23217990Smckusick 		 * count the number of blocks found in id_entryno
23317990Smckusick 		 */
23417990Smckusick 		idesc->id_entryno++;
23516262Smckusick 	}
23616262Smckusick 	return (res);
23716262Smckusick }
238