xref: /csrg-svn/sbin/fsck/pass1.c (revision 17931)
116262Smckusick #ifndef lint
2*17931Smckusick static char version[] = "@(#)pass1.c	3.2 (Berkeley) 02/07/85";
316262Smckusick #endif
416262Smckusick 
516262Smckusick #include <sys/param.h>
616262Smckusick #include <sys/inode.h>
716262Smckusick #include <sys/fs.h>
816262Smckusick #include "fsck.h"
916262Smckusick 
1016262Smckusick int	pass1check();
1116262Smckusick 
1216262Smckusick pass1()
1316262Smckusick {
1416262Smckusick 	register int c, i, n, j;
1516262Smckusick 	register DINODE *dp;
16*17931Smckusick 	int ndb, partial, cgd;
1716262Smckusick 	struct inodesc idesc;
1816262Smckusick 	ino_t inumber;
1916262Smckusick 
20*17931Smckusick 	/*
21*17931Smckusick 	 * Set file system reserved blocks in used block map.
22*17931Smckusick 	 */
23*17931Smckusick 	for (c = 0; c < sblock.fs_ncg; c++) {
24*17931Smckusick 		cgd = cgdmin(&sblock, c);
25*17931Smckusick 		if (c == 0) {
26*17931Smckusick 			i = cgbase(&sblock, c);
27*17931Smckusick 			cgd += howmany(sblock.fs_cssize, sblock.fs_fsize);
28*17931Smckusick 		} else
29*17931Smckusick 			i = cgsblock(&sblock, c);
30*17931Smckusick 		for (; i < cgd; i++)
31*17931Smckusick 			setbmap(i);
32*17931Smckusick 	}
33*17931Smckusick 	/*
34*17931Smckusick 	 * Find all allocated blocks.
35*17931Smckusick 	 */
3616262Smckusick 	bzero((char *)&idesc, sizeof(struct inodesc));
3716262Smckusick 	idesc.id_type = ADDR;
3816262Smckusick 	idesc.id_func = pass1check;
3916262Smckusick 	inumber = 0;
4016262Smckusick 	n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
4116262Smckusick 	for (c = 0; c < sblock.fs_ncg; c++) {
4216262Smckusick 		if (getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize) == 0)
4316262Smckusick 			continue;
4416262Smckusick 		if (cgrp.cg_magic != CG_MAGIC) {
4516262Smckusick 			pfatal("CG %d: BAD MAGIC NUMBER\n", c);
4616262Smckusick 			bzero((char *)&cgrp, (int)sblock.fs_cgsize);
4716262Smckusick 		}
4816262Smckusick 		n = 0;
4916262Smckusick 		for (i = 0; i < sblock.fs_ipg; i++, inumber++) {
5016262Smckusick 			dp = ginode(inumber);
5116262Smckusick 			if (dp == NULL)
5216262Smckusick 				continue;
5316262Smckusick 			n++;
54*17931Smckusick 			if (ALLOC(dp)) {
5516262Smckusick 				if (!isset(cgrp.cg_iused, i)) {
5616262Smckusick 					if (debug)
5716262Smckusick 						printf("%d bad, not used\n",
5816262Smckusick 						    inumber);
5916262Smckusick 					inosumbad++;
6016262Smckusick 				}
6116262Smckusick 				n--;
6216262Smckusick 				lastino = inumber;
6316262Smckusick 				if (!preen && (dp->di_mode & IFMT) == IFMT &&
6416262Smckusick 				    reply("HOLD BAD BLOCK") == 1) {
6516262Smckusick 					dp->di_size = sblock.fs_fsize;
6616262Smckusick 					dp->di_mode = IFREG|0600;
6716262Smckusick 					inodirty();
6816262Smckusick 				} else if (ftypeok(dp) == 0)
6916262Smckusick 					goto unknown;
7016262Smckusick 				if (dp->di_size < 0) {
7116262Smckusick 					if (debug)
7216262Smckusick 						printf("bad size %d:",
7316262Smckusick 							dp->di_size);
7416262Smckusick 					goto unknown;
7516262Smckusick 				}
7616262Smckusick 				ndb = howmany(dp->di_size, sblock.fs_bsize);
77*17931Smckusick 				if (SPECIAL(dp))
7816262Smckusick 					ndb++;
7916262Smckusick 				for (j = ndb; j < NDADDR; j++)
8016262Smckusick 					if (dp->di_db[j] != 0) {
8116262Smckusick 						if (debug)
8216262Smckusick 							printf("bad direct addr: %d\n",
8316262Smckusick 								dp->di_db[j]);
8416262Smckusick 						goto unknown;
8516262Smckusick 					}
8616262Smckusick 				for (j = 0, ndb -= NDADDR; ndb > 0; j++)
8716262Smckusick 					ndb /= NINDIR(&sblock);
8816262Smckusick 				for (; j < NIADDR; j++)
8916262Smckusick 					if (dp->di_ib[j] != 0) {
9016262Smckusick 						if (debug)
9116262Smckusick 							printf("bad indirect addr: %d\n",
9216262Smckusick 								dp->di_ib[j]);
9316262Smckusick 						goto unknown;
9416262Smckusick 					}
9516262Smckusick 				n_files++;
9616262Smckusick 				lncntp[inumber] = dp->di_nlink;
9716262Smckusick 				if (dp->di_nlink <= 0) {
9816262Smckusick 					if (badlnp < &badlncnt[MAXLNCNT])
9916262Smckusick 						*badlnp++ = inumber;
10016262Smckusick 					else {
10116262Smckusick 						pfatal("LINK COUNT TABLE OVERFLOW");
10216262Smckusick 						if (reply("CONTINUE") == 0)
10316262Smckusick 							errexit("");
10416262Smckusick 					}
10516262Smckusick 				}
106*17931Smckusick 				statemap[inumber] = DIRCT(dp) ? DSTATE : FSTATE;
10716262Smckusick 				badblk = dupblk = 0; maxblk = 0;
10816262Smckusick 				idesc.id_number = inumber;
10916262Smckusick 				idesc.id_filesize = 0;
11016262Smckusick 				(void)ckinode(dp, &idesc);
11116262Smckusick 				idesc.id_filesize *= btodb(sblock.fs_fsize);
11216262Smckusick 				if (dp->di_blocks != idesc.id_filesize) {
11316262Smckusick 					pwarn("INCORRECT BLOCK COUNT I=%u (%ld should be %ld)",
11416262Smckusick 					    inumber, dp->di_blocks,
11516262Smckusick 					    idesc.id_filesize);
11616262Smckusick 					if (preen)
11716262Smckusick 						printf(" (CORRECTED)\n");
11816262Smckusick 					else if (reply("CORRECT") == 0)
11916262Smckusick 						continue;
12016262Smckusick 					dp->di_blocks = idesc.id_filesize;
12116262Smckusick 					inodirty();
12216262Smckusick 				}
12316262Smckusick 				continue;
12416262Smckusick 		unknown:
12516262Smckusick 				pfatal("UNKNOWN FILE TYPE I=%u", inumber);
12616262Smckusick 				if (reply("CLEAR") == 1) {
12716262Smckusick 					zapino(dp);
12816262Smckusick 					inodirty();
12916262Smckusick 					inosumbad++;
13016262Smckusick 				}
13116262Smckusick 			} else {
13216262Smckusick 				if (isset(cgrp.cg_iused, i)) {
13316262Smckusick 					if (debug)
13416262Smckusick 						printf("%d bad, marked used\n",
13516262Smckusick 						    inumber);
13616262Smckusick 					inosumbad++;
13716262Smckusick 					n--;
13816262Smckusick 				}
13916262Smckusick 				partial = 0;
14016262Smckusick 				for (j = 0; j < NDADDR; j++)
14116262Smckusick 					if (dp->di_db[j] != 0)
14216262Smckusick 						partial++;
14316262Smckusick 				for (j = 0; j < NIADDR; j++)
14416262Smckusick 					if (dp->di_ib[j] != 0)
14516262Smckusick 						partial++;
14616262Smckusick 				if (partial || dp->di_mode != 0 ||
14716262Smckusick 				    dp->di_size != 0) {
14816262Smckusick 					pfatal("PARTIALLY ALLOCATED INODE I=%u",
14916262Smckusick 						inumber);
15016262Smckusick 					if (reply("CLEAR") == 1) {
15116262Smckusick 						zapino(dp);
15216262Smckusick 						inodirty();
15316262Smckusick 						inosumbad++;
15416262Smckusick 					}
15516262Smckusick 				}
15616262Smckusick 			}
15716262Smckusick 		}
15816262Smckusick 		if (n != cgrp.cg_cs.cs_nifree) {
15916262Smckusick 			if (debug)
16016262Smckusick 				printf("cg[%d].cg_cs.cs_nifree is %d; calc %d\n",
16116262Smckusick 				    c, cgrp.cg_cs.cs_nifree, n);
16216262Smckusick 			inosumbad++;
16316262Smckusick 		}
16416262Smckusick 		if (cgrp.cg_cs.cs_nbfree != sblock.fs_cs(&sblock, c).cs_nbfree
16516262Smckusick 		  || cgrp.cg_cs.cs_nffree != sblock.fs_cs(&sblock, c).cs_nffree
16616262Smckusick 		  || cgrp.cg_cs.cs_nifree != sblock.fs_cs(&sblock, c).cs_nifree
16716262Smckusick 		  || cgrp.cg_cs.cs_ndir != sblock.fs_cs(&sblock, c).cs_ndir)
16816262Smckusick 			sbsumbad++;
16916262Smckusick 	}
17016262Smckusick }
17116262Smckusick 
17216262Smckusick pass1check(idesc)
17316262Smckusick 	register struct inodesc *idesc;
17416262Smckusick {
17516262Smckusick 	register daddr_t *dlp;
17616262Smckusick 	int res = KEEPON;
17716262Smckusick 	int anyout, nfrags;
17816262Smckusick 	daddr_t blkno = idesc->id_blkno;
17916262Smckusick 
180*17931Smckusick 	if ((anyout = outrange(blkno, idesc->id_numfrags)) != 0) {
181*17931Smckusick 		blkerr(idesc->id_number, "BAD", blkno);
182*17931Smckusick 		if (++badblk >= MAXBAD) {
183*17931Smckusick 			pwarn("EXCESSIVE BAD BLKS I=%u",
184*17931Smckusick 				idesc->id_number);
185*17931Smckusick 			if (preen)
186*17931Smckusick 				printf(" (SKIPPING)\n");
187*17931Smckusick 			else if (reply("CONTINUE") == 0)
188*17931Smckusick 				errexit("");
189*17931Smckusick 			return (STOP);
190*17931Smckusick 		}
191*17931Smckusick 	}
19216262Smckusick 	for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
19316262Smckusick 		if (anyout && outrange(blkno, 1)) {
19416262Smckusick 			res = SKIP;
195*17931Smckusick 		} else if (!getbmap(blkno)) {
196*17931Smckusick 			n_blks++;
197*17931Smckusick 			setbmap(blkno);
198*17931Smckusick 		} else {
19916262Smckusick 			blkerr(idesc->id_number, "DUP", blkno);
20016262Smckusick 			if (++dupblk >= MAXDUP) {
20116262Smckusick 				pwarn("EXCESSIVE DUP BLKS I=%u",
20216262Smckusick 					idesc->id_number);
20316262Smckusick 				if (preen)
20416262Smckusick 					printf(" (SKIPPING)\n");
20516262Smckusick 				else if (reply("CONTINUE") == 0)
20616262Smckusick 					errexit("");
20716262Smckusick 				return (STOP);
20816262Smckusick 			}
20916262Smckusick 			if (enddup >= &duplist[DUPTBLSIZE]) {
21016262Smckusick 				pfatal("DUP TABLE OVERFLOW.");
21116262Smckusick 				if (reply("CONTINUE") == 0)
21216262Smckusick 					errexit("");
21316262Smckusick 				return (STOP);
21416262Smckusick 			}
21516262Smckusick 			for (dlp = duplist; dlp < muldup; dlp++)
21616262Smckusick 				if (*dlp == blkno) {
21716262Smckusick 					*enddup++ = blkno;
21816262Smckusick 					break;
21916262Smckusick 				}
22016262Smckusick 			if (dlp >= muldup) {
22116262Smckusick 				*enddup++ = *muldup;
22216262Smckusick 				*muldup++ = blkno;
22316262Smckusick 			}
22416262Smckusick 		}
22516262Smckusick 		idesc->id_filesize++;
22616262Smckusick 	}
22716262Smckusick 	return (res);
22816262Smckusick }
229