Merge branch 'vendor/FLEX'
[dragonfly.git] / sbin / fsck / pass5.c
1 /*
2  * Copyright (c) 1980, 1986, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
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.
20  *
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.
32  *
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  */
36
37 #include <sys/param.h>
38
39 #include <vfs/ufs/dinode.h>
40 #include <vfs/ufs/fs.h>
41
42 #include <err.h>
43 #include <string.h>
44
45 #include "fsck.h"
46
47 void
48 pass5(void)
49 {
50         int c, blk, frags, basesize, sumsize, mapsize, savednrpos = 0;
51         int inomapsize, blkmapsize;
52         struct fs *fs = &sblock;
53         struct cg *cg = &cgrp;
54         ufs_daddr_t dbase, dmax;
55         ufs_daddr_t d;
56         long i, j, k;
57         struct csum *cs;
58         struct csum cstotal;
59         struct inodesc idesc[3];
60         char buf[MAXBSIZE];
61         struct cg *newcg = (struct cg *)buf;
62         struct ocg *ocg = (struct ocg *)buf;
63
64         inoinfo(WINO)->ino_state = USTATE;
65         memset(newcg, 0, (size_t)fs->fs_cgsize);
66         newcg->cg_niblk = fs->fs_ipg;
67         if (cvtlevel >= 3) {
68                 if (fs->fs_maxcontig < 2 && fs->fs_contigsumsize > 0) {
69                         if (preen)
70                                 pwarn("DELETING CLUSTERING MAPS\n");
71                         if (preen || reply("DELETE CLUSTERING MAPS")) {
72                                 fs->fs_contigsumsize = 0;
73                                 doinglevel1 = 1;
74                                 sbdirty();
75                         }
76                 }
77                 if (fs->fs_maxcontig > 1) {
78                         char *doit = NULL;
79
80                         if (fs->fs_contigsumsize < 1) {
81                                 doit = "CREAT";
82                         } else if (fs->fs_contigsumsize < fs->fs_maxcontig &&
83                                    fs->fs_contigsumsize < FS_MAXCONTIG) {
84                                 doit = "EXPAND";
85                         }
86                         if (doit) {
87                                 i = fs->fs_contigsumsize;
88                                 fs->fs_contigsumsize =
89                                     MIN(fs->fs_maxcontig, FS_MAXCONTIG);
90                                 if (CGSIZE(fs) > fs->fs_bsize) {
91                                         pwarn("CANNOT %s CLUSTER MAPS\n", doit);
92                                         fs->fs_contigsumsize = i;
93                                 } else if (preen ||
94                                     reply("CREATE CLUSTER MAPS")) {
95                                         if (preen)
96                                                 pwarn("%sING CLUSTER MAPS\n",
97                                                     doit);
98                                         fs->fs_cgsize =
99                                             fragroundup(fs, CGSIZE(fs));
100                                         doinglevel1 = 1;
101                                         sbdirty();
102                                 }
103                         }
104                 }
105         }
106         switch ((int)fs->fs_postblformat) {
107
108         case FS_42POSTBLFMT:
109                 basesize = (char *)(&ocg->cg_btot[0]) -
110                     (char *)(&ocg->cg_firstfield);
111                 sumsize = &ocg->cg_iused[0] - (u_int8_t *)(&ocg->cg_btot[0]);
112                 mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] -
113                         (u_char *)&ocg->cg_iused[0];
114                 blkmapsize = howmany(fs->fs_fpg, NBBY);
115                 inomapsize = &ocg->cg_free[0] - (u_char *)&ocg->cg_iused[0];
116                 ocg->cg_magic = CG_MAGIC;
117                 savednrpos = fs->fs_nrpos;
118                 fs->fs_nrpos = 8;
119                 break;
120
121         case FS_DYNAMICPOSTBLFMT:
122                 newcg->cg_btotoff =
123                      &newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield);
124                 newcg->cg_boff =
125                     newcg->cg_btotoff + fs->fs_cpg * sizeof(int32_t);
126                 newcg->cg_iusedoff = newcg->cg_boff +
127                     fs->fs_cpg * fs->fs_nrpos * sizeof(u_int16_t);
128                 newcg->cg_freeoff =
129                     newcg->cg_iusedoff + howmany(fs->fs_ipg, NBBY);
130                 inomapsize = newcg->cg_freeoff - newcg->cg_iusedoff;
131                 newcg->cg_nextfreeoff = newcg->cg_freeoff +
132                     howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY);
133                 blkmapsize = newcg->cg_nextfreeoff - newcg->cg_freeoff;
134                 if (fs->fs_contigsumsize > 0) {
135                         newcg->cg_clustersumoff = newcg->cg_nextfreeoff -
136                             sizeof(u_int32_t);
137                         newcg->cg_clustersumoff =
138                             roundup(newcg->cg_clustersumoff, sizeof(u_int32_t));
139                         newcg->cg_clusteroff = newcg->cg_clustersumoff +
140                             (fs->fs_contigsumsize + 1) * sizeof(u_int32_t);
141                         newcg->cg_nextfreeoff = newcg->cg_clusteroff +
142                             howmany(fs->fs_cpg * fs->fs_spc / NSPB(fs), NBBY);
143                 }
144                 newcg->cg_magic = CG_MAGIC;
145                 basesize = &newcg->cg_space[0] -
146                     (u_char *)(&newcg->cg_firstfield);
147                 sumsize = newcg->cg_iusedoff - newcg->cg_btotoff;
148                 mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff;
149                 break;
150
151         default:
152                 inomapsize = blkmapsize = sumsize = 0;  /* keep lint happy */
153                 errx(EEXIT, "UNKNOWN ROTATIONAL TABLE FORMAT %d",
154                         fs->fs_postblformat);
155         }
156         memset(&idesc[0], 0, sizeof idesc);
157         for (i = 0; i < 3; i++) {
158                 idesc[i].id_type = ADDR;
159                 if (doinglevel2)
160                         idesc[i].id_fix = FIX;
161         }
162         memset(&cstotal, 0, sizeof(struct csum));
163         j = blknum(fs, fs->fs_size + fs->fs_frag - 1);
164         for (i = fs->fs_size; i < j; i++)
165                 setbmap(i);
166         for (c = 0; c < fs->fs_ncg; c++) {
167                 if (got_siginfo) {
168                         printf("%s: phase 5: cyl group %d of %d (%d%%)\n",
169                             cdevname, c, sblock.fs_ncg,
170                             c * 100 / sblock.fs_ncg);
171                         got_siginfo = 0;
172                 }
173                 getblk(&cgblk, cgtod(fs, c), fs->fs_cgsize);
174                 if (!cg_chkmagic(cg))
175                         pfatal("CG %d: BAD MAGIC NUMBER\n", c);
176                 dbase = cgbase(fs, c);
177                 dmax = dbase + fs->fs_fpg;
178                 if (dmax > fs->fs_size)
179                         dmax = fs->fs_size;
180                 newcg->cg_time = cg->cg_time;
181                 newcg->cg_cgx = c;
182                 if (c == fs->fs_ncg - 1)
183                         newcg->cg_ncyl = fs->fs_ncyl % fs->fs_cpg;
184                 else
185                         newcg->cg_ncyl = fs->fs_cpg;
186                 newcg->cg_ndblk = dmax - dbase;
187                 if (fs->fs_contigsumsize > 0)
188                         newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag;
189                 newcg->cg_cs.cs_ndir = 0;
190                 newcg->cg_cs.cs_nffree = 0;
191                 newcg->cg_cs.cs_nbfree = 0;
192                 newcg->cg_cs.cs_nifree = fs->fs_ipg;
193                 if ((cg->cg_rotor >= 0) && (cg->cg_rotor < newcg->cg_ndblk))
194                         newcg->cg_rotor = cg->cg_rotor;
195                 else
196                         newcg->cg_rotor = 0;
197                 if ((cg->cg_frotor >= 0) && (cg->cg_frotor < newcg->cg_ndblk))
198                         newcg->cg_frotor = cg->cg_frotor;
199                 else
200                         newcg->cg_frotor = 0;
201                 if ((cg->cg_irotor >= 0) && (cg->cg_irotor < newcg->cg_niblk))
202                         newcg->cg_irotor = cg->cg_irotor;
203                 else
204                         newcg->cg_irotor = 0;
205                 memset(&newcg->cg_frsum[0], 0, sizeof newcg->cg_frsum);
206                 memset(&cg_blktot(newcg)[0], 0,
207                       (size_t)(sumsize + mapsize));
208                 if (fs->fs_postblformat == FS_42POSTBLFMT)
209                         ocg->cg_magic = CG_MAGIC;
210                 j = fs->fs_ipg * c;
211                 for (i = 0; i < inostathead[c].il_numalloced; j++, i++) {
212                         switch (inoinfo(j)->ino_state) {
213
214                         case USTATE:
215                                 break;
216
217                         case DSTATE:
218                         case DCLEAR:
219                         case DFOUND:
220                                 newcg->cg_cs.cs_ndir++;
221                                 /* fall through */
222
223                         case FSTATE:
224                         case FCLEAR:
225                                 newcg->cg_cs.cs_nifree--;
226                                 setbit(cg_inosused(newcg), i);
227                                 break;
228
229                         default:
230                                 if (j < ROOTINO)
231                                         break;
232                                 errx(EEXIT, "BAD STATE %d FOR INODE I=%ld",
233                                     inoinfo(j)->ino_state, j);
234                         }
235                 }
236                 if (c == 0)
237                         for (i = 0; i < ROOTINO; i++) {
238                                 setbit(cg_inosused(newcg), i);
239                                 newcg->cg_cs.cs_nifree--;
240                         }
241                 for (i = 0, d = dbase;
242                      d < dmax;
243                      d += fs->fs_frag, i += fs->fs_frag) {
244                         frags = 0;
245                         for (j = 0; j < fs->fs_frag; j++) {
246                                 if (testbmap(d + j))
247                                         continue;
248                                 setbit(cg_blksfree(newcg), i + j);
249                                 frags++;
250                         }
251                         if (frags == fs->fs_frag) {
252                                 newcg->cg_cs.cs_nbfree++;
253                                 j = cbtocylno(fs, i);
254                                 cg_blktot(newcg)[j]++;
255                                 cg_blks(fs, newcg, j)[cbtorpos(fs, i)]++;
256                                 if (fs->fs_contigsumsize > 0)
257                                         setbit(cg_clustersfree(newcg),
258                                             i / fs->fs_frag);
259                         } else if (frags > 0) {
260                                 newcg->cg_cs.cs_nffree += frags;
261                                 blk = blkmap(fs, cg_blksfree(newcg), i);
262                                 ffs_fragacct(fs, blk, newcg->cg_frsum, 1);
263                         }
264                 }
265                 if (fs->fs_contigsumsize > 0) {
266                         int32_t *sump = cg_clustersum(newcg);
267                         u_char *mapp = cg_clustersfree(newcg);
268                         int map = *mapp++;
269                         int bit = 1;
270                         int run = 0;
271
272                         for (i = 0; i < newcg->cg_nclusterblks; i++) {
273                                 if ((map & bit) != 0) {
274                                         run++;
275                                 } else if (run != 0) {
276                                         if (run > fs->fs_contigsumsize)
277                                                 run = fs->fs_contigsumsize;
278                                         sump[run]++;
279                                         run = 0;
280                                 }
281                                 if ((i & (NBBY - 1)) != (NBBY - 1)) {
282                                         bit <<= 1;
283                                 } else {
284                                         map = *mapp++;
285                                         bit = 1;
286                                 }
287                         }
288                         if (run != 0) {
289                                 if (run > fs->fs_contigsumsize)
290                                         run = fs->fs_contigsumsize;
291                                 sump[run]++;
292                         }
293                 }
294                 cstotal.cs_nffree += newcg->cg_cs.cs_nffree;
295                 cstotal.cs_nbfree += newcg->cg_cs.cs_nbfree;
296                 cstotal.cs_nifree += newcg->cg_cs.cs_nifree;
297                 cstotal.cs_ndir += newcg->cg_cs.cs_ndir;
298                 cs = &fs->fs_cs(fs, c);
299                 if (memcmp(&newcg->cg_cs, cs, sizeof *cs) != 0 &&
300                     dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
301                         memmove(cs, &newcg->cg_cs, sizeof *cs);
302                         sbdirty();
303                 }
304                 if (doinglevel1) {
305                         memmove(cg, newcg, (size_t)fs->fs_cgsize);
306                         cgdirty();
307                         continue;
308                 }
309                 if ((memcmp(newcg, cg, basesize) != 0 ||
310                      memcmp(&cg_blktot(newcg)[0],
311                           &cg_blktot(cg)[0], sumsize) != 0) &&
312                     dofix(&idesc[2], "SUMMARY INFORMATION BAD")) {
313                         memmove(cg, newcg, (size_t)basesize);
314                         memmove(&cg_blktot(cg)[0],
315                                &cg_blktot(newcg)[0], (size_t)sumsize);
316                         cgdirty();
317                 }
318                 if (usedsoftdep) {
319                         for (i = 0; i < inomapsize; i++) {
320                                 j = cg_inosused(newcg)[i];
321                                 if ((cg_inosused(cg)[i] & j) == j)
322                                         continue;
323                                 for (k = 0; k < NBBY; k++) {
324                                         if ((j & (1 << k)) == 0)
325                                                 continue;
326                                         if (cg_inosused(cg)[i] & (1 << k))
327                                                 continue;
328                                         pwarn("ALLOCATED INODE %d MARKED FREE\n",
329                                             c * fs->fs_ipg + i * NBBY + k);
330                                 }
331                         }
332                         for (i = 0; i < blkmapsize; i++) {
333                                 j = cg_blksfree(cg)[i];
334                                 if ((cg_blksfree(newcg)[i] & j) == j)
335                                         continue;
336                                 for (k = 0; k < NBBY; k++) {
337                                         if ((j & (1 << k)) == 0)
338                                                 continue;
339                                         if (cg_blksfree(newcg)[i] & (1 << k))
340                                                 continue;
341                                         pwarn("ALLOCATED FRAG %d MARKED FREE\n",
342                                             c * fs->fs_fpg + i * NBBY + k);
343                                 }
344                         }
345                 }
346                 if (memcmp(cg_inosused(newcg), cg_inosused(cg), mapsize) != 0 &&
347                     dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) {
348                         memmove(cg_inosused(cg), cg_inosused(newcg),
349                               (size_t)mapsize);
350                         cgdirty();
351                 }
352         }
353         if (fs->fs_postblformat == FS_42POSTBLFMT)
354                 fs->fs_nrpos = savednrpos;
355         if (memcmp(&cstotal, &fs->fs_cstotal, sizeof *cs) != 0
356             && dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
357                 memmove(&fs->fs_cstotal, &cstotal, sizeof *cs);
358                 fs->fs_ronly = 0;
359                 fs->fs_fmod = 0;
360                 sbdirty();
361         }
362 }