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