xref: /csrg-svn/sbin/fsck/pass5.c (revision 34141)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)pass5.c	5.4 (Berkeley) 05/01/88";
9 #endif not lint
10 
11 #include <sys/param.h>
12 #include <sys/inode.h>
13 #include <sys/fs.h>
14 #include "fsck.h"
15 
16 pass5()
17 {
18 	int c, blk, frags, basesize, sumsize, mapsize, savednrpos;
19 	daddr_t dbase, dmax;
20 	register daddr_t d;
21 	register long i, j;
22 	struct csum *cs;
23 	time_t now;
24 	struct csum cstotal;
25 	struct inodesc idesc;
26 	char buf[MAXBSIZE];
27 	register struct cg *newcg = (struct cg *)buf;
28 	struct ocg *ocg = (struct ocg *)buf;
29 
30 	bzero((char *)newcg, sblock.fs_cgsize);
31 	newcg->cg_niblk = sblock.fs_ipg;
32 	switch (sblock.fs_postblformat) {
33 
34 	case FS_42POSTBLFMT:
35 		basesize = (char *)(&ocg->cg_btot[0]) - (char *)(&ocg->cg_link);
36 		sumsize = &ocg->cg_iused[0] - (char *)(&ocg->cg_btot[0]);
37 		mapsize = &ocg->cg_free[howmany(sblock.fs_fpg, NBBY)] -
38 			(u_char *)&ocg->cg_iused[0];
39 		ocg->cg_magic = CG_MAGIC;
40 		savednrpos = sblock.fs_nrpos;
41 		sblock.fs_nrpos = 8;
42 		break;
43 
44 	case FS_DYNAMICPOSTBLFMT:
45 		newcg->cg_btotoff =
46 		 	&newcg->cg_space[0] - (u_char *)(&newcg->cg_link);
47 		newcg->cg_boff =
48 			newcg->cg_btotoff + sblock.fs_cpg * sizeof(long);
49 		newcg->cg_iusedoff = newcg->cg_boff +
50 			sblock.fs_cpg * sblock.fs_nrpos * sizeof(short);
51 		newcg->cg_freeoff =
52 			newcg->cg_iusedoff + howmany(sblock.fs_ipg, NBBY);
53 		newcg->cg_nextfreeoff = newcg->cg_freeoff +
54 			howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock),
55 				NBBY);
56 		newcg->cg_magic = CG_MAGIC;
57 		basesize = &newcg->cg_space[0] - (u_char *)(&newcg->cg_link);
58 		sumsize = newcg->cg_iusedoff - newcg->cg_btotoff;
59 		mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff;
60 		break;
61 
62 	default:
63 		errexit("UNKNOWN ROTATIONAL TABLE FORMAT %d\n",
64 			sblock.fs_postblformat);
65 	}
66 	bzero((char *)&idesc, sizeof(struct inodesc));
67 	idesc.id_type = ADDR;
68 	bzero((char *)&cstotal, sizeof(struct csum));
69 	(void)time(&now);
70 	for (i = sblock.fs_size; i < fragroundup(&sblock, sblock.fs_size); i++)
71 		setbmap(i);
72 	for (c = 0; c < sblock.fs_ncg; c++) {
73 		getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize);
74 		if (!cg_chkmagic(&cgrp))
75 			pfatal("CG %d: BAD MAGIC NUMBER\n", c);
76 		dbase = cgbase(&sblock, c);
77 		dmax = dbase + sblock.fs_fpg;
78 		if (dmax > sblock.fs_size)
79 			dmax = sblock.fs_size;
80 		if (now > cgrp.cg_time)
81 			newcg->cg_time = cgrp.cg_time;
82 		else
83 			newcg->cg_time = now;
84 		newcg->cg_cgx = c;
85 		if (c == sblock.fs_ncg - 1)
86 			newcg->cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg;
87 		else
88 			newcg->cg_ncyl = sblock.fs_cpg;
89 		newcg->cg_ndblk = dmax - dbase;
90 		newcg->cg_cs.cs_ndir = 0;
91 		newcg->cg_cs.cs_nffree = 0;
92 		newcg->cg_cs.cs_nbfree = 0;
93 		newcg->cg_cs.cs_nifree = sblock.fs_ipg;
94 		if (cgrp.cg_rotor < newcg->cg_ndblk)
95 			newcg->cg_rotor = cgrp.cg_rotor;
96 		else
97 			newcg->cg_rotor = 0;
98 		if (cgrp.cg_frotor < newcg->cg_ndblk)
99 			newcg->cg_frotor = cgrp.cg_frotor;
100 		else
101 			newcg->cg_frotor = 0;
102 		if (cgrp.cg_irotor < newcg->cg_niblk)
103 			newcg->cg_irotor = cgrp.cg_irotor;
104 		else
105 			newcg->cg_irotor = 0;
106 		bzero((char *)&newcg->cg_frsum[0], sizeof newcg->cg_frsum);
107 		bzero((char *)&cg_blktot(newcg)[0], sumsize + mapsize);
108 		if (sblock.fs_postblformat == FS_42POSTBLFMT)
109 			ocg->cg_magic = CG_MAGIC;
110 		j = sblock.fs_ipg * c;
111 		for (i = 0; i < sblock.fs_ipg; j++, i++) {
112 			switch (statemap[j]) {
113 
114 			case USTATE:
115 				break;
116 
117 			case DSTATE:
118 			case DCLEAR:
119 			case DFOUND:
120 				newcg->cg_cs.cs_ndir++;
121 				/* fall through */
122 
123 			case FSTATE:
124 			case FCLEAR:
125 				newcg->cg_cs.cs_nifree--;
126 				setbit(cg_inosused(newcg), i);
127 				break;
128 
129 			default:
130 				if (j < ROOTINO)
131 					break;
132 				errexit("BAD STATE %d FOR INODE I=%d",
133 				    statemap[j], j);
134 			}
135 		}
136 		if (c == 0)
137 			for (i = 0; i < ROOTINO; i++) {
138 				setbit(cg_inosused(newcg), i);
139 				newcg->cg_cs.cs_nifree--;
140 			}
141 		for (i = 0, d = dbase;
142 		     d < dmax;
143 		     d += sblock.fs_frag, i += sblock.fs_frag) {
144 			frags = 0;
145 			for (j = 0; j < sblock.fs_frag; j++) {
146 				if (getbmap(d + j))
147 					continue;
148 				setbit(cg_blksfree(newcg), i + j);
149 				frags++;
150 			}
151 			if (frags == sblock.fs_frag) {
152 				newcg->cg_cs.cs_nbfree++;
153 				j = cbtocylno(&sblock, i);
154 				cg_blktot(newcg)[j]++;
155 				cg_blks(&sblock, newcg, j)
156 				    [cbtorpos(&sblock, i)]++;
157 			} else if (frags > 0) {
158 				newcg->cg_cs.cs_nffree += frags;
159 				blk = blkmap(&sblock, cg_blksfree(newcg), i);
160 				fragacct(&sblock, blk, newcg->cg_frsum, 1);
161 			}
162 		}
163 		cstotal.cs_nffree += newcg->cg_cs.cs_nffree;
164 		cstotal.cs_nbfree += newcg->cg_cs.cs_nbfree;
165 		cstotal.cs_nifree += newcg->cg_cs.cs_nifree;
166 		cstotal.cs_ndir += newcg->cg_cs.cs_ndir;
167 		cs = &sblock.fs_cs(&sblock, c);
168 		if (bcmp((char *)&newcg->cg_cs, (char *)cs, sizeof *cs) != 0 &&
169 		    dofix(&idesc, "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
170 			bcopy((char *)&newcg->cg_cs, (char *)cs, sizeof *cs);
171 			sbdirty();
172 		}
173 		if (cvtflag) {
174 			bcopy((char *)newcg, (char *)&cgrp, sblock.fs_cgsize);
175 			cgdirty();
176 			continue;
177 		}
178 		if (bcmp(cg_inosused(newcg),
179 			 cg_inosused(&cgrp), mapsize) != 0 &&
180 		    dofix(&idesc, "BLK(S) MISSING IN BIT MAPS")) {
181 			bcopy(cg_inosused(newcg), cg_inosused(&cgrp), mapsize);
182 			cgdirty();
183 		}
184 		if ((bcmp((char *)newcg, (char *)&cgrp, basesize) != 0 ||
185 		     bcmp((char *)&cg_blktot(newcg)[0],
186 			  (char *)&cg_blktot(&cgrp)[0], sumsize) != 0) &&
187 		    dofix(&idesc, "SUMMARY INFORMATION BAD")) {
188 			bcopy((char *)newcg, (char *)&cgrp, basesize);
189 			bcopy((char *)&cg_blktot(newcg)[0],
190 			      (char *)&cg_blktot(&cgrp)[0], sumsize);
191 			cgdirty();
192 		}
193 	}
194 	if (sblock.fs_postblformat == FS_42POSTBLFMT)
195 		sblock.fs_nrpos = savednrpos;
196 	if (bcmp((char *)&cstotal, (char *)&sblock.fs_cstotal, sizeof *cs) != 0
197 	    && dofix(&idesc, "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
198 		bcopy((char *)&cstotal, (char *)&sblock.fs_cstotal, sizeof *cs);
199 		sblock.fs_ronly = 0;
200 		sblock.fs_fmod = 0;
201 		sbdirty();
202 	}
203 }
204