1 /* 2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7 /* All Rights Reserved */ 8 9 /* 10 * Copyright (c) 1980, 1986, 1990 The Regents of the University of California. 11 * All rights reserved. 12 * 13 * Redistribution and use in source and binary forms are permitted 14 * provided that: (1) source distributions retain this entire copyright 15 * notice and comment, and (2) distributions including binaries display 16 * the following acknowledgement: ``This product includes software 17 * developed by the University of California, Berkeley and its contributors'' 18 * in the documentation or other materials provided with the distribution 19 * and in all advertising materials mentioning features or use of this 20 * software. Neither the name of the University nor the names of its 21 * contributors may be used to endorse or promote products derived 22 * from this software without specific prior written permission. 23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 26 */ 27 28 #pragma ident "%Z%%M% %I% %E% SMI" 29 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <unistd.h> 33 #include <string.h> 34 #include <sys/param.h> 35 #include <sys/mntent.h> 36 #include <sys/fs/ufs_fs.h> 37 #include <sys/vnode.h> 38 #include <sys/fs/ufs_inode.h> 39 #include "fsck.h" 40 41 static int check_maps(uchar_t *, uchar_t *, int, int, char *, int, int); 42 43 void 44 pass5(void) 45 { 46 caddr_t err; 47 int32_t c, blk, frags; 48 int cg_fatal; 49 size_t basesize, sumsize, mapsize; 50 int excessdirs; 51 int inomapsize, blkmapsize; 52 int update_csums, bad_csum, update_bitmaps; 53 struct fs *fs = &sblock; 54 struct cg *cg = &cgrp; 55 diskaddr_t dbase, dmax; 56 diskaddr_t d; 57 uint64_t i, j; 58 struct csum *cs; 59 struct csum backup_cs; 60 time_t now; 61 struct csum cstotal; 62 struct inodesc idesc; 63 union { /* keep lint happy about alignment */ 64 struct cg cg; /* the rest of buf has the bitmaps */ 65 char buf[MAXBSIZE]; 66 } u; 67 caddr_t buf = u.buf; 68 struct cg *newcg = &u.cg; 69 70 (void) memset((void *)buf, 0, sizeof (u.buf)); 71 newcg->cg_niblk = fs->fs_ipg; 72 73 if (fs->fs_postblformat != FS_DYNAMICPOSTBLFMT) { 74 pfatal("UNSUPPORTED ROTATIONAL TABLE FORMAT %d\n", 75 fs->fs_postblformat); 76 errexit("Program terminated."); 77 /* NOTREACHED */ 78 } 79 80 /* LINTED this subtraction can't overflow and is int32-aligned */ 81 basesize = &newcg->cg_space[0] - (uchar_t *)newcg; 82 83 /* 84 * We reserve the space for the old rotation summary 85 * tables for the benefit of old kernels, but do not 86 * maintain them in modern kernels. In time, they could 87 * theoretically go away, if we wanted to deal with 88 * changing the on-disk format. 89 */ 90 91 /* 92 * Note that we don't use any of the cg_*() macros until 93 * after cg_sanity() has approved of what we've got. 94 */ 95 newcg->cg_btotoff = basesize; 96 newcg->cg_boff = newcg->cg_btotoff + fs->fs_cpg * sizeof (daddr32_t); 97 newcg->cg_iusedoff = newcg->cg_boff + 98 fs->fs_cpg * fs->fs_nrpos * sizeof (uint16_t); 99 (void) memset(&newcg->cg_space[0], 0, newcg->cg_iusedoff - basesize); 100 101 inomapsize = howmany(fs->fs_ipg, NBBY); 102 newcg->cg_freeoff = newcg->cg_iusedoff + inomapsize; 103 blkmapsize = howmany(fs->fs_fpg, NBBY); 104 newcg->cg_nextfreeoff = newcg->cg_freeoff + blkmapsize; 105 newcg->cg_magic = CG_MAGIC; 106 107 sumsize = newcg->cg_iusedoff - newcg->cg_btotoff; 108 mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff; 109 110 init_inodesc(&idesc); 111 idesc.id_type = ADDR; 112 (void) memset((void *)&cstotal, 0, sizeof (struct csum)); 113 now = time(NULL); 114 115 /* 116 * If the last fragments in the file system don't make up a 117 * full file system block, mark the bits in the blockmap 118 * that correspond to those missing fragments as "allocated", 119 * so that the last block doesn't get counted as a free block 120 * and those missing fragments don't get counted as free frags. 121 */ 122 j = blknum(fs, (uint64_t)fs->fs_size + fs->fs_frag - 1); 123 for (i = fs->fs_size; i < j; i++) 124 setbmap(i); 125 126 /* 127 * The cg summaries are not always updated when using 128 * logging. Since we're really concerned with getting a 129 * sane filesystem, rather than in trying to debug UFS 130 * corner cases, logically we would just always recompute 131 * them. However, it is disconcerting to users to be asked 132 * about updating the summaries when, from their point of 133 * view, there's been no indication of a problem up to this 134 * point. So, only do it if we find a discrepancy. 135 */ 136 update_csums = -1; 137 update_bitmaps = 0; 138 for (c = 0; c < fs->fs_ncg; c++) { 139 backup_cs = cstotal; 140 141 /* 142 * cg_sanity() will catch i/o errors for us. 143 */ 144 (void) getblk(&cgblk, (diskaddr_t)cgtod(fs, c), 145 (size_t)fs->fs_cgsize); 146 err = cg_sanity(cg, c, &cg_fatal); 147 if (err != NULL) { 148 pfatal("CG %d: %s\n", c, err); 149 free((void *)err); 150 if (cg_fatal) 151 errexit( 152 "Irreparable cylinder group header problem. Program terminated."); 153 if (reply("REPAIR") == 0) 154 errexit("Program terminated."); 155 fix_cg(cg, c); 156 } 157 /* 158 * If the on-disk timestamp is in the future, then it 159 * by definition is wrong. Otherwise, if it's in 160 * the past, then use that value so that we don't 161 * declare a spurious mismatch. 162 */ 163 if (now > cg->cg_time) 164 newcg->cg_time = cg->cg_time; 165 else 166 newcg->cg_time = now; 167 newcg->cg_cgx = c; 168 dbase = cgbase(fs, c); 169 dmax = dbase + fs->fs_fpg; 170 if (dmax > fs->fs_size) 171 dmax = fs->fs_size; 172 newcg->cg_ndblk = dmax - dbase; 173 if (c == fs->fs_ncg - 1) 174 newcg->cg_ncyl = fs->fs_ncyl - (fs->fs_cpg * c); 175 else 176 newcg->cg_ncyl = fs->fs_cpg; 177 newcg->cg_niblk = sblock.fs_ipg; 178 newcg->cg_cs.cs_ndir = 0; 179 newcg->cg_cs.cs_nffree = 0; 180 newcg->cg_cs.cs_nbfree = 0; 181 newcg->cg_cs.cs_nifree = fs->fs_ipg; 182 if ((cg->cg_rotor >= 0) && (cg->cg_rotor < newcg->cg_ndblk)) 183 newcg->cg_rotor = cg->cg_rotor; 184 else 185 newcg->cg_rotor = 0; 186 if ((cg->cg_frotor >= 0) && (cg->cg_frotor < newcg->cg_ndblk)) 187 newcg->cg_frotor = cg->cg_frotor; 188 else 189 newcg->cg_frotor = 0; 190 if ((cg->cg_irotor >= 0) && (cg->cg_irotor < newcg->cg_niblk)) 191 newcg->cg_irotor = cg->cg_irotor; 192 else 193 newcg->cg_irotor = 0; 194 (void) memset((void *)&newcg->cg_frsum[0], 0, 195 sizeof (newcg->cg_frsum)); 196 (void) memset((void *)cg_inosused(newcg), 0, (size_t)mapsize); 197 /* LINTED macro is int32-aligned per newcg->cg_btotoff above */ 198 (void) memset((void *)&cg_blktot(newcg)[0], 0, 199 sumsize + mapsize); 200 j = fs->fs_ipg * c; 201 for (i = 0; i < fs->fs_ipg; j++, i++) { 202 switch (statemap[j] & ~(INORPHAN | INDELAYD)) { 203 204 case USTATE: 205 break; 206 207 case DSTATE: 208 case DCLEAR: 209 case DFOUND: 210 case DZLINK: 211 newcg->cg_cs.cs_ndir++; 212 /* FALLTHROUGH */ 213 214 case FSTATE: 215 case FCLEAR: 216 case FZLINK: 217 case SSTATE: 218 case SCLEAR: 219 newcg->cg_cs.cs_nifree--; 220 setbit(cg_inosused(newcg), i); 221 break; 222 223 default: 224 if (j < UFSROOTINO) 225 break; 226 errexit("BAD STATE 0x%x FOR INODE I=%d", 227 statemap[j], (int)j); 228 } 229 } 230 if (c == 0) { 231 for (i = 0; i < UFSROOTINO; i++) { 232 setbit(cg_inosused(newcg), i); 233 newcg->cg_cs.cs_nifree--; 234 } 235 } 236 /* 237 * Count up what fragments and blocks are free, and 238 * reflect the relevant section of blockmap[] into 239 * newcg's map. 240 */ 241 for (i = 0, d = dbase; 242 d < dmax; 243 d += fs->fs_frag, i += fs->fs_frag) { 244 frags = 0; 245 for (j = 0; j < fs->fs_frag; j++) { 246 if (testbmap(d + j)) 247 continue; 248 setbit(cg_blksfree(newcg), i + j); 249 frags++; 250 } 251 if (frags == fs->fs_frag) { 252 newcg->cg_cs.cs_nbfree++; 253 j = cbtocylno(fs, i); 254 /* LINTED macro is int32-aligned per above */ 255 cg_blktot(newcg)[j]++; 256 /* LINTED cg_blks(newcg) is aligned */ 257 cg_blks(fs, newcg, j)[cbtorpos(fs, i)]++; 258 } else if (frags > 0) { 259 newcg->cg_cs.cs_nffree += frags; 260 blk = blkmap(fs, cg_blksfree(newcg), i); 261 fragacct(fs, blk, newcg->cg_frsum, 1); 262 } 263 } 264 cstotal.cs_nffree += newcg->cg_cs.cs_nffree; 265 cstotal.cs_nbfree += newcg->cg_cs.cs_nbfree; 266 cstotal.cs_nifree += newcg->cg_cs.cs_nifree; 267 cstotal.cs_ndir += newcg->cg_cs.cs_ndir; 268 269 /* 270 * Note that, just like the kernel, we dynamically 271 * allocated an array to hold the csums and stuffed 272 * the pointer into the in-core superblock's fs_u.fs_csp 273 * field. This means that the fs_u field contains a 274 * random value when the disk version is examined, but 275 * fs_cs() gives us a valid pointer nonetheless. 276 */ 277 cs = &fs->fs_cs(fs, c); 278 bad_csum = (memcmp((void *)cs, (void *)&newcg->cg_cs, 279 sizeof (*cs)) != 0); 280 281 /* 282 * Has the user told us what to do yet? If not, find out. 283 */ 284 if (bad_csum && (update_csums == -1)) { 285 if (preen) { 286 update_csums = 1; 287 (void) printf("CORRECTING BAD CG SUMMARIES\n"); 288 } else if (update_csums == -1) { 289 update_csums = (reply( 290 "CORRECT BAD CG SUMMARIES") == 1); 291 } 292 } 293 294 if (bad_csum && (update_csums == 1)) { 295 (void) memmove((void *)cs, (void *)&newcg->cg_cs, 296 sizeof (*cs)); 297 sbdirty(); 298 299 (void) memmove((void *)cg, (void *)newcg, 300 (size_t)basesize); 301 /* LINTED per cg_sanity() */ 302 (void) memmove((void *)&cg_blktot(cg)[0], 303 /* LINTED macro aligned as above */ 304 (void *)&cg_blktot(newcg)[0], sumsize); 305 cgdirty(); 306 (void) printf("CORRECTED SUMMARY FOR CG %d\n", c); 307 } 308 309 excessdirs = cg->cg_cs.cs_ndir - newcg->cg_cs.cs_ndir; 310 if (excessdirs < 0) { 311 pfatal("LOST %d DIRECTORIES IN CG %d\n", 312 -excessdirs, c); 313 excessdirs = 0; 314 } 315 if (excessdirs > 0) { 316 if (check_maps((uchar_t *)cg_inosused(newcg), 317 (uchar_t *)cg_inosused(cg), inomapsize, 318 cg->cg_cgx * fs->fs_ipg, "DIR", 0, excessdirs)) { 319 if (!verbose) 320 (void) printf("DIR BITMAP WRONG "); 321 if (preen || update_bitmaps || 322 reply("FIX") == 1) { 323 (void) memmove((void *)cg_inosused(cg), 324 (void *)cg_inosused(newcg), 325 inomapsize); 326 cgdirty(); 327 if (preen || 328 (!verbose && update_bitmaps)) 329 (void) printf("(CORRECTED)\n"); 330 update_bitmaps = 1; 331 } 332 } 333 } 334 335 if (check_maps((uchar_t *)cg_inosused(newcg), 336 (uchar_t *)cg_inosused(cg), inomapsize, 337 cg->cg_cgx * fs->fs_ipg, "FILE", excessdirs, fs->fs_ipg)) { 338 if (!verbose) 339 (void) printf("FILE BITMAP WRONG "); 340 if (preen || update_bitmaps || reply("FIX") == 1) { 341 (void) memmove((void *)cg_inosused(cg), 342 (void *)cg_inosused(newcg), inomapsize); 343 cgdirty(); 344 if (preen || 345 (!verbose && update_bitmaps)) 346 (void) printf("(CORRECTED)\n"); 347 update_bitmaps = 1; 348 } 349 } 350 351 if (check_maps((uchar_t *)cg_blksfree(cg), 352 (uchar_t *)cg_blksfree(newcg), blkmapsize, 353 cg->cg_cgx * fs->fs_fpg, "FRAG", 0, fs->fs_fpg)) { 354 if (!verbose) 355 (void) printf("FRAG BITMAP WRONG "); 356 if (preen || update_bitmaps || reply("FIX") == 1) { 357 (void) memmove((void *)cg_blksfree(cg), 358 (void *)cg_blksfree(newcg), blkmapsize); 359 cgdirty(); 360 if (preen || 361 (!verbose && update_bitmaps)) 362 (void) printf("(CORRECTED)\n"); 363 update_bitmaps = 1; 364 } 365 } 366 367 /* 368 * Fixing one set of problems often shows up more in the 369 * same cg. Just to make sure, go back and check it 370 * again if we found something this time through. 371 */ 372 if (cgisdirty()) { 373 cgflush(); 374 cstotal = backup_cs; 375 c--; 376 } 377 } 378 379 if ((fflag || !(islog && islogok)) && 380 (memcmp((void *)&cstotal, (void *)&fs->fs_cstotal, 381 sizeof (struct csum)) != 0)) { 382 if (dofix(&idesc, "CORRECT GLOBAL SUMMARY")) { 383 (void) memmove((void *)&fs->fs_cstotal, 384 (void *)&cstotal, sizeof (struct csum)); 385 fs->fs_ronly = 0; 386 fs->fs_fmod = 0; 387 sbdirty(); 388 } else { 389 iscorrupt = 1; 390 } 391 } 392 } 393 394 /* 395 * Compare two allocation bitmaps, reporting any discrepancies. 396 * 397 * If a mismatch is found, if the bit is set in map1, it's considered 398 * to be an indication that the corresponding resource is supposed 399 * to be free, but isn't. Otherwise, it's considered marked as allocated 400 * but not found to be so. In other words, if the two maps being compared 401 * use a set bit to indicate something is free, pass the on-disk map 402 * first. Otherwise, pass the calculated map first. 403 */ 404 static int 405 check_maps( 406 uchar_t *map1, /* map of claimed allocations */ 407 uchar_t *map2, /* map of determined allocations */ 408 int mapsize, /* size of above two maps */ 409 int startvalue, /* resource value for first element in map */ 410 char *name, /* name of resource found in maps */ 411 int skip, /* number of entries to skip before starting to free */ 412 int limit) /* limit on number of entries to free */ 413 { 414 long i, j, k, l, m, n, size; 415 int astart, aend, ustart, uend; 416 int mismatch; 417 418 mismatch = 0; 419 astart = ustart = aend = uend = -1; 420 for (i = 0; i < mapsize; i++) { 421 j = *map1++; 422 k = *map2++; 423 if (j == k) 424 continue; 425 for (m = 0, l = 1; m < NBBY; m++, l <<= 1) { 426 if ((j & l) == (k & l)) 427 continue; 428 n = startvalue + i * NBBY + m; 429 if ((j & l) != 0) { 430 if (astart == -1) { 431 astart = aend = n; 432 continue; 433 } 434 if (aend + 1 == n) { 435 aend = n; 436 continue; 437 } 438 if (verbose) { 439 if (astart == aend) 440 pwarn( 441 "ALLOCATED %s %d WAS MARKED FREE ON DISK\n", 442 name, astart); 443 else 444 pwarn( 445 "ALLOCATED %sS %d-%d WERE MARKED FREE ON DISK\n", 446 name, astart, aend); 447 } 448 mismatch = 1; 449 astart = aend = n; 450 } else { 451 if (ustart == -1) { 452 ustart = uend = n; 453 continue; 454 } 455 if (uend + 1 == n) { 456 uend = n; 457 continue; 458 } 459 size = uend - ustart + 1; 460 if (size <= skip) { 461 skip -= size; 462 ustart = uend = n; 463 continue; 464 } 465 if (skip > 0) { 466 ustart += skip; 467 size -= skip; 468 skip = 0; 469 } 470 if (size > limit) 471 size = limit; 472 if (verbose) { 473 if (size == 1) 474 pwarn( 475 "UNALLOCATED %s %d WAS MARKED USED ON DISK\n", 476 name, ustart); 477 else 478 pwarn( 479 "UNALLOCATED %sS %d-%ld WERE MARKED USED ON DISK\n", 480 name, ustart, 481 ustart + size - 1); 482 } 483 mismatch = 1; 484 limit -= size; 485 if (limit <= 0) 486 return (mismatch); 487 ustart = uend = n; 488 } 489 } 490 } 491 if (astart != -1) { 492 if (verbose) { 493 if (astart == aend) 494 pwarn( 495 "ALLOCATED %s %d WAS MARKED FREE ON DISK\n", 496 name, astart); 497 else 498 pwarn( 499 "ALLOCATED %sS %d-%d WERE MARKED FREE ON DISK\n", 500 name, astart, aend); 501 } 502 mismatch = 1; 503 } 504 if (ustart != -1) { 505 size = uend - ustart + 1; 506 if (size <= skip) 507 return (mismatch); 508 if (skip > 0) { 509 ustart += skip; 510 size -= skip; 511 } 512 if (size > limit) 513 size = limit; 514 if (verbose) { 515 if (size == 1) 516 pwarn( 517 "UNALLOCATED %s %d WAS MARKED USED ON DISK\n", 518 name, ustart); 519 else 520 pwarn( 521 "UNALLOCATED %sS %d-%ld WERE MARKED USED ON DISK\n", 522 name, ustart, ustart + size - 1); 523 } 524 mismatch = 1; 525 } 526 return (mismatch); 527 } 528