7aa9107a2ab983467aa46ad52245661452e0d2a9
[openafs.git] / src / vfsck / pass5.c
1 /*
2  * Copyright (c) 1980, 1986 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17
18 #include <afsconfig.h>
19 #include <afs/param.h>
20
21
22 #define VICE
23 #include <sys/param.h>
24 #include <sys/time.h>
25 #ifdef  AFS_OSF_ENV
26 #include <sys/vnode.h>
27 #include <sys/mount.h>
28 #include <ufs/inode.h>
29 #include <ufs/fs.h>
30 #define _BSD
31 #define _KERNEL
32 #include <ufs/dir.h>
33 #undef  _KERNEL
34 #undef  _BSD
35 #include <stdio.h>
36 #else /* AFS_OSF_ENV */
37 #ifdef AFS_VFSINCL_ENV
38 #include <sys/vnode.h>
39 #ifdef    AFS_SUN5_ENV
40 #include <stdio.h>
41 #include <unistd.h>
42 #include <sys/fs/ufs_inode.h>
43 #include <sys/fs/ufs_fs.h>
44 #define _KERNEL
45 #include <sys/fs/ufs_fsdir.h>
46 #undef _KERNEL
47 #include <sys/fs/ufs_mount.h>
48 #else
49 #include <ufs/inode.h>
50 #include <ufs/fs.h>
51 #endif
52 #else /* AFS_VFSINCL_ENV */
53 #include <sys/inode.h>
54 #ifdef  AFS_HPUX_ENV
55 #include <ctype.h>
56 #define LONGFILENAMES   1
57 #include <sys/sysmacros.h>
58 #include <sys/ino.h>
59 #endif
60 #include <sys/fs.h>
61 #endif /* AFS_VFSINCL_ENV */
62 #endif /* AFS_OSF_ENV */
63 #include <afs/osi_inode.h>
64
65 #include "fsck.h"
66
67 #if     defined(AFS_SUN_ENV) || defined(AFS_OSF_ENV)
68 #define AFS_NEWCG_ENV
69 #else
70 #undef AFS_NEWCG_ENV
71 #endif
72
73 #ifndef AFS_NEWCG_ENV
74 /* define enough so this thing compiles! */
75 #define FS_42POSTBLFMT          1
76 #define FS_DYNAMICPOSTBLFMT     2
77 #endif /* AFS_NEWCG_ENV */
78
79 pass5()
80 {
81     int c, blk, frags, basesize, sumsize, mapsize, savednrpos;
82     struct fs *fs = &sblock;
83     struct cg *cg = &cgrp;
84     daddr_t dbase, dmax;
85     daddr_t d;
86     long i, j;
87     struct csum *cs;
88     time_t now;
89     struct csum cstotal;
90     struct inodesc idesc[3];
91     char buf[MAXBSIZE];
92     int postype;
93
94 #ifdef AFS_NEWCG_ENV
95     struct cg *newcg = (struct cg *)buf;
96     struct ocg *ocg = (struct ocg *)buf;
97 #else /* AFS_NEWCG_ENV */
98     /* don't bother with newcg format yet, most systems don't support it */
99     struct cg *newcg = (struct cg *)buf;
100     struct cg *ocg = (struct cg *)buf;
101 #endif /* AFS_NEWCG_ENV */
102
103     memset(newcg, 0, (int)fs->fs_cgsize);
104     newcg->cg_niblk = fs->fs_ipg;
105 #ifdef AFS_NEWCG_ENV
106     postype = (int)fs->fs_postblformat;
107 #else /* AFS_NEWCG_ENV */
108     postype = FS_42POSTBLFMT;
109 #endif /* AFS_NEWCG_ENV */
110     switch (postype) {
111
112     case FS_42POSTBLFMT:
113         basesize = (char *)(&ocg->cg_btot[0]) - (char *)(&ocg->cg_link);
114         sumsize = &ocg->cg_iused[0] - (char *)(&ocg->cg_btot[0]);
115         mapsize =
116             &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] -
117             (u_char *) & ocg->cg_iused[0];
118         ocg->cg_magic = CG_MAGIC;
119 #ifdef AFS_NEWCG_ENV
120         savednrpos = fs->fs_nrpos;
121         fs->fs_nrpos = 8;
122 #endif /* AFS_NEWCG_ENV */
123         break;
124
125 #ifdef AFS_NEWCG_ENV
126     case FS_DYNAMICPOSTBLFMT:
127         newcg->cg_btotoff =
128 #ifdef  __alpha
129             /* Matches decl in ufs/fs.h */
130             &newcg->cg_space[0] - (u_char *) (&newcg->cg_link[0]);
131 #else /* __alpha */
132             &newcg->cg_space[0] - (u_char *) (&newcg->cg_link);
133 #endif
134         newcg->cg_boff = newcg->cg_btotoff + fs->fs_cpg * sizeof(afs_int32);
135         newcg->cg_iusedoff =
136             newcg->cg_boff + fs->fs_cpg * fs->fs_nrpos * sizeof(short);
137         newcg->cg_freeoff = newcg->cg_iusedoff + howmany(fs->fs_ipg, NBBY);
138         newcg->cg_nextfreeoff =
139             newcg->cg_freeoff + howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs),
140                                         NBBY);
141         newcg->cg_magic = CG_MAGIC;
142 #ifdef  __alpha
143         /* Matches decl in ufs/fs.h */
144         basesize = &newcg->cg_space[0] - (u_char *) (&newcg->cg_link[0]);
145 #else /* __alpha */
146         basesize = &newcg->cg_space[0] - (u_char *) (&newcg->cg_link);
147 #endif
148         sumsize = newcg->cg_iusedoff - newcg->cg_btotoff;
149         mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff;
150         break;
151
152     default:
153         errexit("UNKNOWN ROTATIONAL TABLE FORMAT %d\n", fs->fs_postblformat);
154 #endif /* AFS_NEWCG_ENV */
155
156     }
157     memset(&idesc[0], 0, sizeof idesc);
158     for (i = 0; i < 3; i++)
159         idesc[i].id_type = ADDR;
160     memset(&cstotal, 0, sizeof(struct csum));
161     (void)time(&now);
162 #ifdef notdef
163     /* this is the original from UCB/McKusick, but it is clearly wrong.  It is
164      * rounding the # of fragments to the next 1024 (in our case, with a 1K/8K file system),
165      * while instead it should be rounding to the next block.
166      *
167      * In addition, we should be sure that we allocate enough space, but that seems to be
168      * ensured by the fact that the bitmap is rounded up to the nearest short, and that there
169      * are never more than 16 frags per block.
170      */
171     for (i = fs->fs_size; i < fragroundup(fs, fs->fs_size); i++)
172 #else
173     c = 1 << fs->fs_fragshift;  /* unit to which we want to round */
174     for (i = fs->fs_size; i < roundup(fs->fs_size, c); i++)
175 #endif
176         setbmap(i);
177     for (c = 0; c < fs->fs_ncg; c++) {
178         getblk(&cgblk, cgtod(fs, c), fs->fs_cgsize);
179 #ifdef AFS_NEWCG_ENV
180         if (!cg_chkmagic(cg))
181             pfatal("CG %d: BAD MAGIC NUMBER\n", c);
182 #else /* AFS_NEWCG_ENV */
183         if (cg->cg_magic != CG_MAGIC)
184             pfatal("CG %d: BAD MAGIC NUMBER\n", c);
185 #endif /* AFS_NEWCG_ENV */
186         dbase = cgbase(fs, c);
187         dmax = dbase + fs->fs_fpg;
188         if (dmax > fs->fs_size)
189             dmax = fs->fs_size;
190         if (now > cg->cg_time)
191             newcg->cg_time = cg->cg_time;
192         else
193             newcg->cg_time = now;
194         newcg->cg_cgx = c;
195         if (c == fs->fs_ncg - 1)
196             newcg->cg_ncyl = fs->fs_ncyl % fs->fs_cpg;
197         else
198             newcg->cg_ncyl = fs->fs_cpg;
199         newcg->cg_ndblk = dmax - dbase;
200         newcg->cg_cs.cs_ndir = 0;
201         newcg->cg_cs.cs_nffree = 0;
202         newcg->cg_cs.cs_nbfree = 0;
203         newcg->cg_cs.cs_nifree = fs->fs_ipg;
204         if (cg->cg_rotor < newcg->cg_ndblk)
205             newcg->cg_rotor = cg->cg_rotor;
206         else
207             newcg->cg_rotor = 0;
208         if (cg->cg_frotor < newcg->cg_ndblk)
209             newcg->cg_frotor = cg->cg_frotor;
210         else
211             newcg->cg_frotor = 0;
212         if (cg->cg_irotor < newcg->cg_niblk)
213             newcg->cg_irotor = cg->cg_irotor;
214         else
215             newcg->cg_irotor = 0;
216         memset(&newcg->cg_frsum[0], 0, sizeof newcg->cg_frsum);
217 #ifdef AFS_NEWCG_ENV
218         memset(&cg_blktot(newcg)[0], 0, sumsize + mapsize);
219 #else /* AFS_NEWCG_ENV */
220         memset(newcg->cg_btot, 0, sizeof(newcg->cg_btot));
221         memset(newcg->cg_b, 0, sizeof(newcg->cg_b));
222         memset(newcg->cg_iused, 0, sizeof(newcg->cg_iused));
223         memset(newcg->cg_free, 0, howmany(fs->fs_fpg, NBBY));
224 #endif /* AFS_NEWCG_ENV */
225 #ifdef AFS_NEWCG_ENV
226         if (fs->fs_postblformat == FS_42POSTBLFMT)
227             ocg->cg_magic = CG_MAGIC;
228 #endif /* AFS_NEWCG_ENV */
229         j = fs->fs_ipg * c;
230         for (i = 0; i < fs->fs_ipg; j++, i++) {
231 #if defined(ACLS) && defined(AFS_HPUX_ENV)
232             switch (statemap[j] & STATE) {
233 #else
234             switch (statemap[j]) {
235 #endif
236             case USTATE:
237                 break;
238
239             case DSTATE:
240             case DCLEAR:
241             case DFOUND:
242                 newcg->cg_cs.cs_ndir++;
243                 /* fall through */
244
245 #ifdef VICE
246             case VSTATE:
247 #endif /* VICE */
248             case FSTATE:
249             case FCLEAR:
250                 newcg->cg_cs.cs_nifree--;
251 #ifdef AFS_NEWCG_ENV
252                 setbit(cg_inosused(newcg), i);
253 #else
254                 setbit(newcg->cg_iused, i);
255 #endif /* AFS_NEWCG_ENV */
256                 break;
257
258 #if defined(ACLS) && defined(AFS_HPUX_ENV)
259                 /* hpux has more dynamic states (CSTATE, CRSTATE) */
260             case CSTATE:
261             case CRSTATE:
262                 break;
263 #endif
264             default:
265                 if (j < ROOTINO)
266                     break;
267                 errexit("BAD STATE %d FOR INODE I=%d", statemap[j], j);
268             }
269         }
270         if (c == 0)
271             for (i = 0; i < ROOTINO; i++) {
272 #ifdef AFS_NEWCG_ENV
273                 setbit(cg_inosused(newcg), i);
274 #else
275                 setbit(newcg->cg_iused, i);
276 #endif /* AFS_NEWCG_ENV */
277                 newcg->cg_cs.cs_nifree--;
278             }
279         for (i = 0, d = dbase; d < dmax; d += fs->fs_frag, i += fs->fs_frag) {
280             frags = 0;
281             for (j = 0; j < fs->fs_frag; j++) {
282                 if (testbmap(d + j))
283                     continue;
284 #ifdef AFS_NEWCG_ENV
285                 setbit(cg_blksfree(newcg), i + j);
286 #else /* AFS_NEWCG_ENV */
287                 setbit(newcg->cg_free, i + j);
288 #endif /* AFS_NEWCG_ENV */
289                 frags++;
290             }
291             if (frags == fs->fs_frag) {
292                 newcg->cg_cs.cs_nbfree++;
293                 j = cbtocylno(fs, i);
294 #ifdef AFS_NEWCG_ENV
295                 cg_blktot(newcg)[j]++;
296                 cg_blks(fs, newcg, j)[cbtorpos(fs, i)]++;
297 #else /* AFS_NEWCG_ENV */
298                 newcg->cg_btot[j]++;
299                 newcg->cg_b[j][cbtorpos(fs, i)]++;
300 #endif /* AFS_NEWCG_ENV */
301             } else if (frags > 0) {
302                 newcg->cg_cs.cs_nffree += frags;
303 #ifdef AFS_NEWCG_ENV
304                 blk = blkmap(fs, cg_blksfree(newcg), i);
305 #else /* AFS_NEWCG_ENV */
306                 blk = blkmap(fs, newcg->cg_free, i);
307 #endif /* AFS_NEWCG_ENV */
308                 fragacct(fs, blk, newcg->cg_frsum, 1);
309             }
310         }
311         cstotal.cs_nffree += newcg->cg_cs.cs_nffree;
312         cstotal.cs_nbfree += newcg->cg_cs.cs_nbfree;
313         cstotal.cs_nifree += newcg->cg_cs.cs_nifree;
314         cstotal.cs_ndir += newcg->cg_cs.cs_ndir;
315         cs = &fs->fs_cs(fs, c);
316         if (memcmp((char *)&newcg->cg_cs, (char *)cs, sizeof *cs) != 0
317             && dofix(&idesc[0],
318                      "FREE BLK COUNT(S) WRONG IN CYL GROUP (SUPERBLK)")) {
319             memcpy((char *)cs, (char *)&newcg->cg_cs, sizeof *cs);
320             sbdirty();
321         }
322 #ifdef AFS_NEWCG_ENV
323         if (cvtflag) {
324             memcpy((char *)cg, (char *)newcg, (int)fs->fs_cgsize);
325             cgdirty();
326             continue;
327         }
328 #endif /* AFS_NEWCG_ENV */
329 #ifdef AFS_NEWCG_ENV
330         if (memcmp(cg_inosused(newcg), cg_inosused(cg), mapsize) != 0
331             && dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) {
332             memcpy(cg_inosused(cg), cg_inosused(newcg), mapsize);
333             cgdirty();
334         }
335 #else /* AFS_NEWCG_ENV */
336         if (memcmp(newcg->cg_iused, cg->cg_iused, mapsize) != 0
337             && dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) {
338             memcpy(cg->cg_iused, newcg->cg_iused, mapsize);
339             cgdirty();
340         }
341 #endif /* AFS_NEWCG_ENV */
342         if ((memcmp((char *)newcg, (char *)cg, basesize) != 0 ||
343 #ifdef AFS_NEWCG_ENV
344              memcmp((char *)&cg_blktot(newcg)[0], (char *)&cg_blktot(cg)[0],
345                     sumsize) != 0) &&
346 #else /* AFS_NEWCG_ENV */
347              memcmp((char *)newcg->cg_btot, (char *)cg->cg_btot,
348                     sumsize) != 0) &&
349 #endif /* AFS_NEWCG_ENV */
350             dofix(&idesc[2], "SUMMARY INFORMATION BAD")) {
351 #ifdef AFS_NEWCG_ENV
352             memcpy((char *)cg, (char *)newcg, basesize);
353             memcpy((char *)&cg_blktot(cg)[0], (char *)&cg_blktot(newcg)[0],
354                    sumsize);
355 #else /* AFS_NEWCG_ENV */
356             memcpy((char *)cg, (char *)newcg, basesize);
357             memcpy((char *)cg->cg_btot, (char *)newcg->cg_btot, sumsize);
358 #endif /* AFS_NEWCG_ENV */
359             cgdirty();
360         }
361     }
362 #ifdef AFS_NEWCG_ENV
363     if (fs->fs_postblformat == FS_42POSTBLFMT)
364         fs->fs_nrpos = savednrpos;
365 #endif /* AFS_NEWCG_ENV */
366     if (memcmp((char *)&cstotal, (char *)&fs->fs_cstotal, sizeof *cs) != 0
367         && dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
368         memcpy((char *)&fs->fs_cstotal, (char *)&cstotal, sizeof *cs);
369         fs->fs_ronly = 0;
370         sbfine(fs);
371         sbdirty();
372     }
373 }
374
375 /* returns true if sbdirty should be called */
376 sbfine(fs)
377      struct fs *fs;
378 {
379     int rcode;
380     rcode = 0;
381     if (fs->fs_fmod != 0) {
382         fs->fs_fmod = 0;
383         rcode = 1;
384     }
385     return rcode;
386 }