1 /* $NetBSD: pass5.c,v 1.58 2023/07/04 20:40:53 riastradh 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.58 2023/07/04 20:40:53 riastradh 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 blk, frags, basesize, sumsize, mapsize, cssize; 63 uint32_t inomapsize, blkmapsize; 64 uint32_t c; 65 struct fs *fs = sblock; 66 daddr_t dbase, dmax; 67 daddr_t d; 68 uint32_t i; 69 int32_t j; 70 int k; 71 ino_t inum; 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 ocg *ocg = (struct ocg *)buf; 78 struct cg *cg = cgrp, *ncg; 79 struct inostat *info; 80 u_int32_t ncgsize; 81 82 inoinfo(UFS_WINO)->ino_state = USTATE; 83 memset(newcg, 0, (size_t)fs->fs_cgsize); 84 newcg->cg_niblk = fs->fs_ipg; 85 if (cvtlevel >= 3) { 86 if (fs->fs_maxcontig < 2 && fs->fs_contigsumsize > 0) { 87 if (preen) 88 pwarn("DELETING CLUSTERING MAPS\n"); 89 if (preen || reply("DELETE CLUSTERING MAPS")) { 90 fs->fs_contigsumsize = 0; 91 doinglevel1 = 1; 92 sbdirty(); 93 } 94 } 95 if (fs->fs_maxcontig > 1) { 96 const char *doit = NULL; 97 98 if (fs->fs_contigsumsize < 1) { 99 doit = "CREAT"; 100 } else if (fs->fs_contigsumsize < fs->fs_maxcontig && 101 fs->fs_contigsumsize < FS_MAXCONTIG) { 102 doit = "EXPAND"; 103 } 104 if (doit) { 105 i = fs->fs_contigsumsize; 106 fs->fs_contigsumsize = 107 MIN(fs->fs_maxcontig, FS_MAXCONTIG); 108 if (CGSIZE(fs) > (uint32_t)fs->fs_bsize) { 109 pwarn("CANNOT %s CLUSTER MAPS\n", doit); 110 fs->fs_contigsumsize = i; 111 } else if (preen || 112 reply("CREATE CLUSTER MAPS")) { 113 if (preen) 114 pwarn("%sING CLUSTER MAPS\n", 115 doit); 116 ncgsize = ffs_fragroundup(fs, CGSIZE(fs)); 117 ncg = realloc(cgrp, ncgsize); 118 if (ncg == NULL) 119 errexit( 120 "cannot reallocate cg space"); 121 cg = cgrp = ncg; 122 fs->fs_cgsize = ncgsize; 123 doinglevel1 = 1; 124 sbdirty(); 125 } 126 } 127 } 128 } 129 basesize = &newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield); 130 cssize = (u_char *)&cstotal.cs_spare[0] - (u_char *)&cstotal.cs_ndir; 131 sumsize = 0; 132 if (is_ufs2) { 133 newcg->cg_iusedoff = basesize; 134 } else { 135 /* 136 * We reserve the space for the old rotation summary 137 * tables for the benefit of old kernels, but do not 138 * maintain them in modern kernels. In time, they can 139 * go away. 140 */ 141 newcg->cg_old_btotoff = basesize; 142 newcg->cg_old_boff = newcg->cg_old_btotoff + 143 fs->fs_old_cpg * sizeof(int32_t); 144 newcg->cg_iusedoff = newcg->cg_old_boff + 145 fs->fs_old_cpg * fs->fs_old_nrpos * sizeof(u_int16_t); 146 memset(&newcg->cg_space[0], 0, newcg->cg_iusedoff - basesize); 147 } 148 inomapsize = howmany(fs->fs_ipg, CHAR_BIT); 149 newcg->cg_freeoff = newcg->cg_iusedoff + inomapsize; 150 blkmapsize = howmany(fs->fs_fpg, CHAR_BIT); 151 newcg->cg_nextfreeoff = newcg->cg_freeoff + blkmapsize; 152 if (fs->fs_contigsumsize > 0) { 153 newcg->cg_clustersumoff = newcg->cg_nextfreeoff - 154 sizeof(u_int32_t); 155 if (isappleufs) { 156 /* Apple PR2216969 gives rationale for this change. 157 * I believe they were mistaken, but we need to 158 * duplicate it for compatibility. -- dbj (at) NetBSD.org 159 */ 160 newcg->cg_clustersumoff += sizeof(u_int32_t); 161 } 162 newcg->cg_clustersumoff = 163 roundup(newcg->cg_clustersumoff, sizeof(u_int32_t)); 164 newcg->cg_clusteroff = newcg->cg_clustersumoff + 165 (fs->fs_contigsumsize + 1) * sizeof(u_int32_t); 166 newcg->cg_nextfreeoff = newcg->cg_clusteroff + 167 howmany(ffs_fragstoblks(fs, fs->fs_fpg), CHAR_BIT); 168 } 169 newcg->cg_magic = CG_MAGIC; 170 mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff; 171 if (!is_ufs2 && ((fs->fs_old_flags & FS_FLAGS_UPDATED) == 0)) { 172 switch ((int)fs->fs_old_postblformat) { 173 174 case FS_42POSTBLFMT: 175 basesize = (char *)(&ocg->cg_btot[0]) - 176 (char *)(&ocg->cg_firstfield); 177 sumsize = &ocg->cg_iused[0] - (u_int8_t *)(&ocg->cg_btot[0]); 178 mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] - 179 (u_char *)&ocg->cg_iused[0]; 180 blkmapsize = howmany(fs->fs_fpg, NBBY); 181 inomapsize = &ocg->cg_free[0] - (u_char *)&ocg->cg_iused[0]; 182 ocg->cg_magic = CG_MAGIC; 183 newcg->cg_magic = 0; 184 break; 185 186 case FS_DYNAMICPOSTBLFMT: 187 sumsize = newcg->cg_iusedoff - newcg->cg_old_btotoff; 188 break; 189 190 default: 191 errexit("UNKNOWN ROTATIONAL TABLE FORMAT %d", 192 fs->fs_old_postblformat); 193 } 194 } 195 memset(&idesc[0], 0, sizeof idesc); 196 for (i = 0; i < 4; i++) { 197 idesc[i].id_type = ADDR; 198 if (!is_ufs2 && doinglevel2) 199 idesc[i].id_fix = FIX; 200 } 201 memset(&cstotal, 0, sizeof(struct csum_total)); 202 dmax = ffs_blknum(fs, fs->fs_size + fs->fs_frag - 1); 203 for (d = fs->fs_size; d < dmax; d++) 204 setbmap(d); 205 for (c = 0; c < fs->fs_ncg; c++) { 206 if (got_siginfo) { 207 fprintf(stderr, 208 "%s: phase 5: cyl group %d of %d (%d%%)\n", 209 cdevname(), c, fs->fs_ncg, 210 c * 100 / fs->fs_ncg); 211 got_siginfo = 0; 212 } 213 #ifdef PROGRESS 214 progress_bar(cdevname(), preen ? NULL : "phase 5", 215 c, fs->fs_ncg); 216 #endif /* PROGRESS */ 217 getblk(&cgblk, cgtod(fs, c), fs->fs_cgsize); 218 memcpy(cg, cgblk.b_un.b_cg, fs->fs_cgsize); 219 if((doswap && !needswap) || (!doswap && needswap)) 220 ffs_cg_swap(cgblk.b_un.b_cg, cg, sblock); 221 if (!doinglevel1 && !cg_chkmagic(cg, 0)) 222 pfatal("CG %d: PASS5: BAD MAGIC NUMBER\n", c); 223 if(doswap) 224 cgdirty(); 225 /* 226 * While we have the disk head where we want it, 227 * write back the superblock to the spare at this 228 * cylinder group. 229 */ 230 if ((cvtlevel && sblk.b_dirty) || doswap || doing2ea || doing2noea) { 231 bwrite(fswritefd, sblk.b_un.b_buf, 232 FFS_FSBTODB(sblock, cgsblock(sblock, c)), 233 sblock->fs_sbsize); 234 } else { 235 int alt_ufs2ea = 0; 236 237 /* 238 * Read in the current alternate superblock, 239 * and compare it to the master. If it's 240 * wrong, fix it up. 241 */ 242 getblk(&asblk, cgsblock(sblock, c), sblock->fs_sbsize); 243 if (asblk.b_errs) 244 pfatal("CG %d: UNABLE TO READ ALTERNATE " 245 "SUPERBLK\n", c); 246 else { 247 memmove(altsblock, asblk.b_un.b_fs, 248 sblock->fs_sbsize); 249 if (needswap) 250 ffs_sb_swap(asblk.b_un.b_fs, altsblock); 251 if (altsblock->fs_magic == FS_UFS2EA_MAGIC) { 252 altsblock->fs_magic = FS_UFS2_MAGIC; 253 alt_ufs2ea = 1; 254 } 255 } 256 sb_oldfscompat_write(sblock, sblocksave); 257 if ((asblk.b_errs || cmpsblks(sblock, altsblock) || 258 is_ufs2ea != alt_ufs2ea) && 259 dofix(&idesc[3], 260 "ALTERNATE SUPERBLK(S) ARE INCORRECT")) { 261 bwrite(fswritefd, sblk.b_un.b_buf, 262 FFS_FSBTODB(sblock, cgsblock(sblock, c)), 263 sblock->fs_sbsize); 264 } 265 sb_oldfscompat_read(sblock, 0); 266 } 267 dbase = cgbase(fs, c); 268 dmax = dbase + fs->fs_fpg; 269 if (dmax > fs->fs_size) 270 dmax = fs->fs_size; 271 if (is_ufs2 || (fs->fs_old_flags & FS_FLAGS_UPDATED)) 272 newcg->cg_time = cg->cg_time; 273 newcg->cg_old_time = cg->cg_old_time; 274 newcg->cg_cgx = c; 275 newcg->cg_ndblk = dmax - dbase; 276 if (!is_ufs2) { 277 if (c == fs->fs_ncg - 1) { 278 /* Avoid fighting old fsck for this value. Its never used 279 * outside of this check anyway. 280 */ 281 if ((fs->fs_old_flags & FS_FLAGS_UPDATED) == 0) 282 newcg->cg_old_ncyl = fs->fs_old_ncyl % fs->fs_old_cpg; 283 else 284 newcg->cg_old_ncyl = howmany(newcg->cg_ndblk, 285 fs->fs_fpg / fs->fs_old_cpg); 286 } else 287 newcg->cg_old_ncyl = fs->fs_old_cpg; 288 newcg->cg_old_niblk = fs->fs_ipg; 289 newcg->cg_niblk = 0; 290 } 291 if (fs->fs_contigsumsize > 0) 292 newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag; 293 newcg->cg_cs.cs_ndir = 0; 294 newcg->cg_cs.cs_nffree = 0; 295 newcg->cg_cs.cs_nbfree = 0; 296 newcg->cg_cs.cs_nifree = fs->fs_ipg; 297 if (cg->cg_rotor < newcg->cg_ndblk) 298 newcg->cg_rotor = cg->cg_rotor; 299 else 300 newcg->cg_rotor = 0; 301 if (cg->cg_frotor < newcg->cg_ndblk) 302 newcg->cg_frotor = cg->cg_frotor; 303 else 304 newcg->cg_frotor = 0; 305 if (cg->cg_irotor < fs->fs_ipg) 306 newcg->cg_irotor = cg->cg_irotor; 307 else 308 newcg->cg_irotor = 0; 309 if (!is_ufs2) { 310 newcg->cg_initediblk = 0; 311 } else { 312 if ((unsigned)cg->cg_initediblk > (unsigned)fs->fs_ipg) 313 newcg->cg_initediblk = fs->fs_ipg; 314 else 315 newcg->cg_initediblk = cg->cg_initediblk; 316 } 317 memset(&newcg->cg_frsum[0], 0, sizeof newcg->cg_frsum); 318 memset(&old_cg_blktot(newcg, 0)[0], 0, (size_t)(sumsize)); 319 memset(cg_inosused(newcg, 0), 0, (size_t)(mapsize)); 320 if (!is_ufs2 && ((fs->fs_old_flags & FS_FLAGS_UPDATED) == 0) && 321 fs->fs_old_postblformat == FS_42POSTBLFMT) 322 ocg->cg_magic = CG_MAGIC; 323 inum = fs->fs_ipg * c; 324 for (i = 0; i < fs->fs_ipg; inum++, i++) { 325 info = inoinfo(inum); 326 switch (info->ino_state) { 327 328 case USTATE: 329 break; 330 331 case DSTATE: 332 case DCLEAR: 333 case DFOUND: 334 newcg->cg_cs.cs_ndir++; 335 /* fall through */ 336 337 case FSTATE: 338 case FCLEAR: 339 newcg->cg_cs.cs_nifree--; 340 setbit(cg_inosused(newcg, 0), i); 341 break; 342 343 default: 344 if (inum < UFS_ROOTINO) 345 break; 346 errexit("BAD STATE %d FOR INODE I=%ju", 347 info->ino_state, (uintmax_t)inum); 348 } 349 } 350 if (c == 0) 351 for (i = 0; i < UFS_ROOTINO; i++) { 352 setbit(cg_inosused(newcg, 0), i); 353 newcg->cg_cs.cs_nifree--; 354 } 355 for (i = 0, d = dbase; 356 d < dmax; 357 d += fs->fs_frag, i += fs->fs_frag) { 358 frags = 0; 359 for (j = 0; j < fs->fs_frag; j++) { 360 if (testbmap(d + j)) 361 continue; 362 setbit(cg_blksfree(newcg, 0), i + j); 363 frags++; 364 } 365 if (frags == fs->fs_frag) { 366 newcg->cg_cs.cs_nbfree++; 367 if (sumsize) { 368 j = old_cbtocylno(fs, i); 369 old_cg_blktot(newcg, 0)[j]++; 370 old_cg_blks(fs, newcg, j, 0)[old_cbtorpos(fs, i)]++; 371 } 372 if (fs->fs_contigsumsize > 0) 373 setbit(cg_clustersfree(newcg, 0), 374 ffs_fragstoblks(fs, i)); 375 } else if (frags > 0) { 376 newcg->cg_cs.cs_nffree += frags; 377 blk = blkmap(fs, cg_blksfree(newcg, 0), i); 378 ffs_fragacct(fs, blk, newcg->cg_frsum, 1, 0); 379 } 380 } 381 if (fs->fs_contigsumsize > 0) { 382 int32_t *sump = cg_clustersum(newcg, 0); 383 u_char *mapp = cg_clustersfree(newcg, 0); 384 int map = *mapp++; 385 int bit = 1; 386 int run = 0; 387 388 for (i = 0; i < newcg->cg_nclusterblks; i++) { 389 if ((map & bit) != 0) { 390 run++; 391 } else if (run != 0) { 392 if (run > fs->fs_contigsumsize) 393 run = fs->fs_contigsumsize; 394 sump[run]++; 395 run = 0; 396 } 397 if ((i & (NBBY - 1)) != (NBBY - 1)) { 398 bit <<= 1; 399 } else { 400 map = *mapp++; 401 bit = 1; 402 } 403 } 404 if (run != 0) { 405 if (run > fs->fs_contigsumsize) 406 run = fs->fs_contigsumsize; 407 sump[run]++; 408 } 409 } 410 cstotal.cs_nffree += newcg->cg_cs.cs_nffree; 411 cstotal.cs_nbfree += newcg->cg_cs.cs_nbfree; 412 cstotal.cs_nifree += newcg->cg_cs.cs_nifree; 413 cstotal.cs_ndir += newcg->cg_cs.cs_ndir; 414 cs = &fs->fs_cs(fs, c); 415 if (memcmp(&newcg->cg_cs, cs, sizeof *cs) != 0) { 416 if (debug) { 417 printf("cg %d: nffree: %d/%d nbfree %d/%d" 418 " nifree %d/%d ndir %d/%d\n", 419 c, cs->cs_nffree,newcg->cg_cs.cs_nffree, 420 cs->cs_nbfree,newcg->cg_cs.cs_nbfree, 421 cs->cs_nifree,newcg->cg_cs.cs_nifree, 422 cs->cs_ndir,newcg->cg_cs.cs_ndir); 423 } 424 if (dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) { 425 memmove(cs, &newcg->cg_cs, sizeof *cs); 426 sbdirty(); 427 } else 428 markclean = 0; 429 } 430 if (doinglevel1) { 431 memmove(cg, newcg, (size_t)fs->fs_cgsize); 432 cgdirty(); 433 continue; 434 } 435 if ((memcmp(newcg, cg, basesize) != 0) || 436 (memcmp(&old_cg_blktot(newcg, 0)[0], 437 &old_cg_blktot(cg, 0)[0], sumsize) != 0)) { 438 if (dofix(&idesc[2], "SUMMARY INFORMATION BAD")) { 439 memmove(cg, newcg, (size_t)basesize); 440 memmove(&old_cg_blktot(cg, 0)[0], 441 &old_cg_blktot(newcg, 0)[0], (size_t)sumsize); 442 cgdirty(); 443 } else 444 markclean = 0; 445 } 446 if (usedsoftdep) { 447 for (i = 0; i < inomapsize; i++) { 448 j = cg_inosused(newcg, 0)[i]; 449 if ((cg_inosused(cg, 0)[i] & j) == j) 450 continue; 451 for (k = 0; k < NBBY; k++) { 452 if ((j & (1 << k)) == 0) 453 continue; 454 if (cg_inosused(cg, 0)[i] & (1 << k)) 455 continue; 456 pwarn("ALLOCATED INODE %u " 457 "MARKED FREE\n", 458 c * fs->fs_ipg + i * 8 + k); 459 } 460 } 461 for (i = 0; i < blkmapsize; i++) { 462 j = cg_blksfree(cg, 0)[i]; 463 if ((cg_blksfree(newcg, 0)[i] & j) == j) 464 continue; 465 for (k = 0; k < NBBY; k++) { 466 if ((j & (1 << k)) == 0) 467 continue; 468 if (cg_inosused(cg, 0)[i] & (1 << k)) 469 continue; 470 pwarn("ALLOCATED FRAG %u " 471 "MARKED FREE\n", 472 c * fs->fs_fpg + i * 8 + k); 473 } 474 } 475 } 476 if (memcmp(cg_inosused(newcg, 0), cg_inosused(cg, 0), mapsize) 477 != 0 && dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) { 478 memmove(cg_inosused(cg, 0), cg_inosused(newcg, 0), 479 (size_t)mapsize); 480 cgdirty(); 481 } 482 } 483 if (memcmp(&cstotal, &fs->fs_cstotal, cssize) != 0) { 484 if (debug) { 485 printf("total: nffree: %lld/%lld nbfree %lld/%lld" 486 " nifree %lld/%lld ndir %lld/%lld\n", 487 (long long int)fs->fs_cstotal.cs_nffree, 488 (long long int)cstotal.cs_nffree, 489 (long long int)fs->fs_cstotal.cs_nbfree, 490 (long long int)cstotal.cs_nbfree, 491 (long long int)fs->fs_cstotal.cs_nifree, 492 (long long int)cstotal.cs_nifree, 493 (long long int)fs->fs_cstotal.cs_ndir, 494 (long long int)cstotal.cs_ndir); 495 } 496 if (dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) { 497 memmove(&fs->fs_cstotal, &cstotal, sizeof cstotal); 498 fs->fs_ronly = 0; 499 fs->fs_fmod = 0; 500 sbdirty(); 501 } else 502 markclean = 0; 503 } 504 #ifdef PROGRESS 505 if (!preen) 506 progress_done(); 507 #endif /* PROGRESS */ 508 } 509 510 void 511 print_bmap(u_char *map, uint32_t size) 512 { 513 uint32_t i, j; 514 515 i = 0; 516 while (i < size) { 517 printf("%u: ",i); 518 for (j = 0; j < 16; j++, i++) 519 printf("%2x ", (u_int)map[i] & 0xff); 520 printf("\n"); 521 } 522 } 523