Bring in a transport-independent RPC (TI-RPC).
[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  * $DragonFly: src/sbin/fsck/pass5.c,v 1.5 2005/11/06 12:13:53 swildner Exp $
36  */
37
38 #include <sys/param.h>
39
40 #include <vfs/ufs/dinode.h>
41 #include <vfs/ufs/fs.h>
42
43 #include <err.h>
44 #include <string.h>
45
46 #include "fsck.h"
47
48 void
49 pass5(void)
50 {
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;
64
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();
76                         }
77                 }
78                 if (fs->fs_maxcontig > 1) {
79                         char *doit = 0;
80
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";
86                         }
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();
103                                 }
104                         }
105                 }
106         }
107         switch ((int)fs->fs_postblformat) {
108
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;
121
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);
144                 }
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;
151
152         default:
153                 inomapsize = blkmapsize = sumsize = 0;  /* keep lint happy */
154                 errx(EEXIT, "UNKNOWN ROTATIONAL TABLE FORMAT %d",
155                         fs->fs_postblformat);
156         }
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;
162         }
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;
173                 }
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) {
214
215                         case USTATE:
216                                 break;
217
218                         case DSTATE:
219                         case DCLEAR:
220                         case DFOUND:
221                                 newcg->cg_cs.cs_ndir++;
222                                 /* fall through */
223
224                         case FSTATE:
225                         case FCLEAR:
226                                 newcg->cg_cs.cs_nifree--;
227                                 setbit(cg_inosused(newcg), i);
228                                 break;
229
230                         default:
231                                 if (j < ROOTINO)
232                                         break;
233                                 errx(EEXIT, "BAD STATE %d FOR INODE I=%ld",
234                                     inoinfo(j)->ino_state, j);
235                         }
236                 }
237                 if (c == 0)
238                         for (i = 0; i < ROOTINO; i++) {
239                                 setbit(cg_inosused(newcg), i);
240                                 newcg->cg_cs.cs_nifree--;
241                         }
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++;
251                         }
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);
264                         }
265                 }
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;
272
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;
281                                 }
282                                 if ((i & (NBBY - 1)) != (NBBY - 1)) {
283                                         bit <<= 1;
284                                 } else {
285                                         map = *mapp++;
286                                         bit = 1;
287                                 }
288                         }
289                         if (run != 0) {
290                                 if (run > fs->fs_contigsumsize)
291                                         run = fs->fs_contigsumsize;
292                                 sump[run]++;
293                         }
294                 }
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();
304                 }
305                 if (doinglevel1) {
306                         memmove(cg, newcg, (size_t)fs->fs_cgsize);
307                         cgdirty();
308                         continue;
309                 }
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();
318                 }
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);
331                                 }
332                         }
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);
344                                 }
345                         }
346                 }
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();
352                 }
353         }
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();
362         }
363 }