1 /* $NetBSD: pass5.c,v 1.54 2013/06/23 22:03:34 dholland 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. 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. 18 * 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 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "@(#)pass5.c 8.9 (Berkeley) 4/28/95"; 36 #else 37 __RCSID("$NetBSD: pass5.c,v 1.54 2013/06/23 22:03:34 dholland Exp $"); 38 #endif 39 #endif /* not lint */ 40 41 #include <sys/param.h> 42 #include <sys/time.h> 43 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> 48 49 #include <err.h> 50 #include <string.h> 51 #include <stdlib.h> 52 53 #include "fsutil.h" 54 #include "fsck.h" 55 #include "extern.h" 56 57 void print_bmap(u_char *,u_int32_t); 58 59 void 60 pass5(void) 61 { 62 int c, blk, frags, basesize, sumsize, mapsize, cssize; 63 int inomapsize, blkmapsize; 64 struct fs *fs = sblock; 65 daddr_t dbase, dmax; 66 daddr_t d; 67 long i, j, k; 68 struct csum *cs; 69 struct csum_total cstotal; 70 struct inodesc idesc[4]; 71 char buf[MAXBSIZE]; 72 struct cg *newcg = (struct cg *)buf; 73 struct ocg *ocg = (struct ocg *)buf; 74 struct cg *cg = cgrp, *ncg; 75 struct inostat *info; 76 u_int32_t ncgsize; 77 78 inoinfo(UFS_WINO)->ino_state = USTATE; 79 memset(newcg, 0, (size_t)fs->fs_cgsize); 80 newcg->cg_niblk = fs->fs_ipg; 81 if (cvtlevel >= 3) { 82 if (fs->fs_maxcontig < 2 && fs->fs_contigsumsize > 0) { 83 if (preen) 84 pwarn("DELETING CLUSTERING MAPS\n"); 85 if (preen || reply("DELETE CLUSTERING MAPS")) { 86 fs->fs_contigsumsize = 0; 87 doinglevel1 = 1; 88 sbdirty(); 89 } 90 } 91 if (fs->fs_maxcontig > 1) { 92 const char *doit = NULL; 93 94 if (fs->fs_contigsumsize < 1) { 95 doit = "CREAT"; 96 } else if (fs->fs_contigsumsize < fs->fs_maxcontig && 97 fs->fs_contigsumsize < FS_MAXCONTIG) { 98 doit = "EXPAND"; 99 } 100 if (doit) { 101 i = fs->fs_contigsumsize; 102 fs->fs_contigsumsize = 103 MIN(fs->fs_maxcontig, FS_MAXCONTIG); 104 if (CGSIZE(fs) > (uint32_t)fs->fs_bsize) { 105 pwarn("CANNOT %s CLUSTER MAPS\n", doit); 106 fs->fs_contigsumsize = i; 107 } else if (preen || 108 reply("CREATE CLUSTER MAPS")) { 109 if (preen) 110 pwarn("%sING CLUSTER MAPS\n", 111 doit); 112 ncgsize = ffs_fragroundup(fs, CGSIZE(fs)); 113 ncg = realloc(cgrp, ncgsize); 114 if (ncg == NULL) 115 errexit( 116 "cannot reallocate cg space"); 117 cg = cgrp = ncg; 118 fs->fs_cgsize = ncgsize; 119 doinglevel1 = 1; 120 sbdirty(); 121 } 122 } 123 } 124 } 125 basesize = &newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield); 126 cssize = (u_char *)&cstotal.cs_spare[0] - (u_char *)&cstotal.cs_ndir; 127 sumsize = 0; 128 if (is_ufs2) { 129 newcg->cg_iusedoff = basesize; 130 } else { 131 /* 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 135 * go away. 136 */ 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); 143 } 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 - 150 sizeof(u_int32_t); 151 if (isappleufs) { 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 155 */ 156 newcg->cg_clustersumoff += sizeof(u_int32_t); 157 } 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(ffs_fragstoblks(fs, fs->fs_fpg), CHAR_BIT); 164 } 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) { 169 170 case FS_42POSTBLFMT: 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; 179 newcg->cg_magic = 0; 180 break; 181 182 case FS_DYNAMICPOSTBLFMT: 183 sumsize = newcg->cg_iusedoff - newcg->cg_old_btotoff; 184 break; 185 186 default: 187 errexit("UNKNOWN ROTATIONAL TABLE FORMAT %d", 188 fs->fs_old_postblformat); 189 } 190 } 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; 196 } 197 memset(&cstotal, 0, sizeof(struct csum_total)); 198 dmax = ffs_blknum(fs, fs->fs_size + fs->fs_frag - 1); 199 for (d = fs->fs_size; d < dmax; d++) 200 setbmap(d); 201 for (c = 0; c < fs->fs_ncg; c++) { 202 if (got_siginfo) { 203 fprintf(stderr, 204 "%s: phase 5: cyl group %d of %d (%d%%)\n", 205 cdevname(), c, fs->fs_ncg, 206 c * 100 / fs->fs_ncg); 207 got_siginfo = 0; 208 } 209 #ifdef PROGRESS 210 progress_bar(cdevname(), preen ? NULL : "phase 5", 211 c, fs->fs_ncg); 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); 219 if(doswap) 220 cgdirty(); 221 /* 222 * While we have the disk head where we want it, 223 * write back the superblock to the spare at this 224 * cylinder group. 225 */ 226 if ((cvtlevel && sblk.b_dirty) || doswap) { 227 bwrite(fswritefd, sblk.b_un.b_buf, 228 FFS_FSBTODB(sblock, cgsblock(sblock, c)), 229 sblock->fs_sbsize); 230 } else { 231 /* 232 * Read in the current alternate superblock, 233 * and compare it to the master. If it's 234 * wrong, fix it up. 235 */ 236 getblk(&asblk, cgsblock(sblock, c), sblock->fs_sbsize); 237 if (asblk.b_errs) 238 pfatal("CG %d: UNABLE TO READ ALTERNATE " 239 "SUPERBLK\n", c); 240 else { 241 memmove(altsblock, asblk.b_un.b_fs, 242 sblock->fs_sbsize); 243 if (needswap) 244 ffs_sb_swap(asblk.b_un.b_fs, altsblock); 245 } 246 sb_oldfscompat_write(sblock, sblocksave); 247 if ((asblk.b_errs || cmpsblks(sblock, altsblock)) && 248 dofix(&idesc[3], 249 "ALTERNATE SUPERBLK(S) ARE INCORRECT")) { 250 bwrite(fswritefd, sblk.b_un.b_buf, 251 FFS_FSBTODB(sblock, cgsblock(sblock, c)), 252 sblock->fs_sbsize); 253 } 254 sb_oldfscompat_read(sblock, 0); 255 } 256 dbase = cgbase(fs, c); 257 dmax = dbase + fs->fs_fpg; 258 if (dmax > fs->fs_size) 259 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; 263 newcg->cg_cgx = c; 264 newcg->cg_ndblk = dmax - dbase; 265 if (!is_ufs2) { 266 if (c == fs->fs_ncg - 1) { 267 /* Avoid fighting old fsck for this value. Its never used 268 * outside of this check anyway. 269 */ 270 if ((fs->fs_old_flags & FS_FLAGS_UPDATED) == 0) 271 newcg->cg_old_ncyl = fs->fs_old_ncyl % fs->fs_old_cpg; 272 else 273 newcg->cg_old_ncyl = howmany(newcg->cg_ndblk, 274 fs->fs_fpg / fs->fs_old_cpg); 275 } else 276 newcg->cg_old_ncyl = fs->fs_old_cpg; 277 newcg->cg_old_niblk = fs->fs_ipg; 278 newcg->cg_niblk = 0; 279 } 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; 288 else 289 newcg->cg_rotor = 0; 290 if (cg->cg_frotor >= 0 && cg->cg_frotor < newcg->cg_ndblk) 291 newcg->cg_frotor = cg->cg_frotor; 292 else 293 newcg->cg_frotor = 0; 294 if (cg->cg_irotor >= 0 && cg->cg_irotor < fs->fs_ipg) 295 newcg->cg_irotor = cg->cg_irotor; 296 else 297 newcg->cg_irotor = 0; 298 if (!is_ufs2) { 299 newcg->cg_initediblk = 0; 300 } else { 301 if ((unsigned)cg->cg_initediblk > (unsigned)fs->fs_ipg) 302 newcg->cg_initediblk = fs->fs_ipg; 303 else 304 newcg->cg_initediblk = cg->cg_initediblk; 305 } 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; 312 j = fs->fs_ipg * c; 313 for (i = 0; i < fs->fs_ipg; j++, i++) { 314 info = inoinfo(j); 315 switch (info->ino_state) { 316 317 case USTATE: 318 break; 319 320 case DSTATE: 321 case DCLEAR: 322 case DFOUND: 323 newcg->cg_cs.cs_ndir++; 324 /* fall through */ 325 326 case FSTATE: 327 case FCLEAR: 328 newcg->cg_cs.cs_nifree--; 329 setbit(cg_inosused(newcg, 0), i); 330 break; 331 332 default: 333 if ((ino_t)j < UFS_ROOTINO) 334 break; 335 errexit("BAD STATE %d FOR INODE I=%ld", 336 info->ino_state, (long)j); 337 } 338 } 339 if (c == 0) 340 for (i = 0; i < (long)UFS_ROOTINO; i++) { 341 setbit(cg_inosused(newcg, 0), i); 342 newcg->cg_cs.cs_nifree--; 343 } 344 for (i = 0, d = dbase; 345 d < dmax; 346 d += fs->fs_frag, i += fs->fs_frag) { 347 frags = 0; 348 for (j = 0; j < fs->fs_frag; j++) { 349 if (testbmap(d + j)) 350 continue; 351 setbit(cg_blksfree(newcg, 0), i + j); 352 frags++; 353 } 354 if (frags == fs->fs_frag) { 355 newcg->cg_cs.cs_nbfree++; 356 if (sumsize) { 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)]++; 360 } 361 if (fs->fs_contigsumsize > 0) 362 setbit(cg_clustersfree(newcg, 0), 363 ffs_fragstoblks(fs, i)); 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); 368 } 369 } 370 if (fs->fs_contigsumsize > 0) { 371 int32_t *sump = cg_clustersum(newcg, 0); 372 u_char *mapp = cg_clustersfree(newcg, 0); 373 int map = *mapp++; 374 int bit = 1; 375 int run = 0; 376 377 for (i = 0; i < newcg->cg_nclusterblks; i++) { 378 if ((map & bit) != 0) { 379 run++; 380 } else if (run != 0) { 381 if (run > fs->fs_contigsumsize) 382 run = fs->fs_contigsumsize; 383 sump[run]++; 384 run = 0; 385 } 386 if ((i & (NBBY - 1)) != (NBBY - 1)) { 387 bit <<= 1; 388 } else { 389 map = *mapp++; 390 bit = 1; 391 } 392 } 393 if (run != 0) { 394 if (run > fs->fs_contigsumsize) 395 run = fs->fs_contigsumsize; 396 sump[run]++; 397 } 398 } 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) { 405 if (debug) { 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); 412 } 413 if (dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) { 414 memmove(cs, &newcg->cg_cs, sizeof *cs); 415 sbdirty(); 416 } else 417 markclean = 0; 418 } 419 if (doinglevel1) { 420 memmove(cg, newcg, (size_t)fs->fs_cgsize); 421 cgdirty(); 422 continue; 423 } 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); 431 cgdirty(); 432 } else 433 markclean = 0; 434 } 435 if (usedsoftdep) { 436 for (i = 0; i < inomapsize; i++) { 437 j = cg_inosused(newcg, 0)[i]; 438 if ((cg_inosused(cg, 0)[i] & j) == j) 439 continue; 440 for (k = 0; k < NBBY; k++) { 441 if ((j & (1 << k)) == 0) 442 continue; 443 if (cg_inosused(cg, 0)[i] & (1 << k)) 444 continue; 445 pwarn("ALLOCATED INODE %ld " 446 "MARKED FREE\n", 447 c * fs->fs_ipg + i * 8 + k); 448 } 449 } 450 for (i = 0; i < blkmapsize; i++) { 451 j = cg_blksfree(cg, 0)[i]; 452 if ((cg_blksfree(newcg, 0)[i] & j) == j) 453 continue; 454 for (k = 0; k < NBBY; k++) { 455 if ((j & (1 << k)) == 0) 456 continue; 457 if (cg_inosused(cg, 0)[i] & (1 << k)) 458 continue; 459 pwarn("ALLOCATED FRAG %ld " 460 "MARKED FREE\n", 461 c * fs->fs_fpg + i * 8 + k); 462 } 463 } 464 } 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), 468 (size_t)mapsize); 469 cgdirty(); 470 } 471 } 472 if (memcmp(&cstotal, &fs->fs_cstotal, cssize) != 0) { 473 if (debug) { 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); 484 } 485 if (dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) { 486 memmove(&fs->fs_cstotal, &cstotal, sizeof cstotal); 487 fs->fs_ronly = 0; 488 fs->fs_fmod = 0; 489 sbdirty(); 490 } else 491 markclean = 0; 492 } 493 #ifdef PROGRESS 494 if (!preen) 495 progress_done(); 496 #endif /* PROGRESS */ 497 } 498 499 void 500 print_bmap(u_char *map, uint32_t size) 501 { 502 uint32_t i, j; 503 504 i = 0; 505 while (i < size) { 506 printf("%u: ",i); 507 for (j = 0; j < 16; j++, i++) 508 printf("%2x ", (u_int)map[i] & 0xff); 509 printf("\n"); 510 } 511 } 512