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