xref: /openbsd/sbin/fsck_ffs/pass5.c (revision 09467b48)
1 /*	$OpenBSD: pass5.c,v 1.50 2020/07/13 06:52:53 otto 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 u_int info_cg;
52 static u_int info_maxcg;
53 
54 static int
55 pass5_info(char *buf, size_t buflen)
56 {
57 	return (snprintf(buf, buflen, "phase 5, cg %u/%u",
58 	    info_cg, info_maxcg) > 0);
59 }
60 
61 void
62 pass5(void)
63 {
64 	int blk, frags, basesize, sumsize, mapsize, savednrpos=0;
65 	u_int c;
66 	int inomapsize, blkmapsize;
67 	struct fs *fs = &sblock;
68 	daddr_t dbase, dmax;
69 	daddr_t d;
70 	long i, k, rewritecg = 0;
71 	ino_t j;
72 	struct csum *cs;
73 	struct csum_total cstotal;
74 	struct inodesc idesc[3];
75 	char buf[MAXBSIZE];
76 	struct cg *newcg = (struct cg *)buf;
77 	struct ocg *ocg = (struct ocg *)buf;
78 	struct cg *cg;
79 	struct bufarea *cgbp;
80 
81 	memset(newcg, 0, (size_t)fs->fs_cgsize);
82 	if (cvtlevel >= 3) {
83 		if (fs->fs_maxcontig < 2 && fs->fs_contigsumsize > 0) {
84 			if (preen)
85 				pwarn("DELETING CLUSTERING MAPS\n");
86 			if (preen || reply("DELETE CLUSTERING MAPS")) {
87 				fs->fs_contigsumsize = 0;
88 				rewritecg = 1;
89 				sbdirty();
90 			}
91 		}
92 		if (fs->fs_maxcontig > 1) {
93 			char *doit = 0;
94 
95 			if (fs->fs_contigsumsize < 1) {
96 				doit = "CREAT";
97 			} else if (fs->fs_contigsumsize < fs->fs_maxcontig &&
98 				   fs->fs_contigsumsize < FS_MAXCONTIG) {
99 				doit = "EXPAND";
100 			}
101 			if (doit) {
102 				i = fs->fs_contigsumsize;
103 				fs->fs_contigsumsize =
104 				    MINIMUM(fs->fs_maxcontig, FS_MAXCONTIG);
105 				if (CGSIZE(fs) > fs->fs_bsize) {
106 					pwarn("CANNOT %s CLUSTER MAPS\n", doit);
107 					fs->fs_contigsumsize = i;
108 				} else if (preen ||
109 				    reply("CREATE CLUSTER MAPS")) {
110 					if (preen)
111 						pwarn("%sING CLUSTER MAPS\n",
112 						    doit);
113 					fs->fs_cgsize =
114 					    fragroundup(fs, CGSIZE(fs));
115 					rewritecg = 1;
116 					sbdirty();
117 				}
118 			}
119 		}
120 	}
121 	switch ((int)fs->fs_postblformat) {
122 
123 	case FS_42POSTBLFMT:
124 		basesize = (char *)(&ocg->cg_btot[0]) -
125 		    (char *)(&ocg->cg_firstfield);
126 		sumsize = &ocg->cg_iused[0] - (u_int8_t *)(&ocg->cg_btot[0]);
127 		mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] -
128 			(u_char *)&ocg->cg_iused[0];
129 		blkmapsize = howmany(fs->fs_fpg, NBBY);
130 		inomapsize = sizeof(ocg->cg_iused);
131 		ocg->cg_magic = CG_MAGIC;
132 		savednrpos = fs->fs_nrpos;
133 		fs->fs_nrpos = 8;
134 		break;
135 
136 	case FS_DYNAMICPOSTBLFMT:
137 		if (sblock.fs_magic == FS_UFS2_MAGIC) {
138 			newcg->cg_iusedoff = sizeof(struct cg);
139 		} else {
140 			newcg->cg_btotoff = sizeof(struct cg);
141 			newcg->cg_boff = newcg->cg_btotoff +
142 			    fs->fs_cpg * sizeof(int32_t);
143 			newcg->cg_iusedoff = newcg->cg_boff + fs->fs_cpg *
144 			    fs->fs_nrpos * sizeof(int16_t);
145 		}
146 		inomapsize = howmany(fs->fs_ipg, CHAR_BIT);
147 		newcg->cg_freeoff = newcg->cg_iusedoff + inomapsize;
148 		blkmapsize = howmany(fs->fs_fpg, CHAR_BIT);
149 		newcg->cg_nextfreeoff = newcg->cg_freeoff + blkmapsize;
150 		if (fs->fs_contigsumsize > 0) {
151 			newcg->cg_clustersumoff = newcg->cg_nextfreeoff -
152 			    sizeof(int32_t);
153 			newcg->cg_clustersumoff =
154 			    roundup(newcg->cg_clustersumoff, sizeof(int32_t));
155 			newcg->cg_clusteroff = newcg->cg_clustersumoff +
156 			    (fs->fs_contigsumsize + 1) * sizeof(int32_t);
157 			newcg->cg_nextfreeoff = newcg->cg_clusteroff +
158 			    howmany(fragstoblks(fs, fs->fs_fpg), CHAR_BIT);
159 		}
160 		newcg->cg_magic = CG_MAGIC;
161 		basesize = sizeof(struct cg);
162 		sumsize = newcg->cg_iusedoff - newcg->cg_btotoff;
163 		mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff;
164 		break;
165 
166 	default:
167 		inomapsize = blkmapsize = sumsize = 0;
168 		errexit("UNKNOWN ROTATIONAL TABLE FORMAT %d\n",
169 			fs->fs_postblformat);
170 	}
171 	memset(&idesc[0], 0, sizeof idesc);
172 	for (i = 0; i < 3; i++)
173 		idesc[i].id_type = ADDR;
174 	memset(&cstotal, 0, sizeof(struct csum_total));
175 	dmax = blknum(fs, fs->fs_size + fs->fs_frag - 1);
176 	for (d = fs->fs_size; d < dmax; d++)
177 		setbmap(d);
178 	info_cg = 0;
179 	info_maxcg = fs->fs_ncg;
180 	info_fn = pass5_info;
181 	for (c = 0; c < fs->fs_ncg; c++) {
182 		info_cg = c;
183 		cgbp = cglookup(c);
184 		cg = cgbp->b_un.b_cg;
185 		if (!cg_chkmagic(cg))
186 			pfatal("CG %u: BAD MAGIC NUMBER\n", c);
187 		dbase = cgbase(fs, c);
188 		dmax = dbase + fs->fs_fpg;
189 		if (dmax > fs->fs_size)
190 			dmax = fs->fs_size;
191 		newcg->cg_time = cg->cg_time;
192 		newcg->cg_ffs2_time = cg->cg_ffs2_time;
193 		newcg->cg_cgx = c;
194 		if (c == fs->fs_ncg - 1)
195 			newcg->cg_ncyl = fs->fs_ncyl % fs->fs_cpg;
196 		else
197 			newcg->cg_ncyl = fs->fs_cpg;
198 		newcg->cg_ndblk = dmax - dbase;
199 		if (fs->fs_contigsumsize > 0)
200 			newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag;
201 		newcg->cg_cs.cs_ndir = 0;
202 		newcg->cg_cs.cs_nffree = 0;
203 		newcg->cg_cs.cs_nbfree = 0;
204 		newcg->cg_cs.cs_nifree = fs->fs_ipg;
205 		if (cg->cg_rotor < newcg->cg_ndblk)
206 			newcg->cg_rotor = cg->cg_rotor;
207 		else
208 			newcg->cg_rotor = 0;
209 		if (cg->cg_frotor >= 0 && cg->cg_frotor < newcg->cg_ndblk)
210 			newcg->cg_frotor = cg->cg_frotor;
211 		else
212 			newcg->cg_frotor = 0;
213 		newcg->cg_irotor = 0;
214 		if (fs->fs_magic == FS_UFS1_MAGIC) {
215 			newcg->cg_initediblk = 0;
216 			newcg->cg_niblk = cg->cg_niblk;
217 			if (cg->cg_irotor >= 0 &&
218 			    cg->cg_irotor < fs->fs_ipg)
219 				newcg->cg_irotor = cg->cg_irotor;
220 		} else {
221 			newcg->cg_ncyl = 0;
222 			if (cg->cg_initediblk > fs->fs_ipg)
223 				newcg->cg_initediblk = fs->fs_ipg;
224 			else
225 				newcg->cg_initediblk = cg->cg_initediblk;
226 			newcg->cg_ffs2_niblk = fs->fs_ipg;
227 			if (cg->cg_irotor >= 0 &&
228 			    cg->cg_irotor < newcg->cg_ffs2_niblk)
229 				newcg->cg_irotor = cg->cg_irotor;
230 		}
231 		memset(&newcg->cg_frsum[0], 0, sizeof newcg->cg_frsum);
232 		memset(cg_inosused(newcg), 0, (size_t)(mapsize));
233 		if (fs->fs_postblformat == FS_42POSTBLFMT)
234 			ocg->cg_magic = CG_MAGIC;
235 		j = fs->fs_ipg * c;
236 		for (i = 0; i < inostathead[c].il_numalloced; j++, i++) {
237 			switch (GET_ISTATE(j)) {
238 
239 			case USTATE:
240 				break;
241 
242 			case DSTATE:
243 			case DCLEAR:
244 			case DFOUND:
245 				newcg->cg_cs.cs_ndir++;
246 				/* FALLTHROUGH */
247 
248 			case FSTATE:
249 			case FCLEAR:
250 				newcg->cg_cs.cs_nifree--;
251 				setbit(cg_inosused(newcg), i);
252 				break;
253 
254 			default:
255 				if (j < ROOTINO)
256 					break;
257 				errexit("BAD STATE %d FOR INODE I=%llu\n",
258 				    GET_ISTATE(j), (unsigned long long)j);
259 			}
260 		}
261 		if (c == 0)
262 			for (i = 0; i < ROOTINO; i++) {
263 				setbit(cg_inosused(newcg), i);
264 				newcg->cg_cs.cs_nifree--;
265 			}
266 		for (i = 0, d = dbase;
267 		     d < dmax;
268 		     d += fs->fs_frag, i += fs->fs_frag) {
269 			frags = 0;
270 			for (j = 0; j < fs->fs_frag; j++) {
271 				if (testbmap(d + j))
272 					continue;
273 				setbit(cg_blksfree(newcg), i + j);
274 				frags++;
275 			}
276 			if (frags == fs->fs_frag) {
277 				newcg->cg_cs.cs_nbfree++;
278 				if (fs->fs_contigsumsize > 0)
279 					setbit(cg_clustersfree(newcg),
280 					    i / fs->fs_frag);
281 			} else if (frags > 0) {
282 				newcg->cg_cs.cs_nffree += frags;
283 				blk = blkmap(fs, cg_blksfree(newcg), i);
284 				ffs_fragacct(fs, blk, newcg->cg_frsum, 1);
285 			}
286 		}
287 		if (fs->fs_contigsumsize > 0) {
288 			int32_t *sump = cg_clustersum(newcg);
289 			u_char *mapp = cg_clustersfree(newcg);
290 			int map = *mapp++;
291 			int bit = 1;
292 			int run = 0;
293 
294 			for (i = 0; i < newcg->cg_nclusterblks; i++) {
295 				if ((map & bit) != 0) {
296 					run++;
297 				} else if (run != 0) {
298 					if (run > fs->fs_contigsumsize)
299 						run = fs->fs_contigsumsize;
300 					sump[run]++;
301 					run = 0;
302 				}
303 				if ((i & (NBBY - 1)) != (NBBY - 1)) {
304 					bit <<= 1;
305 				} else {
306 					map = *mapp++;
307 					bit = 1;
308 				}
309 			}
310 			if (run != 0) {
311 				if (run > fs->fs_contigsumsize)
312 					run = fs->fs_contigsumsize;
313 				sump[run]++;
314 			}
315 		}
316 		cstotal.cs_nffree += newcg->cg_cs.cs_nffree;
317 		cstotal.cs_nbfree += newcg->cg_cs.cs_nbfree;
318 		cstotal.cs_nifree += newcg->cg_cs.cs_nifree;
319 		cstotal.cs_ndir += newcg->cg_cs.cs_ndir;
320 		cs = &fs->fs_cs(fs, c);
321 		if (memcmp(&newcg->cg_cs, cs, sizeof *cs) != 0 &&
322 		    dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
323 			memcpy(cs, &newcg->cg_cs, sizeof *cs);
324 			sbdirty();
325 		}
326 		if (rewritecg) {
327 			memcpy(cg, newcg, (size_t)fs->fs_cgsize);
328 			dirty(cgbp);
329 			continue;
330 		}
331 		if (memcmp(newcg, cg, basesize) &&
332 		    dofix(&idesc[2], "SUMMARY INFORMATION BAD")) {
333 			memcpy(cg, newcg, (size_t)basesize);
334 			dirty(cgbp);
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 %llu MARKED FREE\n",
347 					      ((ino_t)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_blksfree(newcg)[i] & (1 << k))
358 						continue;
359 					pwarn("ALLOCATED FRAG %lld MARKED FREE\n",
360 					      ((long long)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 			dirty(cgbp);
370 		}
371 	}
372 	info_fn = NULL;
373 	if (fs->fs_postblformat == FS_42POSTBLFMT)
374 		fs->fs_nrpos = savednrpos;
375 
376 	sumsize = sizeof(cstotal) - sizeof(cstotal.cs_spare);
377 	if (memcmp(&cstotal, &fs->fs_cstotal, sumsize) != 0
378 	    && dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
379 		memcpy(&fs->fs_cstotal, &cstotal, sumsize);
380 		fs->fs_ronly = 0;
381 		fs->fs_fmod = 0;
382 		sbdirty();
383 	}
384 }
385