1 /* $NetBSD: pass5.c,v 1.27 2001/08/17 02:18:47 lukem 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.27 2001/08/17 02:18:47 lukem 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() 65 { 66 int c, blk, frags, basesize, sumsize, mapsize, savednrpos = 0; 67 int inomapsize, blkmapsize; 68 struct fs *fs = sblock; 69 ufs_daddr_t dbase, dmax; 70 ufs_daddr_t d; 71 long i, j, k; 72 struct csum *cs; 73 struct csum 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; 79 80 statemap[WINO] = 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 switch ((int)fs->fs_postblformat) { 128 129 case FS_42POSTBLFMT: 130 basesize = (char *)(&ocg->cg_btot[0]) - 131 (char *)(&ocg->cg_firstfield); 132 sumsize = &ocg->cg_iused[0] - (u_int8_t *)(&ocg->cg_btot[0]); 133 mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] - 134 (u_char *)&ocg->cg_iused[0]; 135 blkmapsize = howmany(fs->fs_fpg, NBBY); 136 inomapsize = &ocg->cg_free[0] - (u_char *)&ocg->cg_iused[0]; 137 ocg->cg_magic = CG_MAGIC; 138 savednrpos = fs->fs_nrpos; 139 fs->fs_nrpos = 8; 140 break; 141 142 case FS_DYNAMICPOSTBLFMT: 143 newcg->cg_btotoff = 144 &newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield); 145 newcg->cg_boff = 146 newcg->cg_btotoff + fs->fs_cpg * sizeof(int32_t); 147 newcg->cg_iusedoff = newcg->cg_boff + 148 fs->fs_cpg * fs->fs_nrpos * sizeof(int16_t); 149 newcg->cg_freeoff = 150 newcg->cg_iusedoff + howmany(fs->fs_ipg, NBBY); 151 inomapsize = newcg->cg_freeoff - newcg->cg_iusedoff; 152 newcg->cg_nextfreeoff = newcg->cg_freeoff + 153 howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY); 154 blkmapsize = newcg->cg_nextfreeoff - newcg->cg_freeoff; 155 if (fs->fs_contigsumsize > 0) { 156 newcg->cg_clustersumoff = newcg->cg_nextfreeoff - 157 sizeof(int32_t); 158 newcg->cg_clustersumoff = 159 roundup(newcg->cg_clustersumoff, sizeof(int32_t)); 160 newcg->cg_clusteroff = newcg->cg_clustersumoff + 161 (fs->fs_contigsumsize + 1) * sizeof(int32_t); 162 newcg->cg_nextfreeoff = newcg->cg_clusteroff + 163 howmany(fs->fs_cpg * fs->fs_spc / NSPB(fs), NBBY); 164 } 165 newcg->cg_magic = CG_MAGIC; 166 basesize = &newcg->cg_space[0] - 167 (u_char *)(&newcg->cg_firstfield); 168 sumsize = newcg->cg_iusedoff - newcg->cg_btotoff; 169 mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff; 170 break; 171 172 default: 173 inomapsize = blkmapsize = sumsize = 0; /* keep lint happy */ 174 errx(EEXIT, "UNKNOWN ROTATIONAL TABLE FORMAT %d", 175 fs->fs_postblformat); 176 } 177 memset(&idesc[0], 0, sizeof idesc); 178 for (i = 0; i < 4; i++) { 179 idesc[i].id_type = ADDR; 180 if (doinglevel2) 181 idesc[i].id_fix = FIX; 182 } 183 memset(&cstotal, 0, sizeof(struct csum)); 184 j = blknum(fs, fs->fs_size + fs->fs_frag - 1); 185 for (i = fs->fs_size; i < j; i++) 186 setbmap(i); 187 for (c = 0; c < fs->fs_ncg; c++) { 188 getblk(&cgblk, cgtod(fs, c), fs->fs_cgsize); 189 memcpy(cg, cgblk.b_un.b_cg, fs->fs_cgsize); 190 if((doswap && !needswap) || (!doswap && needswap)) 191 swap_cg(cgblk.b_un.b_cg, cg); 192 if (!cg_chkmagic(cg, 0)) 193 pfatal("CG %d: PASS5: BAD MAGIC NUMBER\n", c); 194 if(doswap) 195 cgdirty(); 196 /* 197 * While we have the disk head where we want it, 198 * write back the superblock to the spare at this 199 * cylinder group. 200 */ 201 if ((cvtlevel && sblk.b_dirty) || doswap) { 202 bwrite(fswritefd, sblk.b_un.b_buf, 203 fsbtodb(sblock, cgsblock(sblock, c)), 204 sblock->fs_sbsize); 205 } else { 206 /* 207 * Read in the current alternate superblock, 208 * and compare it to the master. If it's 209 * wrong, fix it up. 210 */ 211 getblk(&asblk, cgsblock(sblock, c), sblock->fs_sbsize); 212 if (asblk.b_errs) 213 pfatal("CG %d: UNABLE TO READ ALTERNATE " 214 "SUPERBLK\n", c); 215 else { 216 memmove(altsblock, asblk.b_un.b_fs, 217 sblock->fs_sbsize); 218 if (needswap) 219 ffs_sb_swap(asblk.b_un.b_fs, altsblock); 220 } 221 if ((asblk.b_errs || cmpsblks(sblock, altsblock)) && 222 dofix(&idesc[3], 223 "ALTERNATE SUPERBLK(S) ARE INCORRECT")) { 224 bwrite(fswritefd, sblk.b_un.b_buf, 225 fsbtodb(sblock, cgsblock(sblock, c)), 226 sblock->fs_sbsize); 227 } 228 } 229 dbase = cgbase(fs, c); 230 dmax = dbase + fs->fs_fpg; 231 if (dmax > fs->fs_size) 232 dmax = fs->fs_size; 233 newcg->cg_time = cg->cg_time; 234 newcg->cg_cgx = c; 235 if (c == fs->fs_ncg - 1) 236 newcg->cg_ncyl = fs->fs_ncyl % fs->fs_cpg; 237 else 238 newcg->cg_ncyl = fs->fs_cpg; 239 newcg->cg_ndblk = dmax - dbase; 240 if (fs->fs_contigsumsize > 0) 241 newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag; 242 newcg->cg_cs.cs_ndir = 0; 243 newcg->cg_cs.cs_nffree = 0; 244 newcg->cg_cs.cs_nbfree = 0; 245 newcg->cg_cs.cs_nifree = fs->fs_ipg; 246 if (cg->cg_rotor >= 0 && cg->cg_rotor < newcg->cg_ndblk) 247 newcg->cg_rotor = cg->cg_rotor; 248 else 249 newcg->cg_rotor = 0; 250 if (cg->cg_frotor >= 0 && cg->cg_frotor < newcg->cg_ndblk) 251 newcg->cg_frotor = cg->cg_frotor; 252 else 253 newcg->cg_frotor = 0; 254 if (cg->cg_irotor >= 0 && cg->cg_irotor < newcg->cg_niblk) 255 newcg->cg_irotor = cg->cg_irotor; 256 else 257 newcg->cg_irotor = 0; 258 memset(&newcg->cg_frsum[0], 0, sizeof newcg->cg_frsum); 259 memset(&cg_blktot(newcg, 0)[0], 0, 260 (size_t)(sumsize + mapsize)); 261 if (fs->fs_postblformat == FS_42POSTBLFMT) 262 ocg->cg_magic = CG_MAGIC; 263 j = fs->fs_ipg * c; 264 for (i = 0; i < fs->fs_ipg; j++, i++) { 265 switch (statemap[j]) { 266 267 case USTATE: 268 break; 269 270 case DSTATE: 271 case DCLEAR: 272 case DFOUND: 273 newcg->cg_cs.cs_ndir++; 274 /* fall through */ 275 276 case FSTATE: 277 case FCLEAR: 278 newcg->cg_cs.cs_nifree--; 279 setbit(cg_inosused(newcg, 0), i); 280 break; 281 282 default: 283 if (j < ROOTINO) 284 break; 285 errx(EEXIT, "BAD STATE %d FOR INODE I=%ld", 286 statemap[j], (long)j); 287 } 288 } 289 if (c == 0) 290 for (i = 0; i < ROOTINO; i++) { 291 setbit(cg_inosused(newcg, 0), i); 292 newcg->cg_cs.cs_nifree--; 293 } 294 for (i = 0, d = dbase; 295 d < dmax; 296 d += fs->fs_frag, i += fs->fs_frag) { 297 frags = 0; 298 for (j = 0; j < fs->fs_frag; j++) { 299 if (testbmap(d + j)) 300 continue; 301 setbit(cg_blksfree(newcg, 0), i + j); 302 frags++; 303 } 304 if (frags == fs->fs_frag) { 305 newcg->cg_cs.cs_nbfree++; 306 j = cbtocylno(fs, i); 307 cg_blktot(newcg, 0)[j]++; 308 cg_blks(fs, newcg, j, 0)[cbtorpos(fs, i)]++; 309 if (fs->fs_contigsumsize > 0) 310 setbit(cg_clustersfree(newcg, 0), 311 i / fs->fs_frag); 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 memcmp(&cg_blktot(newcg, 0)[0], 366 &cg_blktot(cg, 0)[0], sumsize) != 0) { 367 if (dofix(&idesc[2], "SUMMARY INFORMATION BAD")) { 368 memmove(cg, newcg, (size_t)basesize); 369 memmove(&cg_blktot(cg, 0)[0], 370 &cg_blktot(newcg, 0)[0], (size_t)sumsize); 371 cgdirty(); 372 } else 373 markclean = 0; 374 } 375 if (usedsoftdep) { 376 for (i = 0; i < inomapsize; i++) { 377 j = cg_inosused(newcg, 0)[i]; 378 if ((cg_inosused(cg, 0)[i] & j) == j) 379 continue; 380 for (k = 0; k < NBBY; k++) { 381 if ((j & (1 << k)) == 0) 382 continue; 383 if (cg_inosused(cg, 0)[i] & (1 << k)) 384 continue; 385 pwarn("ALLOCATED INODE %ld " 386 "MARKED FREE\n", 387 c * fs->fs_ipg + i * 8 + k); 388 } 389 } 390 for (i = 0; i < blkmapsize; i++) { 391 j = cg_blksfree(cg, 0)[i]; 392 if ((cg_blksfree(newcg, 0)[i] & j) == j) 393 continue; 394 for (k = 0; k < NBBY; k++) { 395 if ((j & (1 << k)) == 0) 396 continue; 397 if (cg_inosused(cg, 0)[i] & (1 << k)) 398 continue; 399 pwarn("ALLOCATED FRAG %ld " 400 "MARKED FREE\n", 401 c * fs->fs_fpg + i * 8 + k); 402 } 403 } 404 } 405 if (memcmp(cg_inosused(newcg, 0), cg_inosused(cg, 0), mapsize) 406 != 0 && dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) { 407 memmove(cg_inosused(cg, 0), cg_inosused(newcg, 0), 408 (size_t)mapsize); 409 cgdirty(); 410 } 411 } 412 if (fs->fs_postblformat == FS_42POSTBLFMT) 413 fs->fs_nrpos = savednrpos; 414 if (memcmp(&cstotal, &fs->fs_cstotal, sizeof *cs) != 0) { 415 if (dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) { 416 memmove(&fs->fs_cstotal, &cstotal, sizeof *cs); 417 fs->fs_ronly = 0; 418 fs->fs_fmod = 0; 419 sbdirty(); 420 } else 421 markclean = 0; 422 } 423 } 424 425 void 426 print_bmap(map, size) 427 u_char *map; 428 u_int32_t size; 429 { 430 int i, j; 431 432 i = 0; 433 while (i < size) { 434 printf("%u: ",i); 435 for (j = 0; j < 16; j++, i++) 436 printf("%2x ", (u_int)map[i] & 0xff); 437 printf("\n"); 438 } 439 } 440