1 /* $NetBSD: pass5.c,v 1.36 2003/04/04 15:02:40 fvdl Exp $ */ 2 3 /* 4 * Copyright (c) 1980, 1986, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 #ifndef lint 38 #if 0 39 static char sccsid[] = "@(#)pass5.c 8.9 (Berkeley) 4/28/95"; 40 #else 41 __RCSID("$NetBSD: pass5.c,v 1.36 2003/04/04 15:02:40 fvdl Exp $"); 42 #endif 43 #endif /* not lint */ 44 45 #include <sys/param.h> 46 #include <sys/time.h> 47 48 #include <ufs/ufs/dinode.h> 49 #include <ufs/ffs/fs.h> 50 #include <ufs/ffs/ffs_extern.h> 51 #include <ufs/ufs/ufs_bswap.h> 52 53 #include <err.h> 54 #include <string.h> 55 #include <malloc.h> 56 57 #include "fsutil.h" 58 #include "fsck.h" 59 #include "extern.h" 60 61 void print_bmap __P((u_char *,u_int32_t)); 62 63 void 64 pass5(void) 65 { 66 int c, blk, frags, basesize, mapsize, cssize; 67 int inomapsize, blkmapsize; 68 struct fs *fs = sblock; 69 daddr_t dbase, dmax; 70 daddr_t d; 71 long i, j, k; 72 struct csum *cs; 73 struct csum_total cstotal; 74 struct inodesc idesc[4]; 75 char buf[MAXBSIZE]; 76 struct cg *newcg = (struct cg *)buf; 77 struct cg *cg = cgrp; 78 struct inostat *info; 79 80 inoinfo(WINO)->ino_state = USTATE; 81 memset(newcg, 0, (size_t)fs->fs_cgsize); 82 newcg->cg_niblk = fs->fs_ipg; 83 if (cvtlevel >= 3) { 84 if (fs->fs_maxcontig < 2 && fs->fs_contigsumsize > 0) { 85 if (preen) 86 pwarn("DELETING CLUSTERING MAPS\n"); 87 if (preen || reply("DELETE CLUSTERING MAPS")) { 88 fs->fs_contigsumsize = 0; 89 doinglevel1 = 1; 90 sbdirty(); 91 } 92 } 93 if (fs->fs_maxcontig > 1) { 94 char *doit = 0; 95 96 if (fs->fs_contigsumsize < 1) { 97 doit = "CREAT"; 98 } else if (fs->fs_contigsumsize < fs->fs_maxcontig && 99 fs->fs_contigsumsize < FS_MAXCONTIG) { 100 doit = "EXPAND"; 101 } 102 if (doit) { 103 i = fs->fs_contigsumsize; 104 fs->fs_contigsumsize = 105 MIN(fs->fs_maxcontig, FS_MAXCONTIG); 106 if (CGSIZE(fs) > fs->fs_bsize) { 107 pwarn("CANNOT %s CLUSTER MAPS\n", doit); 108 fs->fs_contigsumsize = i; 109 } else if (preen || 110 reply("CREATE CLUSTER MAPS")) { 111 if (preen) 112 pwarn("%sING CLUSTER MAPS\n", 113 doit); 114 fs->fs_cgsize = 115 fragroundup(fs, CGSIZE(fs)); 116 cg = cgrp = 117 realloc(cgrp, fs->fs_cgsize); 118 if (cg == NULL) 119 errx(EEXIT, 120 "cannot reallocate cg space"); 121 doinglevel1 = 1; 122 sbdirty(); 123 } 124 } 125 } 126 } 127 basesize = &newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield); 128 cssize = (u_char *)&cstotal.cs_spare[0] - (u_char *)&cstotal.cs_ndir; 129 if (is_ufs2) { 130 newcg->cg_iusedoff = basesize; 131 } else { 132 /* 133 * We reserve the space for the old rotation summary 134 * tables for the benefit of old kernels, but do not 135 * maintain them in modern kernels. In time, they can 136 * go away. 137 */ 138 newcg->cg_old_btotoff = basesize; 139 newcg->cg_old_boff = newcg->cg_old_btotoff + 140 fs->fs_old_cpg * sizeof(int32_t); 141 newcg->cg_iusedoff = newcg->cg_old_boff + 142 fs->fs_old_cpg * fs->fs_old_nrpos * sizeof(u_int16_t); 143 memset(&newcg->cg_space[0], 0, newcg->cg_iusedoff - basesize); 144 } 145 inomapsize = howmany(fs->fs_ipg, CHAR_BIT); 146 newcg->cg_freeoff = newcg->cg_iusedoff + inomapsize; 147 blkmapsize = howmany(fs->fs_fpg, CHAR_BIT); 148 newcg->cg_nextfreeoff = newcg->cg_freeoff + blkmapsize; 149 if (fs->fs_contigsumsize > 0) { 150 newcg->cg_clustersumoff = newcg->cg_nextfreeoff - 151 sizeof(u_int32_t); 152 newcg->cg_clustersumoff = 153 roundup(newcg->cg_clustersumoff, sizeof(u_int32_t)); 154 newcg->cg_clusteroff = newcg->cg_clustersumoff + 155 (fs->fs_contigsumsize + 1) * sizeof(u_int32_t); 156 newcg->cg_nextfreeoff = newcg->cg_clusteroff + 157 howmany(fragstoblks(fs, fs->fs_fpg), CHAR_BIT); 158 } 159 newcg->cg_magic = CG_MAGIC; 160 mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff; 161 memset(&idesc[0], 0, sizeof idesc); 162 for (i = 0; i < 4; i++) { 163 idesc[i].id_type = ADDR; 164 if (!is_ufs2 && doinglevel2) 165 idesc[i].id_fix = FIX; 166 } 167 memset(&cstotal, 0, sizeof(struct csum_total)); 168 dmax = blknum(fs, fs->fs_size + fs->fs_frag - 1); 169 for (d = fs->fs_size; d < dmax; d++) 170 setbmap(d); 171 for (c = 0; c < fs->fs_ncg; c++) { 172 if (got_siginfo) { 173 fprintf(stderr, 174 "%s: phase 5: cyl group %d of %d (%d%%)\n", 175 cdevname(), c, fs->fs_ncg, 176 c * 100 / fs->fs_ncg); 177 got_siginfo = 0; 178 } 179 getblk(&cgblk, cgtod(fs, c), fs->fs_cgsize); 180 memcpy(cg, cgblk.b_un.b_cg, fs->fs_cgsize); 181 if((doswap && !needswap) || (!doswap && needswap)) 182 ffs_cg_swap(cgblk.b_un.b_cg, cg, sblock); 183 if (!cg_chkmagic(cg, 0)) 184 pfatal("CG %d: PASS5: BAD MAGIC NUMBER\n", c); 185 if(doswap) 186 cgdirty(); 187 /* 188 * While we have the disk head where we want it, 189 * write back the superblock to the spare at this 190 * cylinder group. 191 */ 192 if ((cvtlevel && sblk.b_dirty) || doswap) { 193 bwrite(fswritefd, sblk.b_un.b_buf, 194 fsbtodb(sblock, cgsblock(sblock, c)), 195 sblock->fs_sbsize); 196 } else { 197 /* 198 * Read in the current alternate superblock, 199 * and compare it to the master. If it's 200 * wrong, fix it up. 201 */ 202 getblk(&asblk, cgsblock(sblock, c), sblock->fs_sbsize); 203 if (asblk.b_errs) 204 pfatal("CG %d: UNABLE TO READ ALTERNATE " 205 "SUPERBLK\n", c); 206 else { 207 memmove(altsblock, asblk.b_un.b_fs, 208 sblock->fs_sbsize); 209 if (needswap) 210 ffs_sb_swap(asblk.b_un.b_fs, altsblock); 211 } 212 if ((asblk.b_errs || cmpsblks(sblock, altsblock)) && 213 dofix(&idesc[3], 214 "ALTERNATE SUPERBLK(S) ARE INCORRECT")) { 215 bwrite(fswritefd, sblk.b_un.b_buf, 216 fsbtodb(sblock, cgsblock(sblock, c)), 217 sblock->fs_sbsize); 218 } 219 } 220 dbase = cgbase(fs, c); 221 dmax = dbase + fs->fs_fpg; 222 if (dmax > fs->fs_size) 223 dmax = fs->fs_size; 224 newcg->cg_time = cg->cg_time; 225 newcg->cg_old_time = cg->cg_old_time; 226 newcg->cg_cgx = c; 227 newcg->cg_ndblk = dmax - dbase; 228 if (!is_ufs2) { 229 if (c == fs->fs_ncg - 1) 230 newcg->cg_old_ncyl = howmany(newcg->cg_ndblk, 231 fs->fs_fpg / fs->fs_old_cpg); 232 else 233 newcg->cg_old_ncyl = fs->fs_old_cpg; 234 newcg->cg_old_niblk = fs->fs_ipg; 235 newcg->cg_niblk = 0; 236 } 237 if (fs->fs_contigsumsize > 0) 238 newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag; 239 newcg->cg_cs.cs_ndir = 0; 240 newcg->cg_cs.cs_nffree = 0; 241 newcg->cg_cs.cs_nbfree = 0; 242 newcg->cg_cs.cs_nifree = fs->fs_ipg; 243 if (cg->cg_rotor >= 0 && cg->cg_rotor < newcg->cg_ndblk) 244 newcg->cg_rotor = cg->cg_rotor; 245 else 246 newcg->cg_rotor = 0; 247 if (cg->cg_frotor >= 0 && cg->cg_frotor < newcg->cg_ndblk) 248 newcg->cg_frotor = cg->cg_frotor; 249 else 250 newcg->cg_frotor = 0; 251 if (cg->cg_irotor >= 0 && cg->cg_irotor < fs->fs_ipg) 252 newcg->cg_irotor = cg->cg_irotor; 253 else 254 newcg->cg_irotor = 0; 255 if (!is_ufs2) { 256 newcg->cg_initediblk = 0; 257 } else { 258 if ((unsigned)cg->cg_initediblk > fs->fs_ipg) 259 newcg->cg_initediblk = fs->fs_ipg; 260 else 261 newcg->cg_initediblk = cg->cg_initediblk; 262 } 263 memset(&newcg->cg_frsum[0], 0, sizeof newcg->cg_frsum); 264 memset(cg_inosused(newcg, 0), 0, (size_t)(mapsize)); 265 j = fs->fs_ipg * c; 266 for (i = 0; i < fs->fs_ipg; j++, i++) { 267 info = inoinfo(j); 268 switch (info->ino_state) { 269 270 case USTATE: 271 break; 272 273 case DSTATE: 274 case DCLEAR: 275 case DFOUND: 276 newcg->cg_cs.cs_ndir++; 277 /* fall through */ 278 279 case FSTATE: 280 case FCLEAR: 281 newcg->cg_cs.cs_nifree--; 282 setbit(cg_inosused(newcg, 0), i); 283 break; 284 285 default: 286 if (j < ROOTINO) 287 break; 288 errx(EEXIT, "BAD STATE %d FOR INODE I=%ld", 289 info->ino_state, (long)j); 290 } 291 } 292 if (c == 0) 293 for (i = 0; i < ROOTINO; i++) { 294 setbit(cg_inosused(newcg, 0), i); 295 newcg->cg_cs.cs_nifree--; 296 } 297 for (i = 0, d = dbase; 298 d < dmax; 299 d += fs->fs_frag, i += fs->fs_frag) { 300 frags = 0; 301 for (j = 0; j < fs->fs_frag; j++) { 302 if (testbmap(d + j)) 303 continue; 304 setbit(cg_blksfree(newcg, 0), i + j); 305 frags++; 306 } 307 if (frags == fs->fs_frag) { 308 newcg->cg_cs.cs_nbfree++; 309 if (fs->fs_contigsumsize > 0) 310 setbit(cg_clustersfree(newcg, 0), 311 fragstoblks(fs, i)); 312 } else if (frags > 0) { 313 newcg->cg_cs.cs_nffree += frags; 314 blk = blkmap(fs, cg_blksfree(newcg, 0), i); 315 ffs_fragacct(fs, blk, newcg->cg_frsum, 1, 0); 316 } 317 } 318 if (fs->fs_contigsumsize > 0) { 319 int32_t *sump = cg_clustersum(newcg, 0); 320 u_char *mapp = cg_clustersfree(newcg, 0); 321 int map = *mapp++; 322 int bit = 1; 323 int run = 0; 324 325 for (i = 0; i < newcg->cg_nclusterblks; i++) { 326 if ((map & bit) != 0) { 327 run++; 328 } else if (run != 0) { 329 if (run > fs->fs_contigsumsize) 330 run = fs->fs_contigsumsize; 331 sump[run]++; 332 run = 0; 333 } 334 if ((i & (NBBY - 1)) != (NBBY - 1)) { 335 bit <<= 1; 336 } else { 337 map = *mapp++; 338 bit = 1; 339 } 340 } 341 if (run != 0) { 342 if (run > fs->fs_contigsumsize) 343 run = fs->fs_contigsumsize; 344 sump[run]++; 345 } 346 } 347 cstotal.cs_nffree += newcg->cg_cs.cs_nffree; 348 cstotal.cs_nbfree += newcg->cg_cs.cs_nbfree; 349 cstotal.cs_nifree += newcg->cg_cs.cs_nifree; 350 cstotal.cs_ndir += newcg->cg_cs.cs_ndir; 351 cs = &fs->fs_cs(fs, c); 352 if (memcmp(&newcg->cg_cs, cs, sizeof *cs) != 0) { 353 if (dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) { 354 memmove(cs, &newcg->cg_cs, sizeof *cs); 355 sbdirty(); 356 } else 357 markclean = 0; 358 } 359 if (doinglevel1) { 360 memmove(cg, newcg, (size_t)fs->fs_cgsize); 361 cgdirty(); 362 continue; 363 } 364 if (memcmp(newcg, cg, basesize) != 0) { 365 if (dofix(&idesc[2], "SUMMARY INFORMATION BAD")) { 366 memmove(cg, newcg, (size_t)basesize); 367 cgdirty(); 368 } else 369 markclean = 0; 370 } 371 if (usedsoftdep) { 372 for (i = 0; i < inomapsize; i++) { 373 j = cg_inosused(newcg, 0)[i]; 374 if ((cg_inosused(cg, 0)[i] & j) == j) 375 continue; 376 for (k = 0; k < NBBY; k++) { 377 if ((j & (1 << k)) == 0) 378 continue; 379 if (cg_inosused(cg, 0)[i] & (1 << k)) 380 continue; 381 pwarn("ALLOCATED INODE %ld " 382 "MARKED FREE\n", 383 c * fs->fs_ipg + i * 8 + k); 384 } 385 } 386 for (i = 0; i < blkmapsize; i++) { 387 j = cg_blksfree(cg, 0)[i]; 388 if ((cg_blksfree(newcg, 0)[i] & j) == j) 389 continue; 390 for (k = 0; k < NBBY; k++) { 391 if ((j & (1 << k)) == 0) 392 continue; 393 if (cg_inosused(cg, 0)[i] & (1 << k)) 394 continue; 395 pwarn("ALLOCATED FRAG %ld " 396 "MARKED FREE\n", 397 c * fs->fs_fpg + i * 8 + k); 398 } 399 } 400 } 401 if (memcmp(cg_inosused(newcg, 0), cg_inosused(cg, 0), mapsize) 402 != 0 && dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) { 403 memmove(cg_inosused(cg, 0), cg_inosused(newcg, 0), 404 (size_t)mapsize); 405 cgdirty(); 406 } 407 } 408 if (memcmp(&cstotal, &fs->fs_cstotal, cssize) != 0) { 409 if (dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) { 410 memmove(&fs->fs_cstotal, &cstotal, sizeof cstotal); 411 fs->fs_ronly = 0; 412 fs->fs_fmod = 0; 413 sbdirty(); 414 } else 415 markclean = 0; 416 } 417 } 418 419 void 420 print_bmap(map, size) 421 u_char *map; 422 u_int32_t size; 423 { 424 int i, j; 425 426 i = 0; 427 while (i < size) { 428 printf("%u: ",i); 429 for (j = 0; j < 16; j++, i++) 430 printf("%2x ", (u_int)map[i] & 0xff); 431 printf("\n"); 432 } 433 } 434