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