1 /* $NetBSD: pass5.c,v 1.47 2006/11/14 21:01:46 apb Exp $ */
4 * Copyright (c) 1980, 1986, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)pass5.c 8.9 (Berkeley) 4/28/95";
37 __RCSID("$NetBSD: pass5.c,v 1.47 2006/11/14 21:01:46 apb Exp $");
41 #include <sys/param.h>
44 #include <ufs/ufs/dinode.h>
45 #include <ufs/ffs/fs.h>
46 #include <ufs/ffs/ffs_extern.h>
47 #include <ufs/ufs/ufs_bswap.h>
57 void print_bmap(u_char
*,u_int32_t
);
62 int c
, blk
, frags
, basesize
, sumsize
, mapsize
, cssize
;
63 int inomapsize
, blkmapsize
;
64 struct fs
*fs
= sblock
;
69 struct csum_total cstotal
;
70 struct inodesc idesc
[4];
72 struct cg
*newcg
= (struct cg
*)buf
;
73 struct ocg
*ocg
= (struct ocg
*)buf
;
74 struct cg
*cg
= cgrp
, *ncg
;
78 inoinfo(WINO
)->ino_state
= USTATE
;
79 memset(newcg
, 0, (size_t)fs
->fs_cgsize
);
80 newcg
->cg_niblk
= fs
->fs_ipg
;
82 if (fs
->fs_maxcontig
< 2 && fs
->fs_contigsumsize
> 0) {
84 pwarn("DELETING CLUSTERING MAPS\n");
85 if (preen
|| reply("DELETE CLUSTERING MAPS")) {
86 fs
->fs_contigsumsize
= 0;
91 if (fs
->fs_maxcontig
> 1) {
92 const char *doit
= NULL
;
94 if (fs
->fs_contigsumsize
< 1) {
96 } else if (fs
->fs_contigsumsize
< fs
->fs_maxcontig
&&
97 fs
->fs_contigsumsize
< FS_MAXCONTIG
) {
101 i
= fs
->fs_contigsumsize
;
102 fs
->fs_contigsumsize
=
103 MIN(fs
->fs_maxcontig
, FS_MAXCONTIG
);
104 if (CGSIZE(fs
) > fs
->fs_bsize
) {
105 pwarn("CANNOT %s CLUSTER MAPS\n", doit
);
106 fs
->fs_contigsumsize
= i
;
108 reply("CREATE CLUSTER MAPS")) {
110 pwarn("%sING CLUSTER MAPS\n",
112 ncgsize
= fragroundup(fs
, CGSIZE(fs
));
113 ncg
= realloc(cgrp
, ncgsize
);
116 "cannot reallocate cg space");
118 fs
->fs_cgsize
= ncgsize
;
125 basesize
= &newcg
->cg_space
[0] - (u_char
*)(&newcg
->cg_firstfield
);
126 cssize
= (u_char
*)&cstotal
.cs_spare
[0] - (u_char
*)&cstotal
.cs_ndir
;
129 newcg
->cg_iusedoff
= basesize
;
132 * We reserve the space for the old rotation summary
133 * tables for the benefit of old kernels, but do not
134 * maintain them in modern kernels. In time, they can
137 newcg
->cg_old_btotoff
= basesize
;
138 newcg
->cg_old_boff
= newcg
->cg_old_btotoff
+
139 fs
->fs_old_cpg
* sizeof(int32_t);
140 newcg
->cg_iusedoff
= newcg
->cg_old_boff
+
141 fs
->fs_old_cpg
* fs
->fs_old_nrpos
* sizeof(u_int16_t
);
142 memset(&newcg
->cg_space
[0], 0, newcg
->cg_iusedoff
- basesize
);
144 inomapsize
= howmany(fs
->fs_ipg
, CHAR_BIT
);
145 newcg
->cg_freeoff
= newcg
->cg_iusedoff
+ inomapsize
;
146 blkmapsize
= howmany(fs
->fs_fpg
, CHAR_BIT
);
147 newcg
->cg_nextfreeoff
= newcg
->cg_freeoff
+ blkmapsize
;
148 if (fs
->fs_contigsumsize
> 0) {
149 newcg
->cg_clustersumoff
= newcg
->cg_nextfreeoff
-
152 /* Apple PR2216969 gives rationale for this change.
153 * I believe they were mistaken, but we need to
154 * duplicate it for compatibility. -- dbj@NetBSD.org
156 newcg
->cg_clustersumoff
+= sizeof(u_int32_t
);
158 newcg
->cg_clustersumoff
=
159 roundup(newcg
->cg_clustersumoff
, sizeof(u_int32_t
));
160 newcg
->cg_clusteroff
= newcg
->cg_clustersumoff
+
161 (fs
->fs_contigsumsize
+ 1) * sizeof(u_int32_t
);
162 newcg
->cg_nextfreeoff
= newcg
->cg_clusteroff
+
163 howmany(fragstoblks(fs
, fs
->fs_fpg
), CHAR_BIT
);
165 newcg
->cg_magic
= CG_MAGIC
;
166 mapsize
= newcg
->cg_nextfreeoff
- newcg
->cg_iusedoff
;
167 if (!is_ufs2
&& ((fs
->fs_old_flags
& FS_FLAGS_UPDATED
) == 0)) {
168 switch ((int)fs
->fs_old_postblformat
) {
171 basesize
= (char *)(&ocg
->cg_btot
[0]) -
172 (char *)(&ocg
->cg_firstfield
);
173 sumsize
= &ocg
->cg_iused
[0] - (u_int8_t
*)(&ocg
->cg_btot
[0]);
174 mapsize
= &ocg
->cg_free
[howmany(fs
->fs_fpg
, NBBY
)] -
175 (u_char
*)&ocg
->cg_iused
[0];
176 blkmapsize
= howmany(fs
->fs_fpg
, NBBY
);
177 inomapsize
= &ocg
->cg_free
[0] - (u_char
*)&ocg
->cg_iused
[0];
178 ocg
->cg_magic
= CG_MAGIC
;
182 case FS_DYNAMICPOSTBLFMT
:
183 sumsize
= newcg
->cg_iusedoff
- newcg
->cg_old_btotoff
;
187 errexit("UNKNOWN ROTATIONAL TABLE FORMAT %d",
188 fs
->fs_old_postblformat
);
191 memset(&idesc
[0], 0, sizeof idesc
);
192 for (i
= 0; i
< 4; i
++) {
193 idesc
[i
].id_type
= ADDR
;
194 if (!is_ufs2
&& doinglevel2
)
195 idesc
[i
].id_fix
= FIX
;
197 memset(&cstotal
, 0, sizeof(struct csum_total
));
198 dmax
= blknum(fs
, fs
->fs_size
+ fs
->fs_frag
- 1);
199 for (d
= fs
->fs_size
; d
< dmax
; d
++)
201 for (c
= 0; c
< fs
->fs_ncg
; c
++) {
204 "%s: phase 5: cyl group %d of %d (%d%%)\n",
205 cdevname(), c
, fs
->fs_ncg
,
206 c
* 100 / fs
->fs_ncg
);
210 progress_bar(cdevname(), preen
? NULL
: "phase 5",
212 #endif /* PROGRESS */
213 getblk(&cgblk
, cgtod(fs
, c
), fs
->fs_cgsize
);
214 memcpy(cg
, cgblk
.b_un
.b_cg
, fs
->fs_cgsize
);
215 if((doswap
&& !needswap
) || (!doswap
&& needswap
))
216 ffs_cg_swap(cgblk
.b_un
.b_cg
, cg
, sblock
);
217 if (!doinglevel1
&& !cg_chkmagic(cg
, 0))
218 pfatal("CG %d: PASS5: BAD MAGIC NUMBER\n", c
);
222 * While we have the disk head where we want it,
223 * write back the superblock to the spare at this
226 if ((cvtlevel
&& sblk
.b_dirty
) || doswap
) {
227 bwrite(fswritefd
, sblk
.b_un
.b_buf
,
228 fsbtodb(sblock
, cgsblock(sblock
, c
)),
232 * Read in the current alternate superblock,
233 * and compare it to the master. If it's
236 getblk(&asblk
, cgsblock(sblock
, c
), sblock
->fs_sbsize
);
238 pfatal("CG %d: UNABLE TO READ ALTERNATE "
241 memmove(altsblock
, asblk
.b_un
.b_fs
,
244 ffs_sb_swap(asblk
.b_un
.b_fs
, altsblock
);
246 sb_oldfscompat_write(sblock
, sblocksave
);
247 if ((asblk
.b_errs
|| cmpsblks(sblock
, altsblock
)) &&
249 "ALTERNATE SUPERBLK(S) ARE INCORRECT")) {
250 bwrite(fswritefd
, sblk
.b_un
.b_buf
,
251 fsbtodb(sblock
, cgsblock(sblock
, c
)),
254 sb_oldfscompat_read(sblock
, 0);
256 dbase
= cgbase(fs
, c
);
257 dmax
= dbase
+ fs
->fs_fpg
;
258 if (dmax
> fs
->fs_size
)
260 if (is_ufs2
|| (fs
->fs_old_flags
& FS_FLAGS_UPDATED
))
261 newcg
->cg_time
= cg
->cg_time
;
262 newcg
->cg_old_time
= cg
->cg_old_time
;
264 newcg
->cg_ndblk
= dmax
- dbase
;
266 if (c
== fs
->fs_ncg
- 1) {
267 /* Avoid fighting old fsck for this value. Its never used
268 * outside of this check anyway.
270 if ((fs
->fs_old_flags
& FS_FLAGS_UPDATED
) == 0)
271 newcg
->cg_old_ncyl
= fs
->fs_old_ncyl
% fs
->fs_old_cpg
;
273 newcg
->cg_old_ncyl
= howmany(newcg
->cg_ndblk
,
274 fs
->fs_fpg
/ fs
->fs_old_cpg
);
276 newcg
->cg_old_ncyl
= fs
->fs_old_cpg
;
277 newcg
->cg_old_niblk
= fs
->fs_ipg
;
280 if (fs
->fs_contigsumsize
> 0)
281 newcg
->cg_nclusterblks
= newcg
->cg_ndblk
/ fs
->fs_frag
;
282 newcg
->cg_cs
.cs_ndir
= 0;
283 newcg
->cg_cs
.cs_nffree
= 0;
284 newcg
->cg_cs
.cs_nbfree
= 0;
285 newcg
->cg_cs
.cs_nifree
= fs
->fs_ipg
;
286 if (cg
->cg_rotor
>= 0 && cg
->cg_rotor
< newcg
->cg_ndblk
)
287 newcg
->cg_rotor
= cg
->cg_rotor
;
290 if (cg
->cg_frotor
>= 0 && cg
->cg_frotor
< newcg
->cg_ndblk
)
291 newcg
->cg_frotor
= cg
->cg_frotor
;
293 newcg
->cg_frotor
= 0;
294 if (cg
->cg_irotor
>= 0 && cg
->cg_irotor
< fs
->fs_ipg
)
295 newcg
->cg_irotor
= cg
->cg_irotor
;
297 newcg
->cg_irotor
= 0;
299 newcg
->cg_initediblk
= 0;
301 if ((unsigned)cg
->cg_initediblk
> fs
->fs_ipg
)
302 newcg
->cg_initediblk
= fs
->fs_ipg
;
304 newcg
->cg_initediblk
= cg
->cg_initediblk
;
306 memset(&newcg
->cg_frsum
[0], 0, sizeof newcg
->cg_frsum
);
307 memset(&old_cg_blktot(newcg
, 0)[0], 0, (size_t)(sumsize
));
308 memset(cg_inosused(newcg
, 0), 0, (size_t)(mapsize
));
309 if (!is_ufs2
&& ((fs
->fs_old_flags
& FS_FLAGS_UPDATED
) == 0) &&
310 fs
->fs_old_postblformat
== FS_42POSTBLFMT
)
311 ocg
->cg_magic
= CG_MAGIC
;
313 for (i
= 0; i
< fs
->fs_ipg
; j
++, i
++) {
315 switch (info
->ino_state
) {
323 newcg
->cg_cs
.cs_ndir
++;
328 newcg
->cg_cs
.cs_nifree
--;
329 setbit(cg_inosused(newcg
, 0), i
);
335 errexit("BAD STATE %d FOR INODE I=%ld",
336 info
->ino_state
, (long)j
);
340 for (i
= 0; i
< ROOTINO
; i
++) {
341 setbit(cg_inosused(newcg
, 0), i
);
342 newcg
->cg_cs
.cs_nifree
--;
344 for (i
= 0, d
= dbase
;
346 d
+= fs
->fs_frag
, i
+= fs
->fs_frag
) {
348 for (j
= 0; j
< fs
->fs_frag
; j
++) {
351 setbit(cg_blksfree(newcg
, 0), i
+ j
);
354 if (frags
== fs
->fs_frag
) {
355 newcg
->cg_cs
.cs_nbfree
++;
357 j
= old_cbtocylno(fs
, i
);
358 old_cg_blktot(newcg
, 0)[j
]++;
359 old_cg_blks(fs
, newcg
, j
, 0)[old_cbtorpos(fs
, i
)]++;
361 if (fs
->fs_contigsumsize
> 0)
362 setbit(cg_clustersfree(newcg
, 0),
364 } else if (frags
> 0) {
365 newcg
->cg_cs
.cs_nffree
+= frags
;
366 blk
= blkmap(fs
, cg_blksfree(newcg
, 0), i
);
367 ffs_fragacct(fs
, blk
, newcg
->cg_frsum
, 1, 0);
370 if (fs
->fs_contigsumsize
> 0) {
371 int32_t *sump
= cg_clustersum(newcg
, 0);
372 u_char
*mapp
= cg_clustersfree(newcg
, 0);
377 for (i
= 0; i
< newcg
->cg_nclusterblks
; i
++) {
378 if ((map
& bit
) != 0) {
380 } else if (run
!= 0) {
381 if (run
> fs
->fs_contigsumsize
)
382 run
= fs
->fs_contigsumsize
;
386 if ((i
& (NBBY
- 1)) != (NBBY
- 1)) {
394 if (run
> fs
->fs_contigsumsize
)
395 run
= fs
->fs_contigsumsize
;
399 cstotal
.cs_nffree
+= newcg
->cg_cs
.cs_nffree
;
400 cstotal
.cs_nbfree
+= newcg
->cg_cs
.cs_nbfree
;
401 cstotal
.cs_nifree
+= newcg
->cg_cs
.cs_nifree
;
402 cstotal
.cs_ndir
+= newcg
->cg_cs
.cs_ndir
;
403 cs
= &fs
->fs_cs(fs
, c
);
404 if (memcmp(&newcg
->cg_cs
, cs
, sizeof *cs
) != 0) {
406 printf("cg %d: nffree: %d/%d nbfree %d/%d"
407 " nifree %d/%d ndir %d/%d\n",
408 c
, cs
->cs_nffree
,newcg
->cg_cs
.cs_nffree
,
409 cs
->cs_nbfree
,newcg
->cg_cs
.cs_nbfree
,
410 cs
->cs_nifree
,newcg
->cg_cs
.cs_nifree
,
411 cs
->cs_ndir
,newcg
->cg_cs
.cs_ndir
);
413 if (dofix(&idesc
[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
414 memmove(cs
, &newcg
->cg_cs
, sizeof *cs
);
420 memmove(cg
, newcg
, (size_t)fs
->fs_cgsize
);
424 if ((memcmp(newcg
, cg
, basesize
) != 0) ||
425 (memcmp(&old_cg_blktot(newcg
, 0)[0],
426 &old_cg_blktot(cg
, 0)[0], sumsize
) != 0)) {
427 if (dofix(&idesc
[2], "SUMMARY INFORMATION BAD")) {
428 memmove(cg
, newcg
, (size_t)basesize
);
429 memmove(&old_cg_blktot(cg
, 0)[0],
430 &old_cg_blktot(newcg
, 0)[0], (size_t)sumsize
);
436 for (i
= 0; i
< inomapsize
; i
++) {
437 j
= cg_inosused(newcg
, 0)[i
];
438 if ((cg_inosused(cg
, 0)[i
] & j
) == j
)
440 for (k
= 0; k
< NBBY
; k
++) {
441 if ((j
& (1 << k
)) == 0)
443 if (cg_inosused(cg
, 0)[i
] & (1 << k
))
445 pwarn("ALLOCATED INODE %ld "
447 c
* fs
->fs_ipg
+ i
* 8 + k
);
450 for (i
= 0; i
< blkmapsize
; i
++) {
451 j
= cg_blksfree(cg
, 0)[i
];
452 if ((cg_blksfree(newcg
, 0)[i
] & j
) == j
)
454 for (k
= 0; k
< NBBY
; k
++) {
455 if ((j
& (1 << k
)) == 0)
457 if (cg_inosused(cg
, 0)[i
] & (1 << k
))
459 pwarn("ALLOCATED FRAG %ld "
461 c
* fs
->fs_fpg
+ i
* 8 + k
);
465 if (memcmp(cg_inosused(newcg
, 0), cg_inosused(cg
, 0), mapsize
)
466 != 0 && dofix(&idesc
[1], "BLK(S) MISSING IN BIT MAPS")) {
467 memmove(cg_inosused(cg
, 0), cg_inosused(newcg
, 0),
472 if (memcmp(&cstotal
, &fs
->fs_cstotal
, cssize
) != 0) {
474 printf("total: nffree: %lld/%lld nbfree %lld/%lld"
475 " nifree %lld/%lld ndir %lld/%lld\n",
476 (long long int)fs
->fs_cstotal
.cs_nffree
,
477 (long long int)cstotal
.cs_nffree
,
478 (long long int)fs
->fs_cstotal
.cs_nbfree
,
479 (long long int)cstotal
.cs_nbfree
,
480 (long long int)fs
->fs_cstotal
.cs_nifree
,
481 (long long int)cstotal
.cs_nifree
,
482 (long long int)fs
->fs_cstotal
.cs_ndir
,
483 (long long int)cstotal
.cs_ndir
);
485 if (dofix(&idesc
[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
486 memmove(&fs
->fs_cstotal
, &cstotal
, sizeof cstotal
);
496 #endif /* PROGRESS */
500 print_bmap(u_char
*map
, u_int32_t size
)
507 for (j
= 0; j
< 16; j
++, i
++)
508 printf("%2x ", (u_int
)map
[i
] & 0xff);