xref: /openbsd/sbin/fsck_ffs/pass5.c (revision cecf84d4)
1 /*	$OpenBSD: pass5.c,v 1.48 2015/01/20 18:22:21 deraadt 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 #include <sys/param.h>	/* MAXBSIZE roundup setbit */
34 #include <sys/time.h>
35 #include <sys/lock.h>
36 #include <sys/ucred.h>
37 #include <ufs/ffs/fs.h>
38 #include <ufs/ufs/quota.h>
39 #include <ufs/ufs/inode.h>
40 #include <ufs/ffs/ffs_extern.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <limits.h>
44 
45 #include "fsutil.h"
46 #include "fsck.h"
47 #include "extern.h"
48 
49 #define MINIMUM(a, b)	(((a) < (b)) ? (a) : (b))
50 
51 static int info_cg;
52 static int info_maxcg;
53 
54 static int
55 pass5_info(char *buf, size_t buflen)
56 {
57 	return (snprintf(buf, buflen, "phase 5, cg %d/%d",
58 	    info_cg, info_maxcg) > 0);
59 }
60 
61 void
62 pass5(void)
63 {
64 	int c, blk, frags, basesize, sumsize, mapsize, savednrpos=0;
65 	int inomapsize, blkmapsize;
66 	struct fs *fs = &sblock;
67 	struct cg *cg = &cgrp;
68 	daddr_t dbase, dmax;
69 	daddr_t d;
70 	long i, j, k, rewritecg = 0;
71 	struct csum *cs;
72 	struct csum_total cstotal;
73 	struct inodesc idesc[3];
74 	char buf[MAXBSIZE];
75 	struct cg *newcg = (struct cg *)buf;
76 	struct ocg *ocg = (struct ocg *)buf;
77 
78 	memset(newcg, 0, (size_t)fs->fs_cgsize);
79 	if (cvtlevel >= 3) {
80 		if (fs->fs_maxcontig < 2 && fs->fs_contigsumsize > 0) {
81 			if (preen)
82 				pwarn("DELETING CLUSTERING MAPS\n");
83 			if (preen || reply("DELETE CLUSTERING MAPS")) {
84 				fs->fs_contigsumsize = 0;
85 				rewritecg = 1;
86 				sbdirty();
87 			}
88 		}
89 		if (fs->fs_maxcontig > 1) {
90 			char *doit = 0;
91 
92 			if (fs->fs_contigsumsize < 1) {
93 				doit = "CREAT";
94 			} else if (fs->fs_contigsumsize < fs->fs_maxcontig &&
95 				   fs->fs_contigsumsize < FS_MAXCONTIG) {
96 				doit = "EXPAND";
97 			}
98 			if (doit) {
99 				i = fs->fs_contigsumsize;
100 				fs->fs_contigsumsize =
101 				    MINIMUM(fs->fs_maxcontig, FS_MAXCONTIG);
102 				if (CGSIZE(fs) > fs->fs_bsize) {
103 					pwarn("CANNOT %s CLUSTER MAPS\n", doit);
104 					fs->fs_contigsumsize = i;
105 				} else if (preen ||
106 				    reply("CREATE CLUSTER MAPS")) {
107 					if (preen)
108 						pwarn("%sING CLUSTER MAPS\n",
109 						    doit);
110 					fs->fs_cgsize =
111 					    fragroundup(fs, CGSIZE(fs));
112 					rewritecg = 1;
113 					sbdirty();
114 				}
115 			}
116 		}
117 	}
118 	switch ((int)fs->fs_postblformat) {
119 
120 	case FS_42POSTBLFMT:
121 		basesize = (char *)(&ocg->cg_btot[0]) -
122 		    (char *)(&ocg->cg_firstfield);
123 		sumsize = &ocg->cg_iused[0] - (u_int8_t *)(&ocg->cg_btot[0]);
124 		mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] -
125 			(u_char *)&ocg->cg_iused[0];
126 		blkmapsize = howmany(fs->fs_fpg, NBBY);
127 		inomapsize = sizeof(ocg->cg_iused);
128 		ocg->cg_magic = CG_MAGIC;
129 		savednrpos = fs->fs_nrpos;
130 		fs->fs_nrpos = 8;
131 		break;
132 
133 	case FS_DYNAMICPOSTBLFMT:
134 		if (sblock.fs_magic == FS_UFS2_MAGIC) {
135 			newcg->cg_iusedoff = sizeof(struct cg);
136 		} else {
137 			newcg->cg_btotoff = sizeof(struct cg);
138 			newcg->cg_boff = newcg->cg_btotoff +
139 			    fs->fs_cpg * sizeof(int32_t);
140 			newcg->cg_iusedoff = newcg->cg_boff + fs->fs_cpg *
141 			    fs->fs_nrpos * sizeof(int16_t);
142 		}
143 		inomapsize = howmany(fs->fs_ipg, CHAR_BIT);
144 		newcg->cg_freeoff = newcg->cg_iusedoff + inomapsize;
145 		blkmapsize = howmany(fs->fs_fpg, CHAR_BIT);
146 		newcg->cg_nextfreeoff = newcg->cg_freeoff + blkmapsize;
147 		if (fs->fs_contigsumsize > 0) {
148 			newcg->cg_clustersumoff = newcg->cg_nextfreeoff -
149 			    sizeof(int32_t);
150 			newcg->cg_clustersumoff =
151 			    roundup(newcg->cg_clustersumoff, sizeof(int32_t));
152 			newcg->cg_clusteroff = newcg->cg_clustersumoff +
153 			    (fs->fs_contigsumsize + 1) * sizeof(int32_t);
154 			newcg->cg_nextfreeoff = newcg->cg_clusteroff +
155 			    howmany(fragstoblks(fs, fs->fs_fpg), CHAR_BIT);
156 		}
157 		newcg->cg_magic = CG_MAGIC;
158 		basesize = sizeof(struct cg);
159 		sumsize = newcg->cg_iusedoff - newcg->cg_btotoff;
160 		mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff;
161 		break;
162 
163 	default:
164 		inomapsize = blkmapsize = sumsize = 0;
165 		errexit("UNKNOWN ROTATIONAL TABLE FORMAT %d\n",
166 			fs->fs_postblformat);
167 	}
168 	memset(&idesc[0], 0, sizeof idesc);
169 	for (i = 0; i < 3; i++)
170 		idesc[i].id_type = ADDR;
171 	memset(&cstotal, 0, sizeof(struct csum_total));
172 	dmax = blknum(fs, fs->fs_size + fs->fs_frag - 1);
173 	for (d = fs->fs_size; d < dmax; d++)
174 		setbmap(d);
175 	info_cg = 0;
176 	info_maxcg = fs->fs_ncg;
177 	info_fn = pass5_info;
178 	for (c = 0; c < fs->fs_ncg; c++) {
179 		info_cg = c;
180 		getblk(&cgblk, cgtod(fs, c), fs->fs_cgsize);
181 		if (!cg_chkmagic(cg))
182 			pfatal("CG %d: BAD MAGIC NUMBER\n", c);
183 		dbase = cgbase(fs, c);
184 		dmax = dbase + fs->fs_fpg;
185 		if (dmax > fs->fs_size)
186 			dmax = fs->fs_size;
187 		newcg->cg_time = cg->cg_time;
188 		newcg->cg_ffs2_time = cg->cg_ffs2_time;
189 		newcg->cg_cgx = c;
190 		if (c == fs->fs_ncg - 1)
191 			newcg->cg_ncyl = fs->fs_ncyl % fs->fs_cpg;
192 		else
193 			newcg->cg_ncyl = fs->fs_cpg;
194 		newcg->cg_ndblk = dmax - dbase;
195 		if (fs->fs_contigsumsize > 0)
196 			newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag;
197 		newcg->cg_cs.cs_ndir = 0;
198 		newcg->cg_cs.cs_nffree = 0;
199 		newcg->cg_cs.cs_nbfree = 0;
200 		newcg->cg_cs.cs_nifree = fs->fs_ipg;
201 		if (cg->cg_rotor < newcg->cg_ndblk)
202 			newcg->cg_rotor = cg->cg_rotor;
203 		else
204 			newcg->cg_rotor = 0;
205 		if (cg->cg_frotor >= 0 && cg->cg_frotor < newcg->cg_ndblk)
206 			newcg->cg_frotor = cg->cg_frotor;
207 		else
208 			newcg->cg_frotor = 0;
209 		newcg->cg_irotor = 0;
210 		if (fs->fs_magic == FS_UFS1_MAGIC) {
211 			newcg->cg_initediblk = 0;
212 			newcg->cg_niblk = cg->cg_niblk;
213 			if (cg->cg_irotor >= 0 &&
214 			    cg->cg_irotor < fs->fs_ipg)
215 				newcg->cg_irotor = cg->cg_irotor;
216 		} else {
217 			newcg->cg_ncyl = 0;
218 			if ((unsigned)cg->cg_initediblk > fs->fs_ipg)
219 				newcg->cg_initediblk = fs->fs_ipg;
220 			else
221 				newcg->cg_initediblk = cg->cg_initediblk;
222 			newcg->cg_ffs2_niblk = fs->fs_ipg;
223 			if (cg->cg_irotor >= 0 &&
224 			    cg->cg_irotor < newcg->cg_ffs2_niblk)
225 				newcg->cg_irotor = cg->cg_irotor;
226 		}
227 		memset(&newcg->cg_frsum[0], 0, sizeof newcg->cg_frsum);
228 		memset(cg_inosused(newcg), 0, (size_t)(mapsize));
229 		if (fs->fs_postblformat == FS_42POSTBLFMT)
230 			ocg->cg_magic = CG_MAGIC;
231 		j = fs->fs_ipg * c;
232 		for (i = 0; i < inostathead[c].il_numalloced; j++, i++) {
233 			switch (GET_ISTATE(j)) {
234 
235 			case USTATE:
236 				break;
237 
238 			case DSTATE:
239 			case DCLEAR:
240 			case DFOUND:
241 				newcg->cg_cs.cs_ndir++;
242 				/* FALLTHROUGH */
243 
244 			case FSTATE:
245 			case FCLEAR:
246 				newcg->cg_cs.cs_nifree--;
247 				setbit(cg_inosused(newcg), i);
248 				break;
249 
250 			default:
251 				if (j < ROOTINO)
252 					break;
253 				errexit("BAD STATE %d FOR INODE I=%llu\n",
254 				    GET_ISTATE(j), (unsigned long long)j);
255 			}
256 		}
257 		if (c == 0)
258 			for (i = 0; i < ROOTINO; i++) {
259 				setbit(cg_inosused(newcg), i);
260 				newcg->cg_cs.cs_nifree--;
261 			}
262 		for (i = 0, d = dbase;
263 		     d < dmax;
264 		     d += fs->fs_frag, i += fs->fs_frag) {
265 			frags = 0;
266 			for (j = 0; j < fs->fs_frag; j++) {
267 				if (testbmap(d + j))
268 					continue;
269 				setbit(cg_blksfree(newcg), i + j);
270 				frags++;
271 			}
272 			if (frags == fs->fs_frag) {
273 				newcg->cg_cs.cs_nbfree++;
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 (rewritecg) {
323 			memcpy(cg, newcg, (size_t)fs->fs_cgsize);
324 			cgdirty();
325 			continue;
326 		}
327 		if (memcmp(newcg, cg, basesize) &&
328 		    dofix(&idesc[2], "SUMMARY INFORMATION BAD")) {
329 			memcpy(cg, newcg, (size_t)basesize);
330 			cgdirty();
331 		}
332 		if (usedsoftdep) {
333 			for (i = 0; i < inomapsize; i++) {
334 				j = cg_inosused(newcg)[i];
335 				if ((cg_inosused(cg)[i] & j) == j)
336 					continue;
337 				for (k = 0; k < NBBY; k++) {
338 					if ((j & (1 << k)) == 0)
339 						continue;
340 					if (cg_inosused(cg)[i] & (1 << k))
341 						continue;
342 					pwarn("ALLOCATED INODE %lld MARKED FREE\n",
343 					      ((long long)c * fs->fs_ipg + i * 8) + k);
344 				}
345 			}
346 			for (i = 0; i < blkmapsize; i++) {
347 				j = cg_blksfree(cg)[i];
348 				if ((cg_blksfree(newcg)[i] & j) == j)
349 					continue;
350 				for (k = 0; k < NBBY; k++) {
351 					if ((j & (1 << k)) == 0)
352 						continue;
353 					if (cg_blksfree(newcg)[i] & (1 << k))
354 						continue;
355 					pwarn("ALLOCATED FRAG %lld MARKED FREE\n",
356 					      ((long long)c * fs->fs_fpg + i * 8) + k);
357 				}
358 			}
359 		}
360 		if (memcmp(cg_inosused(newcg), cg_inosused(cg),
361 			   mapsize) != 0 &&
362 		    dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) {
363 			memmove(cg_inosused(cg), cg_inosused(newcg),
364 				(size_t)mapsize);
365 			cgdirty();
366 		}
367 	}
368 	info_fn = NULL;
369 	if (fs->fs_postblformat == FS_42POSTBLFMT)
370 		fs->fs_nrpos = savednrpos;
371 
372 	sumsize = sizeof(cstotal) - sizeof(cstotal.cs_spare);
373 	if (memcmp(&cstotal, &fs->fs_cstotal, sumsize) != 0
374 	    && dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
375 		memcpy(&fs->fs_cstotal, &cstotal, sumsize);
376 		fs->fs_ronly = 0;
377 		fs->fs_fmod = 0;
378 		sbdirty();
379 	}
380 }
381