1 /* $OpenBSD: pass5.c,v 1.52 2024/09/15 07:14:58 jsg 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
pass5_info(char * buf,size_t buflen)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
pass5(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, 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 (memcmp(cg_inosused(newcg), cg_inosused(cg),
337 mapsize) != 0 &&
338 dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) {
339 memmove(cg_inosused(cg), cg_inosused(newcg),
340 (size_t)mapsize);
341 dirty(cgbp);
342 }
343 }
344 info_fn = NULL;
345 if (fs->fs_postblformat == FS_42POSTBLFMT)
346 fs->fs_nrpos = savednrpos;
347
348 sumsize = sizeof(cstotal) - sizeof(cstotal.cs_spare);
349 if (memcmp(&cstotal, &fs->fs_cstotal, sumsize) != 0
350 && dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
351 memcpy(&fs->fs_cstotal, &cstotal, sumsize);
352 fs->fs_ronly = 0;
353 fs->fs_fmod = 0;
354 sbdirty();
355 }
356 }
357