xref: /csrg-svn/sbin/fsck/pass5.c (revision 17693)
1 #ifndef lint
2 static char version[] = "@(#)pass5.c	3.3 (Berkeley) 01/10/85";
3 #endif
4 
5 #include <sys/param.h>
6 #include <sys/inode.h>
7 #include <sys/fs.h>
8 #include "fsck.h"
9 
10 pass5()
11 {
12 	register int c, n, i, b, d;
13 	short bo[MAXCPG][NRPOS];
14 	long botot[MAXCPG];
15 	long frsum[MAXFRAG];
16 	int blk;
17 	daddr_t cbase;
18 	int blockbits = (1<<sblock.fs_frag)-1;
19 
20 	bcopy(blockmap, freemap, (unsigned)bmapsz);
21 	dupblk = 0;
22 	n_index = sblock.fs_ncg * (cgdmin(&sblock, 0) - cgtod(&sblock, 0));
23 	for (c = 0; c < sblock.fs_ncg; c++) {
24 		cbase = cgbase(&sblock, c);
25 		bzero((char *)botot, sizeof (botot));
26 		bzero((char *)bo, sizeof (bo));
27 		bzero((char *)frsum, sizeof (frsum));
28 		/*
29 		 * need to account for the super blocks
30 		 * which appear (inaccurately) bad
31 		 */
32 		n_bad += cgtod(&sblock, c) - cgsblock(&sblock, c);
33 		if (getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize) == 0)
34 			continue;
35 		if (cgrp.cg_magic != CG_MAGIC) {
36 			pfatal("CG %d: BAD MAGIC NUMBER\n", c);
37 			bzero((char *)&cgrp, (int)sblock.fs_cgsize);
38 		}
39 		for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) {
40 			blk = blkmap(&sblock, cgrp.cg_free, b);
41 			if (blk == 0)
42 				continue;
43 			if (blk == blockbits) {
44 				if (pass5check(cbase+b, sblock.fs_frag) == STOP)
45 					goto out5;
46 				/* this is clumsy ... */
47 				n_ffree -= sblock.fs_frag;
48 				n_bfree++;
49 				botot[cbtocylno(&sblock, b)]++;
50 				bo[cbtocylno(&sblock, b)]
51 				    [cbtorpos(&sblock, b)]++;
52 				continue;
53 			}
54 			for (d = 0; d < sblock.fs_frag; d++)
55 				if ((blk & (1<<d)) &&
56 				    pass5check(cbase + b + d, (long)1) == STOP)
57 					goto out5;
58 			fragacct(&sblock, blk, frsum, 1);
59 		}
60 		if (bcmp((char *)cgrp.cg_frsum, (char *)frsum, sizeof(frsum))) {
61 			if (debug)
62 			for (i = 0; i < sblock.fs_frag; i++)
63 				if (cgrp.cg_frsum[i] != frsum[i])
64 				printf("cg[%d].cg_frsum[%d] have %d calc %d\n",
65 				    c, i, cgrp.cg_frsum[i], frsum[i]);
66 			frsumbad++;
67 		}
68 		if (bcmp((char *)cgrp.cg_btot, (char *)botot, sizeof (botot))) {
69 			if (debug)
70 			for (n = 0; n < sblock.fs_cpg; n++)
71 				if (botot[n] != cgrp.cg_btot[n])
72 				printf("cg[%d].cg_btot[%d] have %d calc %d\n",
73 				    c, n, cgrp.cg_btot[n], botot[n]);
74 			offsumbad++;
75 		}
76 		if (bcmp((char *)cgrp.cg_b, (char *)bo, sizeof (bo))) {
77 			if (debug)
78 			for (i = 0; i < NRPOS; i++)
79 				if (bo[n][i] != cgrp.cg_b[n][i])
80 				printf("cg[%d].cg_b[%d][%d] have %d calc %d\n",
81 				    c, n, i, cgrp.cg_b[n][i], bo[n][i]);
82 			offsumbad++;
83 		}
84 	}
85 out5:
86 	if (dupblk)
87 		pwarn("%d DUP BLKS IN BIT MAPS\n", dupblk);
88 	if (fixcg == 0) {
89 		if ((b = n_blks+n_ffree+sblock.fs_frag*n_bfree+n_index+n_bad) != fmax) {
90 			pwarn("%ld BLK(S) MISSING\n", fmax - b);
91 			fixcg = 1;
92 		} else if (inosumbad + offsumbad + frsumbad + sbsumbad) {
93 			pwarn("SUMMARY INFORMATION %s%s%s%sBAD\n",
94 			    inosumbad ? "(INODE FREE) " : "",
95 			    offsumbad ? "(BLOCK OFFSETS) " : "",
96 			    frsumbad ? "(FRAG SUMMARIES) " : "",
97 			    sbsumbad ? "(SUPER BLOCK SUMMARIES) " : "");
98 			fixcg = 1;
99 		} else if (n_ffree != sblock.fs_cstotal.cs_nffree ||
100 		    n_bfree != sblock.fs_cstotal.cs_nbfree) {
101 			pwarn("FREE BLK COUNT(S) WRONG IN SUPERBLK");
102 			if (preen)
103 				printf(" (FIXED)\n");
104 			if (preen || reply("FIX") == 1) {
105 				sblock.fs_cstotal.cs_nffree = n_ffree;
106 				sblock.fs_cstotal.cs_nbfree = n_bfree;
107 				sbdirty();
108 			}
109 		}
110 	}
111 	if (fixcg) {
112 		pwarn("BAD CYLINDER GROUPS");
113 		if (preen)
114 			printf(" (SALVAGED)\n");
115 		else if (reply("SALVAGE") == 0)
116 			fixcg = 0;
117 	}
118 }
119 
120 pass5check(blk, size)
121 	daddr_t blk;
122 	long size;
123 {
124 
125 	if (outrange(blk, (int)size)) {
126 		fixcg = 1;
127 		if (preen)
128 			pfatal("BAD BLOCKS IN BIT MAPS.");
129 		if (++badblk >= MAXBAD) {
130 			printf("EXCESSIVE BAD BLKS IN BIT MAPS.");
131 			if (reply("CONTINUE") == 0)
132 				errexit("");
133 			return (STOP);
134 		}
135 	}
136 	for (; size > 0; blk++, size--)
137 		if (getfmap(blk)) {
138 			fixcg = 1;
139 			++dupblk;
140 		} else {
141 			n_ffree++;
142 			setfmap(blk);
143 		}
144 	return (KEEPON);
145 }
146