1 /*	$OpenBSD: pass5.c,v 1.25 2007/03/15 10:27:00 pedro Exp $	*/
2 /*	$NetBSD: pass5.c,v 1.16 1996/09/27 22:45:18 christos Exp $	*/
3 
4 /*
5  * Copyright (c) 1980, 1986, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)pass5.c	8.6 (Berkeley) 11/30/94";
36 #else
37 static const char rcsid[] = "$OpenBSD: pass5.c,v 1.25 2007/03/15 10:27:00 pedro Exp $";
38 #endif
39 #endif /* not lint */
40 
41 #include <sys/param.h>
42 #include <sys/time.h>
43 #include <sys/lock.h>
44 #include <sys/ucred.h>
45 #include <ufs/ufs/dinode.h>
46 #include <ufs/ffs/fs.h>
47 #include <ufs/ufs/quota.h>
48 #include <ufs/ufs/inode.h>
49 #include <ufs/ffs/ffs_extern.h>
50 #include <stdio.h>
51 #include <string.h>
52 
53 #include "fsutil.h"
54 #include "fsck.h"
55 #include "extern.h"
56 
57 static int info_cg;
58 static int info_maxcg;
59 
60 static int
pass5_info(char * buf,size_t buflen)61 pass5_info(char *buf, size_t buflen)
62 {
63 	return (snprintf(buf, buflen, "phase 5, cg %d/%d",
64 	    info_cg, info_maxcg) > 0);
65 }
66 
67 void
pass5(void)68 pass5(void)
69 {
70 	int c, blk, frags, basesize, sumsize, mapsize, savednrpos=0;
71 	int inomapsize, blkmapsize;
72 	struct fs *fs = &sblock;
73 	struct cg *cg = &cgrp;
74 	daddr_t dbase, dmax;
75 	daddr_t d;
76 	long i, j, k;
77 	struct csum *cs;
78 	struct csum cstotal;
79 	struct inodesc idesc[3];
80 	char buf[MAXBSIZE];
81 	struct cg *newcg = (struct cg *)buf;
82 	struct ocg *ocg = (struct ocg *)buf;
83 
84 	memset(newcg, 0, (size_t)fs->fs_cgsize);
85 	newcg->cg_niblk = fs->fs_ipg;
86 	if (cvtlevel >= 3) {
87 		if (fs->fs_maxcontig < 2 && fs->fs_contigsumsize > 0) {
88 			if (preen)
89 				pwarn("DELETING CLUSTERING MAPS\n");
90 			if (preen || reply("DELETE CLUSTERING MAPS")) {
91 				fs->fs_contigsumsize = 0;
92 				doinglevel1 = 1;
93 				sbdirty();
94 			}
95 		}
96 		if (fs->fs_maxcontig > 1) {
97 			char *doit = 0;
98 
99 			if (fs->fs_contigsumsize < 1) {
100 				doit = "CREAT";
101 			} else if (fs->fs_contigsumsize < fs->fs_maxcontig &&
102 				   fs->fs_contigsumsize < FS_MAXCONTIG) {
103 				doit = "EXPAND";
104 			}
105 			if (doit) {
106 				i = fs->fs_contigsumsize;
107 				fs->fs_contigsumsize =
108 				    MIN(fs->fs_maxcontig, FS_MAXCONTIG);
109 				if (CGSIZE(fs) > fs->fs_bsize) {
110 					pwarn("CANNOT %s CLUSTER MAPS\n", doit);
111 					fs->fs_contigsumsize = i;
112 				} else if (preen ||
113 				    reply("CREATE CLUSTER MAPS")) {
114 					if (preen)
115 						pwarn("%sING CLUSTER MAPS\n",
116 						    doit);
117 					fs->fs_cgsize =
118 					    fragroundup(fs, CGSIZE(fs));
119 					doinglevel1 = 1;
120 					sbdirty();
121 				}
122 			}
123 		}
124 	}
125 	switch ((int)fs->fs_postblformat) {
126 
127 	case FS_42POSTBLFMT:
128 		basesize = (char *)(&ocg->cg_btot[0]) -
129 		    (char *)(&ocg->cg_firstfield);
130 		sumsize = &ocg->cg_iused[0] - (u_int8_t *)(&ocg->cg_btot[0]);
131 		mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] -
132 			(u_char *)&ocg->cg_iused[0];
133 		blkmapsize = howmany(fs->fs_fpg, NBBY);
134 		inomapsize = sizeof(ocg->cg_iused);
135 		ocg->cg_magic = CG_MAGIC;
136 		savednrpos = fs->fs_nrpos;
137 		fs->fs_nrpos = 8;
138 		break;
139 
140 	case FS_DYNAMICPOSTBLFMT:
141 		newcg->cg_btotoff =
142 		     &newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield);
143 		newcg->cg_boff =
144 		    newcg->cg_btotoff + fs->fs_cpg * sizeof(int32_t);
145 		newcg->cg_iusedoff = newcg->cg_boff +
146 		    fs->fs_cpg * fs->fs_nrpos * sizeof(int16_t);
147 		newcg->cg_freeoff =
148 		    newcg->cg_iusedoff + howmany(fs->fs_ipg, NBBY);
149 		inomapsize = newcg->cg_freeoff - newcg->cg_iusedoff;
150 		newcg->cg_nextfreeoff = newcg->cg_freeoff +
151 		    howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY);
152 		blkmapsize = newcg->cg_nextfreeoff - newcg->cg_freeoff;
153 		if (fs->fs_contigsumsize > 0) {
154 			newcg->cg_clustersumoff = newcg->cg_nextfreeoff -
155 			    sizeof(int32_t);
156 			newcg->cg_clustersumoff =
157 			    roundup(newcg->cg_clustersumoff, sizeof(int32_t));
158 			newcg->cg_clusteroff = newcg->cg_clustersumoff +
159 			    (fs->fs_contigsumsize + 1) * sizeof(int32_t);
160 			newcg->cg_nextfreeoff = newcg->cg_clusteroff +
161 			    howmany(fs->fs_cpg * fs->fs_spc / NSPB(fs), NBBY);
162 		}
163 		newcg->cg_magic = CG_MAGIC;
164 		basesize = &newcg->cg_space[0] -
165 		    (u_char *)(&newcg->cg_firstfield);
166 		sumsize = newcg->cg_iusedoff - newcg->cg_btotoff;
167 		mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff;
168 		break;
169 
170 	default:
171 		inomapsize = blkmapsize = sumsize = 0;
172 		errexit("UNKNOWN ROTATIONAL TABLE FORMAT %d\n",
173 			fs->fs_postblformat);
174 	}
175 	memset(&idesc[0], 0, sizeof idesc);
176 	for (i = 0; i < 3; i++) {
177 		idesc[i].id_type = ADDR;
178 		if (doinglevel2)
179 			idesc[i].id_fix = FIX;
180 	}
181 	memset(&cstotal, 0, sizeof(struct csum));
182 	j = blknum(fs, fs->fs_size + fs->fs_frag - 1);
183 	for (i = fs->fs_size; i < j; i++)
184 		setbmap(i);
185 	info_cg = 0;
186 	info_maxcg = fs->fs_ncg;
187 	info_fn = pass5_info;
188 	for (c = 0; c < fs->fs_ncg; c++) {
189 		info_cg = c;
190 		getblk(&cgblk, cgtod(fs, c), fs->fs_cgsize);
191 		if (!cg_chkmagic(cg))
192 			pfatal("CG %d: BAD MAGIC NUMBER\n", c);
193 		dbase = cgbase(fs, c);
194 		dmax = dbase + fs->fs_fpg;
195 		if (dmax > fs->fs_size)
196 			dmax = fs->fs_size;
197 		newcg->cg_time = cg->cg_time;
198 		newcg->cg_ffs2_time = cg->cg_ffs2_time;
199 		newcg->cg_cgx = c;
200 		if (c == fs->fs_ncg - 1)
201 			newcg->cg_ncyl = fs->fs_ncyl % fs->fs_cpg;
202 		else
203 			newcg->cg_ncyl = fs->fs_cpg;
204 		newcg->cg_ndblk = dmax - dbase;
205 		if (fs->fs_contigsumsize > 0)
206 			newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag;
207 		newcg->cg_cs.cs_ndir = 0;
208 		newcg->cg_cs.cs_nffree = 0;
209 		newcg->cg_cs.cs_nbfree = 0;
210 		newcg->cg_cs.cs_nifree = fs->fs_ipg;
211 		if (cg->cg_rotor < newcg->cg_ndblk)
212 			newcg->cg_rotor = cg->cg_rotor;
213 		else
214 			newcg->cg_rotor = 0;
215 		if (cg->cg_frotor >= 0 && cg->cg_frotor < newcg->cg_ndblk)
216 			newcg->cg_frotor = cg->cg_frotor;
217 		else
218 			newcg->cg_frotor = 0;
219 		if (cg->cg_irotor >= 0 && cg->cg_irotor < newcg->cg_niblk)
220 			newcg->cg_irotor = cg->cg_irotor;
221 		else
222 			newcg->cg_irotor = 0;
223 		memset(&newcg->cg_frsum[0], 0, sizeof newcg->cg_frsum);
224 		memset(&cg_blktot(newcg)[0], 0,
225 		      (size_t)(sumsize + mapsize));
226 		if (fs->fs_postblformat == FS_42POSTBLFMT)
227 			ocg->cg_magic = CG_MAGIC;
228 		j = fs->fs_ipg * c;
229 		for (i = 0; i < fs->fs_ipg; j++, i++) {
230 			switch (statemap[j]) {
231 
232 			case USTATE:
233 				break;
234 
235 			case DSTATE:
236 			case DCLEAR:
237 			case DFOUND:
238 				newcg->cg_cs.cs_ndir++;
239 				/* FALLTHROUGH */
240 
241 			case FSTATE:
242 			case FCLEAR:
243 				newcg->cg_cs.cs_nifree--;
244 				setbit(cg_inosused(newcg), i);
245 				break;
246 
247 			default:
248 				if (j < ROOTINO)
249 					break;
250 				errexit("BAD STATE %d FOR INODE I=%ld\n",
251 				    statemap[j], j);
252 			}
253 		}
254 		if (c == 0)
255 			for (i = 0; i < ROOTINO; i++) {
256 				setbit(cg_inosused(newcg), i);
257 				newcg->cg_cs.cs_nifree--;
258 			}
259 		for (i = 0, d = dbase;
260 		     d < dmax;
261 		     d += fs->fs_frag, i += fs->fs_frag) {
262 			frags = 0;
263 			for (j = 0; j < fs->fs_frag; j++) {
264 				if (testbmap(d + j))
265 					continue;
266 				setbit(cg_blksfree(newcg), i + j);
267 				frags++;
268 			}
269 			if (frags == fs->fs_frag) {
270 				newcg->cg_cs.cs_nbfree++;
271 				j = cbtocylno(fs, i);
272 				cg_blktot(newcg)[j]++;
273 				cg_blks(fs, newcg, j)[cbtorpos(fs, i)]++;
274 				if (fs->fs_contigsumsize > 0)
275 					setbit(cg_clustersfree(newcg),
276 					    i / fs->fs_frag);
277 			} else if (frags > 0) {
278 				newcg->cg_cs.cs_nffree += frags;
279 				blk = blkmap(fs, cg_blksfree(newcg), i);
280 				ffs_fragacct(fs, blk, newcg->cg_frsum, 1);
281 			}
282 		}
283 		if (fs->fs_contigsumsize > 0) {
284 			int32_t *sump = cg_clustersum(newcg);
285 			u_char *mapp = cg_clustersfree(newcg);
286 			int map = *mapp++;
287 			int bit = 1;
288 			int run = 0;
289 
290 			for (i = 0; i < newcg->cg_nclusterblks; i++) {
291 				if ((map & bit) != 0) {
292 					run++;
293 				} else if (run != 0) {
294 					if (run > fs->fs_contigsumsize)
295 						run = fs->fs_contigsumsize;
296 					sump[run]++;
297 					run = 0;
298 				}
299 				if ((i & (NBBY - 1)) != (NBBY - 1)) {
300 					bit <<= 1;
301 				} else {
302 					map = *mapp++;
303 					bit = 1;
304 				}
305 			}
306 			if (run != 0) {
307 				if (run > fs->fs_contigsumsize)
308 					run = fs->fs_contigsumsize;
309 				sump[run]++;
310 			}
311 		}
312 		cstotal.cs_nffree += newcg->cg_cs.cs_nffree;
313 		cstotal.cs_nbfree += newcg->cg_cs.cs_nbfree;
314 		cstotal.cs_nifree += newcg->cg_cs.cs_nifree;
315 		cstotal.cs_ndir += newcg->cg_cs.cs_ndir;
316 		cs = &fs->fs_cs(fs, c);
317 		if (memcmp(&newcg->cg_cs, cs, sizeof *cs) != 0 &&
318 		    dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
319 			memcpy(cs, &newcg->cg_cs, sizeof *cs);
320 			sbdirty();
321 		}
322 		if (doinglevel1) {
323 			memcpy(cg, newcg, (size_t)fs->fs_cgsize);
324 			cgdirty();
325 			continue;
326 		}
327 		if ((memcmp(newcg, cg, basesize) != 0 ||
328 		     memcmp(&cg_blktot(newcg)[0],
329 			    &cg_blktot(cg)[0], sumsize) != 0) &&
330 		    dofix(&idesc[2], "SUMMARY INFORMATION BAD")) {
331 			memcpy(cg, newcg, (size_t)basesize);
332 			memcpy(&cg_blktot(cg)[0],
333 			       &cg_blktot(newcg)[0], (size_t)sumsize);
334 			cgdirty();
335 		}
336 		if (usedsoftdep) {
337 			for (i = 0; i < inomapsize; i++) {
338 				j = cg_inosused(newcg)[i];
339 				if ((cg_inosused(cg)[i] & j) == j)
340 					continue;
341 				for (k = 0; k < NBBY; k++) {
342 					if ((j & (1 << k)) == 0)
343 						continue;
344 					if (cg_inosused(cg)[i] & (1 << k))
345 						continue;
346 					pwarn("ALLOCATED INODE %ld MARKED FREE\n",
347 					      c * fs->fs_ipg + i * 8 + k);
348 				}
349 			}
350 			for (i = 0; i < blkmapsize; i++) {
351 				j = cg_blksfree(cg)[i];
352 				if ((cg_blksfree(newcg)[i] & j) == j)
353 					continue;
354 				for (k = 0; k < NBBY; k++) {
355 					if ((j & (1 << k)) == 0)
356 						continue;
357 					if (cg_inosused(cg)[i] & (1 << k))
358 						continue;
359 					pwarn("ALLOCATED FRAG %ld MARKED FREE\n",
360 					      c * fs->fs_fpg + i * 8 + k);
361 				}
362 			}
363 		}
364 		if (memcmp(cg_inosused(newcg), cg_inosused(cg),
365 			   mapsize) != 0 &&
366 		    dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) {
367 			memmove(cg_inosused(cg), cg_inosused(newcg),
368 				(size_t)mapsize);
369 			cgdirty();
370 		}
371 	}
372 	info_fn = NULL;
373 	if (fs->fs_postblformat == FS_42POSTBLFMT)
374 		fs->fs_nrpos = savednrpos;
375 	if (memcmp(&cstotal, &fs->fs_cstotal, sizeof *cs) != 0
376 	    && dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
377 		memcpy(&fs->fs_cstotal, &cstotal, sizeof *cs);
378 		fs->fs_ronly = 0;
379 		fs->fs_fmod = 0;
380 		sbdirty();
381 	}
382 }
383