1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 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 #if 0 33 #ifndef lint 34 static const char sccsid[] = "@(#)utilities.c 8.6 (Berkeley) 5/19/95"; 35 #endif /* not lint */ 36 #endif 37 #include <sys/cdefs.h> 38 __FBSDID("$FreeBSD$"); 39 40 #include <sys/param.h> 41 #include <sys/time.h> 42 #include <sys/types.h> 43 #include <sys/sysctl.h> 44 #include <sys/disk.h> 45 #include <sys/disklabel.h> 46 #include <sys/ioctl.h> 47 #include <sys/stat.h> 48 49 #include <ufs/ufs/dinode.h> 50 #include <ufs/ufs/dir.h> 51 #include <ufs/ffs/fs.h> 52 53 #include <err.h> 54 #include <errno.h> 55 #include <string.h> 56 #include <ctype.h> 57 #include <fstab.h> 58 #include <stdint.h> 59 #include <stdio.h> 60 #include <stdlib.h> 61 #include <time.h> 62 #include <unistd.h> 63 #include <libufs.h> 64 65 #include "fsck.h" 66 67 int sujrecovery = 0; 68 69 static struct bufarea *allocbuf(const char *); 70 static void cg_write(struct bufarea *); 71 static void slowio_start(void); 72 static void slowio_end(void); 73 static void printIOstats(void); 74 75 static long diskreads, totaldiskreads, totalreads; /* Disk cache statistics */ 76 static struct timespec startpass, finishpass; 77 struct timeval slowio_starttime; 78 int slowio_delay_usec = 10000; /* Initial IO delay for background fsck */ 79 int slowio_pollcnt; 80 static struct bufarea cgblk; /* backup buffer for cylinder group blocks */ 81 static struct bufarea failedbuf; /* returned by failed getdatablk() */ 82 static TAILQ_HEAD(bufqueue, bufarea) bufqueuehd; /* head of buffer cache LRU */ 83 static LIST_HEAD(bufhash, bufarea) bufhashhd[HASHSIZE]; /* buffer hash list */ 84 static struct bufhash freebufs; /* unused buffers */ 85 static int numbufs; /* size of buffer cache */ 86 static int cachelookups; /* number of cache lookups */ 87 static int cachereads; /* number of cache reads */ 88 static int flushtries; /* number of tries to reclaim memory */ 89 90 char *buftype[BT_NUMBUFTYPES] = BT_NAMES; 91 92 void 93 fsutilinit(void) 94 { 95 diskreads = totaldiskreads = totalreads = 0; 96 bzero(&startpass, sizeof(struct timespec)); 97 bzero(&finishpass, sizeof(struct timespec)); 98 bzero(&slowio_starttime, sizeof(struct timeval)); 99 slowio_delay_usec = 10000; 100 slowio_pollcnt = 0; 101 flushtries = 0; 102 } 103 104 int 105 ftypeok(union dinode *dp) 106 { 107 switch (DIP(dp, di_mode) & IFMT) { 108 109 case IFDIR: 110 case IFREG: 111 case IFBLK: 112 case IFCHR: 113 case IFLNK: 114 case IFSOCK: 115 case IFIFO: 116 return (1); 117 118 default: 119 if (debug) 120 printf("bad file type 0%o\n", DIP(dp, di_mode)); 121 return (0); 122 } 123 } 124 125 int 126 reply(const char *question) 127 { 128 int persevere; 129 char c; 130 131 if (preen) 132 pfatal("INTERNAL ERROR: GOT TO reply()"); 133 persevere = strcmp(question, "CONTINUE") == 0 || 134 strcmp(question, "LOOK FOR ALTERNATE SUPERBLOCKS") == 0; 135 printf("\n"); 136 if (!persevere && (nflag || (fswritefd < 0 && bkgrdflag == 0))) { 137 printf("%s? no\n\n", question); 138 resolved = 0; 139 return (0); 140 } 141 if (yflag || (persevere && nflag)) { 142 printf("%s? yes\n\n", question); 143 return (1); 144 } 145 do { 146 printf("%s? [yn] ", question); 147 (void) fflush(stdout); 148 c = getc(stdin); 149 while (c != '\n' && getc(stdin) != '\n') { 150 if (feof(stdin)) { 151 resolved = 0; 152 return (0); 153 } 154 } 155 } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N'); 156 printf("\n"); 157 if (c == 'y' || c == 'Y') 158 return (1); 159 resolved = 0; 160 return (0); 161 } 162 163 /* 164 * Look up state information for an inode. 165 */ 166 struct inostat * 167 inoinfo(ino_t inum) 168 { 169 static struct inostat unallocated = { USTATE, 0, 0, 0 }; 170 struct inostatlist *ilp; 171 int iloff; 172 173 if (inum > maxino) 174 errx(EEXIT, "inoinfo: inumber %ju out of range", 175 (uintmax_t)inum); 176 ilp = &inostathead[inum / sblock.fs_ipg]; 177 iloff = inum % sblock.fs_ipg; 178 if (iloff >= ilp->il_numalloced) 179 return (&unallocated); 180 return (&ilp->il_stat[iloff]); 181 } 182 183 /* 184 * Malloc buffers and set up cache. 185 */ 186 void 187 bufinit(void) 188 { 189 int i; 190 191 initbarea(&failedbuf, BT_UNKNOWN); 192 failedbuf.b_errs = -1; 193 failedbuf.b_un.b_buf = NULL; 194 if ((cgblk.b_un.b_buf = Malloc((unsigned int)sblock.fs_bsize)) == NULL) 195 errx(EEXIT, "Initial malloc(%d) failed", sblock.fs_bsize); 196 initbarea(&cgblk, BT_CYLGRP); 197 numbufs = cachelookups = cachereads = 0; 198 TAILQ_INIT(&bufqueuehd); 199 LIST_INIT(&freebufs); 200 for (i = 0; i < HASHSIZE; i++) 201 LIST_INIT(&bufhashhd[i]); 202 for (i = 0; i < BT_NUMBUFTYPES; i++) { 203 readtime[i].tv_sec = totalreadtime[i].tv_sec = 0; 204 readtime[i].tv_nsec = totalreadtime[i].tv_nsec = 0; 205 readcnt[i] = totalreadcnt[i] = 0; 206 } 207 } 208 209 static struct bufarea * 210 allocbuf(const char *failreason) 211 { 212 struct bufarea *bp; 213 char *bufp; 214 215 bp = (struct bufarea *)Malloc(sizeof(struct bufarea)); 216 bufp = Malloc((unsigned int)sblock.fs_bsize); 217 if (bp == NULL || bufp == NULL) { 218 errx(EEXIT, "%s", failreason); 219 /* NOTREACHED */ 220 } 221 numbufs++; 222 bp->b_un.b_buf = bufp; 223 TAILQ_INSERT_HEAD(&bufqueuehd, bp, b_list); 224 initbarea(bp, BT_UNKNOWN); 225 return (bp); 226 } 227 228 /* 229 * Manage cylinder group buffers. 230 * 231 * Use getblk() here rather than cgget() because the cylinder group 232 * may be corrupted but we want it anyway so we can fix it. 233 */ 234 static struct bufarea *cgbufs; /* header for cylinder group cache */ 235 static int flushtries; /* number of tries to reclaim memory */ 236 237 struct bufarea * 238 cglookup(int cg) 239 { 240 struct bufarea *cgbp; 241 struct cg *cgp; 242 243 if ((unsigned) cg >= sblock.fs_ncg) 244 errx(EEXIT, "cglookup: out of range cylinder group %d", cg); 245 if (cgbufs == NULL) { 246 cgbufs = calloc(sblock.fs_ncg, sizeof(struct bufarea)); 247 if (cgbufs == NULL) 248 errx(EEXIT, "Cannot allocate cylinder group buffers"); 249 } 250 cgbp = &cgbufs[cg]; 251 if (cgbp->b_un.b_cg != NULL) 252 return (cgbp); 253 cgp = NULL; 254 if (flushtries == 0) 255 cgp = Malloc((unsigned int)sblock.fs_cgsize); 256 if (cgp == NULL) { 257 if (sujrecovery) 258 errx(EEXIT,"Ran out of memory during journal recovery"); 259 flush(fswritefd, &cgblk); 260 getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize); 261 return (&cgblk); 262 } 263 cgbp->b_un.b_cg = cgp; 264 initbarea(cgbp, BT_CYLGRP); 265 getblk(cgbp, cgtod(&sblock, cg), sblock.fs_cgsize); 266 return (cgbp); 267 } 268 269 /* 270 * Mark a cylinder group buffer as dirty. 271 * Update its check-hash if they are enabled. 272 */ 273 void 274 cgdirty(struct bufarea *cgbp) 275 { 276 struct cg *cg; 277 278 cg = cgbp->b_un.b_cg; 279 if ((sblock.fs_metackhash & CK_CYLGRP) != 0) { 280 cg->cg_ckhash = 0; 281 cg->cg_ckhash = 282 calculate_crc32c(~0L, (void *)cg, sblock.fs_cgsize); 283 } 284 dirty(cgbp); 285 } 286 287 /* 288 * Attempt to flush a cylinder group cache entry. 289 * Return whether the flush was successful. 290 */ 291 int 292 flushentry(void) 293 { 294 struct bufarea *cgbp; 295 296 if (sujrecovery || flushtries == sblock.fs_ncg || cgbufs == NULL) 297 return (0); 298 cgbp = &cgbufs[flushtries++]; 299 if (cgbp->b_un.b_cg == NULL) 300 return (0); 301 flush(fswritefd, cgbp); 302 free(cgbp->b_un.b_buf); 303 cgbp->b_un.b_buf = NULL; 304 return (1); 305 } 306 307 /* 308 * Manage a cache of filesystem disk blocks. 309 */ 310 struct bufarea * 311 getdatablk(ufs2_daddr_t blkno, long size, int type) 312 { 313 struct bufarea *bp; 314 struct bufhash *bhdp; 315 316 cachelookups++; 317 /* 318 * If out of range, return empty buffer with b_err == -1 319 * 320 * Skip check for inodes because chkrange() considers 321 * metadata areas invalid to write data. 322 */ 323 if (type != BT_INODES && chkrange(blkno, size / sblock.fs_fsize)) { 324 failedbuf.b_refcnt++; 325 return (&failedbuf); 326 } 327 bhdp = &bufhashhd[HASH(blkno)]; 328 LIST_FOREACH(bp, bhdp, b_hash) 329 if (bp->b_bno == fsbtodb(&sblock, blkno)) { 330 if (debug && bp->b_size != size) { 331 prtbuf(bp, "getdatablk: size mismatch"); 332 pfatal("getdatablk: b_size %d != size %ld\n", 333 bp->b_size, size); 334 } 335 TAILQ_REMOVE(&bufqueuehd, bp, b_list); 336 goto foundit; 337 } 338 /* 339 * Move long-term busy buffer back to the front of the LRU so we 340 * do not endless inspect them for recycling. 341 */ 342 bp = TAILQ_LAST(&bufqueuehd, bufqueue); 343 if (bp != NULL && bp->b_refcnt != 0) { 344 TAILQ_REMOVE(&bufqueuehd, bp, b_list); 345 TAILQ_INSERT_HEAD(&bufqueuehd, bp, b_list); 346 } 347 /* 348 * Allocate up to the minimum number of buffers before 349 * considering recycling any of them. 350 */ 351 if (size > sblock.fs_bsize) 352 errx(EEXIT, "Excessive buffer size %ld > %d\n", size, 353 sblock.fs_bsize); 354 if ((bp = LIST_FIRST(&freebufs)) != NULL) { 355 LIST_REMOVE(bp, b_hash); 356 } else if (numbufs < MINBUFS) { 357 bp = allocbuf("cannot create minimal buffer pool"); 358 } else if (sujrecovery) { 359 /* 360 * SUJ recovery does not want anything written until it 361 * has successfully completed (so it can fail back to 362 * full fsck). Thus, we can only recycle clean buffers. 363 */ 364 TAILQ_FOREACH_REVERSE(bp, &bufqueuehd, bufqueue, b_list) 365 if ((bp->b_flags & B_DIRTY) == 0 && bp->b_refcnt == 0) 366 break; 367 if (bp == NULL) 368 bp = allocbuf("Ran out of memory during " 369 "journal recovery"); 370 else 371 LIST_REMOVE(bp, b_hash); 372 } else { 373 /* 374 * Recycle oldest non-busy buffer. 375 */ 376 TAILQ_FOREACH_REVERSE(bp, &bufqueuehd, bufqueue, b_list) 377 if (bp->b_refcnt == 0) 378 break; 379 if (bp == NULL) 380 bp = allocbuf("Ran out of memory for buffers"); 381 else 382 LIST_REMOVE(bp, b_hash); 383 } 384 TAILQ_REMOVE(&bufqueuehd, bp, b_list); 385 flush(fswritefd, bp); 386 bp->b_type = type; 387 LIST_INSERT_HEAD(bhdp, bp, b_hash); 388 getblk(bp, blkno, size); 389 cachereads++; 390 /* fall through */ 391 foundit: 392 TAILQ_INSERT_HEAD(&bufqueuehd, bp, b_list); 393 if (debug && bp->b_type != type) { 394 printf("getdatablk: buffer type changed to %s", 395 BT_BUFTYPE(type)); 396 prtbuf(bp, ""); 397 } 398 if (bp->b_errs == 0) 399 bp->b_refcnt++; 400 return (bp); 401 } 402 403 void 404 getblk(struct bufarea *bp, ufs2_daddr_t blk, long size) 405 { 406 ufs2_daddr_t dblk; 407 struct timespec start, finish; 408 409 dblk = fsbtodb(&sblock, blk); 410 if (bp->b_bno == dblk) { 411 totalreads++; 412 } else { 413 if (debug) { 414 readcnt[bp->b_type]++; 415 clock_gettime(CLOCK_REALTIME_PRECISE, &start); 416 } 417 bp->b_errs = blread(fsreadfd, bp->b_un.b_buf, dblk, size); 418 if (debug) { 419 clock_gettime(CLOCK_REALTIME_PRECISE, &finish); 420 timespecsub(&finish, &start, &finish); 421 timespecadd(&readtime[bp->b_type], &finish, 422 &readtime[bp->b_type]); 423 } 424 bp->b_bno = dblk; 425 bp->b_size = size; 426 } 427 } 428 429 void 430 brelse(struct bufarea *bp) 431 { 432 433 if (bp->b_refcnt <= 0) 434 prtbuf(bp, "brelse: buffer with negative reference count"); 435 bp->b_refcnt--; 436 } 437 438 void 439 binval(struct bufarea *bp) 440 { 441 442 bp->b_flags &= ~B_DIRTY; 443 LIST_REMOVE(bp, b_hash); 444 LIST_INSERT_HEAD(&freebufs, bp, b_hash); 445 } 446 447 void 448 flush(int fd, struct bufarea *bp) 449 { 450 struct inode ip; 451 452 if ((bp->b_flags & B_DIRTY) == 0) 453 return; 454 bp->b_flags &= ~B_DIRTY; 455 if (fswritefd < 0) { 456 pfatal("WRITING IN READ_ONLY MODE.\n"); 457 return; 458 } 459 if (bp->b_errs != 0) 460 pfatal("WRITING %sZERO'ED BLOCK %lld TO DISK\n", 461 (bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ", 462 (long long)bp->b_bno); 463 bp->b_errs = 0; 464 /* 465 * Write using the appropriate function. 466 */ 467 switch (bp->b_type) { 468 case BT_SUPERBLK: 469 if (bp != &sblk) 470 pfatal("BUFFER %p DOES NOT MATCH SBLK %p\n", 471 bp, &sblk); 472 /* 473 * Superblocks are always pre-copied so we do not need 474 * to check them for copy-on-write. 475 */ 476 if (sbput(fd, bp->b_un.b_fs, 0) == 0) 477 fsmodified = 1; 478 break; 479 case BT_CYLGRP: 480 /* 481 * Cylinder groups are always pre-copied so we do not 482 * need to check them for copy-on-write. 483 */ 484 if (sujrecovery) 485 cg_write(bp); 486 if (cgput(fswritefd, &sblock, bp->b_un.b_cg) == 0) 487 fsmodified = 1; 488 break; 489 case BT_INODES: 490 if (debug && sblock.fs_magic == FS_UFS2_MAGIC) { 491 struct ufs2_dinode *dp = bp->b_un.b_dinode2; 492 int i; 493 494 for (i = 0; i < bp->b_size; dp++, i += sizeof(*dp)) { 495 if (ffs_verify_dinode_ckhash(&sblock, dp) == 0) 496 continue; 497 pwarn("flush: INODE CHECK-HASH FAILED"); 498 ip.i_bp = bp; 499 ip.i_dp = (union dinode *)dp; 500 ip.i_number = bp->b_index + (i / sizeof(*dp)); 501 prtinode(&ip); 502 if (preen || reply("FIX") != 0) { 503 if (preen) 504 printf(" (FIXED)\n"); 505 ffs_update_dinode_ckhash(&sblock, dp); 506 inodirty(&ip); 507 } 508 } 509 } 510 /* FALLTHROUGH */ 511 default: 512 copyonwrite(&sblock, bp, std_checkblkavail); 513 blwrite(fd, bp->b_un.b_buf, bp->b_bno, bp->b_size); 514 break; 515 } 516 } 517 518 /* 519 * If there are any snapshots, ensure that all the blocks that they 520 * care about have been copied, then release the snapshot inodes. 521 * These operations need to be done before we rebuild the cylinder 522 * groups so that any block allocations are properly recorded. 523 * Since all the cylinder group maps have already been copied in 524 * the snapshots, no further snapshot copies will need to be done. 525 */ 526 void 527 snapflush(ufs2_daddr_t (*checkblkavail)(ufs2_daddr_t, long)) 528 { 529 struct bufarea *bp; 530 int cnt; 531 532 if (snapcnt > 0) { 533 if (debug) 534 printf("Check for snapshot copies\n"); 535 TAILQ_FOREACH_REVERSE(bp, &bufqueuehd, bufqueue, b_list) 536 if ((bp->b_flags & B_DIRTY) != 0) 537 copyonwrite(&sblock, bp, checkblkavail); 538 for (cnt = 0; cnt < snapcnt; cnt++) 539 irelse(&snaplist[cnt]); 540 snapcnt = 0; 541 } 542 } 543 544 /* 545 * Journaled soft updates does not maintain cylinder group summary 546 * information during cleanup, so this routine recalculates the summary 547 * information and updates the superblock summary in preparation for 548 * writing out the cylinder group. 549 */ 550 static void 551 cg_write(struct bufarea *bp) 552 { 553 ufs1_daddr_t fragno, cgbno, maxbno; 554 u_int8_t *blksfree; 555 struct csum *csp; 556 struct cg *cgp; 557 int blk; 558 int i; 559 560 /* 561 * Fix the frag and cluster summary. 562 */ 563 cgp = bp->b_un.b_cg; 564 cgp->cg_cs.cs_nbfree = 0; 565 cgp->cg_cs.cs_nffree = 0; 566 bzero(&cgp->cg_frsum, sizeof(cgp->cg_frsum)); 567 maxbno = fragstoblks(&sblock, sblock.fs_fpg); 568 if (sblock.fs_contigsumsize > 0) { 569 for (i = 1; i <= sblock.fs_contigsumsize; i++) 570 cg_clustersum(cgp)[i] = 0; 571 bzero(cg_clustersfree(cgp), howmany(maxbno, CHAR_BIT)); 572 } 573 blksfree = cg_blksfree(cgp); 574 for (cgbno = 0; cgbno < maxbno; cgbno++) { 575 if (ffs_isfreeblock(&sblock, blksfree, cgbno)) 576 continue; 577 if (ffs_isblock(&sblock, blksfree, cgbno)) { 578 ffs_clusteracct(&sblock, cgp, cgbno, 1); 579 cgp->cg_cs.cs_nbfree++; 580 continue; 581 } 582 fragno = blkstofrags(&sblock, cgbno); 583 blk = blkmap(&sblock, blksfree, fragno); 584 ffs_fragacct(&sblock, blk, cgp->cg_frsum, 1); 585 for (i = 0; i < sblock.fs_frag; i++) 586 if (isset(blksfree, fragno + i)) 587 cgp->cg_cs.cs_nffree++; 588 } 589 /* 590 * Update the superblock cg summary from our now correct values 591 * before writing the block. 592 */ 593 csp = &sblock.fs_cs(&sblock, cgp->cg_cgx); 594 sblock.fs_cstotal.cs_ndir += cgp->cg_cs.cs_ndir - csp->cs_ndir; 595 sblock.fs_cstotal.cs_nbfree += cgp->cg_cs.cs_nbfree - csp->cs_nbfree; 596 sblock.fs_cstotal.cs_nifree += cgp->cg_cs.cs_nifree - csp->cs_nifree; 597 sblock.fs_cstotal.cs_nffree += cgp->cg_cs.cs_nffree - csp->cs_nffree; 598 sblock.fs_cs(&sblock, cgp->cg_cgx) = cgp->cg_cs; 599 } 600 601 void 602 rwerror(const char *mesg, ufs2_daddr_t blk) 603 { 604 605 if (bkgrdcheck) 606 exit(EEXIT); 607 if (preen == 0) 608 printf("\n"); 609 pfatal("CANNOT %s: %ld", mesg, (long)blk); 610 if (reply("CONTINUE") == 0) 611 exit(EEXIT); 612 } 613 614 void 615 ckfini(int markclean) 616 { 617 struct bufarea *bp, *nbp; 618 int ofsmodified, cnt, cg; 619 620 if (bkgrdflag) { 621 unlink(snapname); 622 if ((!(sblock.fs_flags & FS_UNCLEAN)) != markclean) { 623 cmd.value = FS_UNCLEAN; 624 cmd.size = markclean ? -1 : 1; 625 if (sysctlbyname("vfs.ffs.setflags", 0, 0, 626 &cmd, sizeof cmd) == -1) 627 pwarn("CANNOT SET FILE SYSTEM DIRTY FLAG\n"); 628 if (!preen) { 629 printf("\n***** FILE SYSTEM MARKED %s *****\n", 630 markclean ? "CLEAN" : "DIRTY"); 631 if (!markclean) 632 rerun = 1; 633 } 634 } else if (!preen && !markclean) { 635 printf("\n***** FILE SYSTEM STILL DIRTY *****\n"); 636 rerun = 1; 637 } 638 bkgrdflag = 0; 639 } 640 if (debug && cachelookups > 0) 641 printf("cache with %d buffers missed %d of %d (%d%%)\n", 642 numbufs, cachereads, cachelookups, 643 (int)(cachereads * 100 / cachelookups)); 644 if (fswritefd < 0) { 645 (void)close(fsreadfd); 646 return; 647 } 648 649 /* 650 * To remain idempotent with partial truncations the buffers 651 * must be flushed in this order: 652 * 1) cylinder groups (bitmaps) 653 * 2) indirect, directory, external attribute, and data blocks 654 * 3) inode blocks 655 * 4) superblock 656 * This ordering preserves access to the modified pointers 657 * until they are freed. 658 */ 659 /* Step 1: cylinder groups */ 660 if (debug) 661 printf("Flush Cylinder groups\n"); 662 if (cgbufs != NULL) { 663 for (cnt = 0; cnt < sblock.fs_ncg; cnt++) { 664 if (cgbufs[cnt].b_un.b_cg == NULL) 665 continue; 666 flush(fswritefd, &cgbufs[cnt]); 667 free(cgbufs[cnt].b_un.b_cg); 668 } 669 free(cgbufs); 670 cgbufs = NULL; 671 } 672 flush(fswritefd, &cgblk); 673 free(cgblk.b_un.b_buf); 674 cgblk.b_un.b_buf = NULL; 675 cnt = 0; 676 /* Step 2: indirect, directory, external attribute, and data blocks */ 677 if (debug) 678 printf("Flush indirect, directory, external attribute, " 679 "and data blocks\n"); 680 if (pdirbp != NULL) { 681 brelse(pdirbp); 682 pdirbp = NULL; 683 } 684 TAILQ_FOREACH_REVERSE_SAFE(bp, &bufqueuehd, bufqueue, b_list, nbp) { 685 switch (bp->b_type) { 686 /* These should not be in the buffer cache list */ 687 case BT_UNKNOWN: 688 case BT_SUPERBLK: 689 case BT_CYLGRP: 690 default: 691 prtbuf(bp,"ckfini: improper buffer type on cache list"); 692 continue; 693 /* These are the ones to flush in this step */ 694 case BT_LEVEL1: 695 case BT_LEVEL2: 696 case BT_LEVEL3: 697 case BT_EXTATTR: 698 case BT_DIRDATA: 699 case BT_DATA: 700 break; 701 /* These are the ones to flush in the next step */ 702 case BT_INODES: 703 continue; 704 } 705 if (debug && bp->b_refcnt != 0) 706 prtbuf(bp, "ckfini: clearing in-use buffer"); 707 TAILQ_REMOVE(&bufqueuehd, bp, b_list); 708 LIST_REMOVE(bp, b_hash); 709 cnt++; 710 flush(fswritefd, bp); 711 free(bp->b_un.b_buf); 712 free((char *)bp); 713 } 714 /* Step 3: inode blocks */ 715 if (debug) 716 printf("Flush inode blocks\n"); 717 if (icachebp != NULL) { 718 brelse(icachebp); 719 icachebp = NULL; 720 } 721 TAILQ_FOREACH_REVERSE_SAFE(bp, &bufqueuehd, bufqueue, b_list, nbp) { 722 if (debug && bp->b_refcnt != 0) 723 prtbuf(bp, "ckfini: clearing in-use buffer"); 724 TAILQ_REMOVE(&bufqueuehd, bp, b_list); 725 LIST_REMOVE(bp, b_hash); 726 cnt++; 727 flush(fswritefd, bp); 728 free(bp->b_un.b_buf); 729 free((char *)bp); 730 } 731 if (numbufs != cnt) 732 errx(EEXIT, "panic: lost %d buffers", numbufs - cnt); 733 /* Step 4: superblock */ 734 if (debug) 735 printf("Flush the superblock\n"); 736 flush(fswritefd, &sblk); 737 if (havesb && cursnapshot == 0 && 738 sblk.b_bno != sblock.fs_sblockloc / dev_bsize) { 739 if (preen || reply("UPDATE STANDARD SUPERBLOCK")) { 740 /* Change write destination to standard superblock */ 741 sblock.fs_sblockactualloc = sblock.fs_sblockloc; 742 sblk.b_bno = sblock.fs_sblockloc / dev_bsize; 743 sbdirty(); 744 flush(fswritefd, &sblk); 745 } else { 746 markclean = 0; 747 } 748 } 749 if (cursnapshot == 0 && sblock.fs_clean != markclean) { 750 if ((sblock.fs_clean = markclean) != 0) { 751 sblock.fs_flags &= ~(FS_UNCLEAN | FS_NEEDSFSCK); 752 sblock.fs_pendingblocks = 0; 753 sblock.fs_pendinginodes = 0; 754 } 755 sbdirty(); 756 ofsmodified = fsmodified; 757 flush(fswritefd, &sblk); 758 fsmodified = ofsmodified; 759 if (!preen) { 760 printf("\n***** FILE SYSTEM MARKED %s *****\n", 761 markclean ? "CLEAN" : "DIRTY"); 762 if (!markclean) 763 rerun = 1; 764 } 765 } else if (!preen) { 766 if (markclean) { 767 printf("\n***** FILE SYSTEM IS CLEAN *****\n"); 768 } else { 769 printf("\n***** FILE SYSTEM STILL DIRTY *****\n"); 770 rerun = 1; 771 } 772 } 773 /* 774 * Free allocated tracking structures. 775 */ 776 if (blockmap != NULL) 777 free(blockmap); 778 blockmap = NULL; 779 if (inostathead != NULL) { 780 for (cg = 0; cg < sblock.fs_ncg; cg++) 781 if (inostathead[cg].il_stat != NULL) 782 free((char *)inostathead[cg].il_stat); 783 free(inostathead); 784 } 785 inostathead = NULL; 786 inocleanup(); 787 finalIOstats(); 788 (void)close(fsreadfd); 789 (void)close(fswritefd); 790 } 791 792 /* 793 * Print out I/O statistics. 794 */ 795 void 796 IOstats(char *what) 797 { 798 int i; 799 800 if (debug == 0) 801 return; 802 if (diskreads == 0) { 803 printf("%s: no I/O\n\n", what); 804 return; 805 } 806 if (startpass.tv_sec == 0) 807 startpass = startprog; 808 printf("%s: I/O statistics\n", what); 809 printIOstats(); 810 totaldiskreads += diskreads; 811 diskreads = 0; 812 for (i = 0; i < BT_NUMBUFTYPES; i++) { 813 timespecadd(&totalreadtime[i], &readtime[i], &totalreadtime[i]); 814 totalreadcnt[i] += readcnt[i]; 815 readtime[i].tv_sec = readtime[i].tv_nsec = 0; 816 readcnt[i] = 0; 817 } 818 clock_gettime(CLOCK_REALTIME_PRECISE, &startpass); 819 } 820 821 void 822 finalIOstats(void) 823 { 824 int i; 825 826 if (debug == 0) 827 return; 828 printf("Final I/O statistics\n"); 829 totaldiskreads += diskreads; 830 diskreads = totaldiskreads; 831 startpass = startprog; 832 for (i = 0; i < BT_NUMBUFTYPES; i++) { 833 timespecadd(&totalreadtime[i], &readtime[i], &totalreadtime[i]); 834 totalreadcnt[i] += readcnt[i]; 835 readtime[i] = totalreadtime[i]; 836 readcnt[i] = totalreadcnt[i]; 837 } 838 printIOstats(); 839 } 840 841 static void printIOstats(void) 842 { 843 long long msec, totalmsec; 844 int i; 845 846 clock_gettime(CLOCK_REALTIME_PRECISE, &finishpass); 847 timespecsub(&finishpass, &startpass, &finishpass); 848 printf("Running time: %jd.%03ld sec\n", 849 (intmax_t)finishpass.tv_sec, finishpass.tv_nsec / 1000000); 850 printf("buffer reads by type:\n"); 851 for (totalmsec = 0, i = 0; i < BT_NUMBUFTYPES; i++) 852 totalmsec += readtime[i].tv_sec * 1000 + 853 readtime[i].tv_nsec / 1000000; 854 if (totalmsec == 0) 855 totalmsec = 1; 856 for (i = 0; i < BT_NUMBUFTYPES; i++) { 857 if (readcnt[i] == 0) 858 continue; 859 msec = 860 readtime[i].tv_sec * 1000 + readtime[i].tv_nsec / 1000000; 861 printf("%21s:%8ld %2ld.%ld%% %4jd.%03ld sec %2lld.%lld%%\n", 862 buftype[i], readcnt[i], readcnt[i] * 100 / diskreads, 863 (readcnt[i] * 1000 / diskreads) % 10, 864 (intmax_t)readtime[i].tv_sec, readtime[i].tv_nsec / 1000000, 865 msec * 100 / totalmsec, (msec * 1000 / totalmsec) % 10); 866 } 867 printf("\n"); 868 } 869 870 int 871 blread(int fd, char *buf, ufs2_daddr_t blk, long size) 872 { 873 char *cp; 874 int i, errs; 875 off_t offset; 876 877 offset = blk; 878 offset *= dev_bsize; 879 if (bkgrdflag) 880 slowio_start(); 881 totalreads++; 882 diskreads++; 883 if (pread(fd, buf, (int)size, offset) == size) { 884 if (bkgrdflag) 885 slowio_end(); 886 return (0); 887 } 888 889 /* 890 * This is handled specially here instead of in rwerror because 891 * rwerror is used for all sorts of errors, not just true read/write 892 * errors. It should be refactored and fixed. 893 */ 894 if (surrender) { 895 pfatal("CANNOT READ_BLK: %ld", (long)blk); 896 errx(EEXIT, "ABORTING DUE TO READ ERRORS"); 897 } else 898 rwerror("READ BLK", blk); 899 900 errs = 0; 901 memset(buf, 0, (size_t)size); 902 printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:"); 903 for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) { 904 if (pread(fd, cp, (int)secsize, offset + i) != secsize) { 905 if (secsize != dev_bsize && dev_bsize != 1) 906 printf(" %jd (%jd),", 907 (intmax_t)(blk * dev_bsize + i) / secsize, 908 (intmax_t)blk + i / dev_bsize); 909 else 910 printf(" %jd,", (intmax_t)blk + i / dev_bsize); 911 errs++; 912 } 913 } 914 printf("\n"); 915 if (errs) 916 resolved = 0; 917 return (errs); 918 } 919 920 void 921 blwrite(int fd, char *buf, ufs2_daddr_t blk, ssize_t size) 922 { 923 int i; 924 char *cp; 925 off_t offset; 926 927 if (fd < 0) 928 return; 929 offset = blk; 930 offset *= dev_bsize; 931 if (pwrite(fd, buf, size, offset) == size) { 932 fsmodified = 1; 933 return; 934 } 935 resolved = 0; 936 rwerror("WRITE BLK", blk); 937 printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:"); 938 for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize) 939 if (pwrite(fd, cp, dev_bsize, offset + i) != dev_bsize) 940 printf(" %jd,", (intmax_t)blk + i / dev_bsize); 941 printf("\n"); 942 return; 943 } 944 945 void 946 blerase(int fd, ufs2_daddr_t blk, long size) 947 { 948 off_t ioarg[2]; 949 950 if (fd < 0) 951 return; 952 ioarg[0] = blk * dev_bsize; 953 ioarg[1] = size; 954 ioctl(fd, DIOCGDELETE, ioarg); 955 /* we don't really care if we succeed or not */ 956 return; 957 } 958 959 /* 960 * Fill a contiguous region with all-zeroes. Note ZEROBUFSIZE is by 961 * definition a multiple of dev_bsize. 962 */ 963 void 964 blzero(int fd, ufs2_daddr_t blk, long size) 965 { 966 static char *zero; 967 off_t offset, len; 968 969 if (fd < 0) 970 return; 971 if (zero == NULL) { 972 zero = calloc(ZEROBUFSIZE, 1); 973 if (zero == NULL) 974 errx(EEXIT, "cannot allocate buffer pool"); 975 } 976 offset = blk * dev_bsize; 977 if (lseek(fd, offset, 0) < 0) 978 rwerror("SEEK BLK", blk); 979 while (size > 0) { 980 len = MIN(ZEROBUFSIZE, size); 981 if (write(fd, zero, len) != len) 982 rwerror("WRITE BLK", blk); 983 blk += len / dev_bsize; 984 size -= len; 985 } 986 } 987 988 /* 989 * Verify cylinder group's magic number and other parameters. If the 990 * test fails, offer an option to rebuild the whole cylinder group. 991 * 992 * Return 1 if the cylinder group is good or return 0 if it is bad. 993 */ 994 #undef CHK 995 #define CHK(lhs, op, rhs, fmt) \ 996 if (lhs op rhs) { \ 997 pwarn("UFS%d cylinder group %d failed: " \ 998 "%s (" #fmt ") %s %s (" #fmt ")\n", \ 999 sblock.fs_magic == FS_UFS1_MAGIC ? 1 : 2, cg, \ 1000 #lhs, (intmax_t)lhs, #op, #rhs, (intmax_t)rhs); \ 1001 error = 1; \ 1002 } 1003 int 1004 check_cgmagic(int cg, struct bufarea *cgbp) 1005 { 1006 struct cg *cgp = cgbp->b_un.b_cg; 1007 uint32_t cghash, calchash; 1008 static int prevfailcg = -1; 1009 long start; 1010 int error; 1011 1012 /* 1013 * Extended cylinder group checks. 1014 */ 1015 calchash = cgp->cg_ckhash; 1016 if ((sblock.fs_metackhash & CK_CYLGRP) != 0 && 1017 (ckhashadd & CK_CYLGRP) == 0) { 1018 cghash = cgp->cg_ckhash; 1019 cgp->cg_ckhash = 0; 1020 calchash = calculate_crc32c(~0L, (void *)cgp, sblock.fs_cgsize); 1021 cgp->cg_ckhash = cghash; 1022 } 1023 error = 0; 1024 CHK(cgp->cg_ckhash, !=, calchash, "%jd"); 1025 CHK(cg_chkmagic(cgp), ==, 0, "%jd"); 1026 CHK(cgp->cg_cgx, !=, cg, "%jd"); 1027 CHK(cgp->cg_ndblk, >, sblock.fs_fpg, "%jd"); 1028 if (sblock.fs_magic == FS_UFS1_MAGIC) { 1029 CHK(cgp->cg_old_niblk, !=, sblock.fs_ipg, "%jd"); 1030 CHK(cgp->cg_old_ncyl, >, sblock.fs_old_cpg, "%jd"); 1031 } else if (sblock.fs_magic == FS_UFS2_MAGIC) { 1032 CHK(cgp->cg_niblk, !=, sblock.fs_ipg, "%jd"); 1033 CHK(cgp->cg_initediblk, >, sblock.fs_ipg, "%jd"); 1034 } 1035 if (cgbase(&sblock, cg) + sblock.fs_fpg < sblock.fs_size) { 1036 CHK(cgp->cg_ndblk, !=, sblock.fs_fpg, "%jd"); 1037 } else { 1038 CHK(cgp->cg_ndblk, !=, sblock.fs_size - cgbase(&sblock, cg), 1039 "%jd"); 1040 } 1041 start = &cgp->cg_space[0] - (u_char *)(&cgp->cg_firstfield); 1042 if (sblock.fs_magic == FS_UFS2_MAGIC) { 1043 CHK(cgp->cg_iusedoff, !=, start, "%jd"); 1044 } else if (sblock.fs_magic == FS_UFS1_MAGIC) { 1045 CHK(cgp->cg_niblk, !=, 0, "%jd"); 1046 CHK(cgp->cg_initediblk, !=, 0, "%jd"); 1047 CHK(cgp->cg_old_ncyl, !=, sblock.fs_old_cpg, "%jd"); 1048 CHK(cgp->cg_old_niblk, !=, sblock.fs_ipg, "%jd"); 1049 CHK(cgp->cg_old_btotoff, !=, start, "%jd"); 1050 CHK(cgp->cg_old_boff, !=, cgp->cg_old_btotoff + 1051 sblock.fs_old_cpg * sizeof(int32_t), "%jd"); 1052 CHK(cgp->cg_iusedoff, !=, cgp->cg_old_boff + 1053 sblock.fs_old_cpg * sizeof(u_int16_t), "%jd"); 1054 } 1055 CHK(cgp->cg_freeoff, !=, 1056 cgp->cg_iusedoff + howmany(sblock.fs_ipg, CHAR_BIT), "%jd"); 1057 if (sblock.fs_contigsumsize == 0) { 1058 CHK(cgp->cg_nextfreeoff, !=, 1059 cgp->cg_freeoff + howmany(sblock.fs_fpg, CHAR_BIT), "%jd"); 1060 } else { 1061 CHK(cgp->cg_nclusterblks, !=, cgp->cg_ndblk / sblock.fs_frag, 1062 "%jd"); 1063 CHK(cgp->cg_clustersumoff, !=, 1064 roundup(cgp->cg_freeoff + howmany(sblock.fs_fpg, CHAR_BIT), 1065 sizeof(u_int32_t)) - sizeof(u_int32_t), "%jd"); 1066 CHK(cgp->cg_clusteroff, !=, cgp->cg_clustersumoff + 1067 (sblock.fs_contigsumsize + 1) * sizeof(u_int32_t), "%jd"); 1068 CHK(cgp->cg_nextfreeoff, !=, cgp->cg_clusteroff + 1069 howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT), 1070 "%jd"); 1071 } 1072 if (error == 0) 1073 return (1); 1074 if (prevfailcg == cg) 1075 return (0); 1076 prevfailcg = cg; 1077 pfatal("CYLINDER GROUP %d: INTEGRITY CHECK FAILED", cg); 1078 printf("\n"); 1079 return (0); 1080 } 1081 1082 void 1083 rebuild_cg(int cg, struct bufarea *cgbp) 1084 { 1085 struct cg *cgp = cgbp->b_un.b_cg; 1086 long start; 1087 1088 /* 1089 * Zero out the cylinder group and then initialize critical fields. 1090 * Bit maps and summaries will be recalculated by later passes. 1091 */ 1092 memset(cgp, 0, (size_t)sblock.fs_cgsize); 1093 cgp->cg_magic = CG_MAGIC; 1094 cgp->cg_cgx = cg; 1095 cgp->cg_niblk = sblock.fs_ipg; 1096 cgp->cg_initediblk = MIN(sblock.fs_ipg, 2 * INOPB(&sblock)); 1097 if (cgbase(&sblock, cg) + sblock.fs_fpg < sblock.fs_size) 1098 cgp->cg_ndblk = sblock.fs_fpg; 1099 else 1100 cgp->cg_ndblk = sblock.fs_size - cgbase(&sblock, cg); 1101 start = &cgp->cg_space[0] - (u_char *)(&cgp->cg_firstfield); 1102 if (sblock.fs_magic == FS_UFS2_MAGIC) { 1103 cgp->cg_iusedoff = start; 1104 } else if (sblock.fs_magic == FS_UFS1_MAGIC) { 1105 cgp->cg_niblk = 0; 1106 cgp->cg_initediblk = 0; 1107 cgp->cg_old_ncyl = sblock.fs_old_cpg; 1108 cgp->cg_old_niblk = sblock.fs_ipg; 1109 cgp->cg_old_btotoff = start; 1110 cgp->cg_old_boff = cgp->cg_old_btotoff + 1111 sblock.fs_old_cpg * sizeof(int32_t); 1112 cgp->cg_iusedoff = cgp->cg_old_boff + 1113 sblock.fs_old_cpg * sizeof(u_int16_t); 1114 } 1115 cgp->cg_freeoff = cgp->cg_iusedoff + howmany(sblock.fs_ipg, CHAR_BIT); 1116 cgp->cg_nextfreeoff = cgp->cg_freeoff + howmany(sblock.fs_fpg,CHAR_BIT); 1117 if (sblock.fs_contigsumsize > 0) { 1118 cgp->cg_nclusterblks = cgp->cg_ndblk / sblock.fs_frag; 1119 cgp->cg_clustersumoff = 1120 roundup(cgp->cg_nextfreeoff, sizeof(u_int32_t)); 1121 cgp->cg_clustersumoff -= sizeof(u_int32_t); 1122 cgp->cg_clusteroff = cgp->cg_clustersumoff + 1123 (sblock.fs_contigsumsize + 1) * sizeof(u_int32_t); 1124 cgp->cg_nextfreeoff = cgp->cg_clusteroff + 1125 howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT); 1126 } 1127 cgp->cg_ckhash = calculate_crc32c(~0L, (void *)cgp, sblock.fs_cgsize); 1128 cgdirty(cgbp); 1129 } 1130 1131 /* 1132 * allocate a data block with the specified number of fragments 1133 */ 1134 ufs2_daddr_t 1135 allocblk(long startcg, long frags, 1136 ufs2_daddr_t (*checkblkavail)(ufs2_daddr_t blkno, long frags)) 1137 { 1138 ufs2_daddr_t blkno, newblk; 1139 1140 if (sujrecovery && checkblkavail == std_checkblkavail) { 1141 pfatal("allocblk: std_checkblkavail used for SUJ recovery\n"); 1142 return (0); 1143 } 1144 if (frags <= 0 || frags > sblock.fs_frag) 1145 return (0); 1146 for (blkno = MAX(cgdata(&sblock, startcg), 0); 1147 blkno < maxfsblock - sblock.fs_frag; 1148 blkno += sblock.fs_frag) { 1149 if ((newblk = (*checkblkavail)(blkno, frags)) == 0) 1150 continue; 1151 if (newblk > 0) 1152 return (newblk); 1153 if (newblk < 0) 1154 blkno = -newblk; 1155 } 1156 for (blkno = MAX(cgdata(&sblock, 0), 0); 1157 blkno < cgbase(&sblock, startcg) - sblock.fs_frag; 1158 blkno += sblock.fs_frag) { 1159 if ((newblk = (*checkblkavail)(blkno, frags)) == 0) 1160 continue; 1161 if (newblk > 0) 1162 return (newblk); 1163 if (newblk < 0) 1164 blkno = -newblk; 1165 } 1166 return (0); 1167 } 1168 1169 ufs2_daddr_t 1170 std_checkblkavail(ufs2_daddr_t blkno, long frags) 1171 { 1172 struct bufarea *cgbp; 1173 struct cg *cgp; 1174 ufs2_daddr_t j, k, baseblk; 1175 long cg; 1176 1177 if ((u_int64_t)blkno > sblock.fs_size) 1178 return (0); 1179 for (j = 0; j <= sblock.fs_frag - frags; j++) { 1180 if (testbmap(blkno + j)) 1181 continue; 1182 for (k = 1; k < frags; k++) 1183 if (testbmap(blkno + j + k)) 1184 break; 1185 if (k < frags) { 1186 j += k; 1187 continue; 1188 } 1189 cg = dtog(&sblock, blkno + j); 1190 cgbp = cglookup(cg); 1191 cgp = cgbp->b_un.b_cg; 1192 if (!check_cgmagic(cg, cgbp)) 1193 return (-((cg + 1) * sblock.fs_fpg - sblock.fs_frag)); 1194 baseblk = dtogd(&sblock, blkno + j); 1195 for (k = 0; k < frags; k++) { 1196 setbmap(blkno + j + k); 1197 clrbit(cg_blksfree(cgp), baseblk + k); 1198 } 1199 n_blks += frags; 1200 if (frags == sblock.fs_frag) 1201 cgp->cg_cs.cs_nbfree--; 1202 else 1203 cgp->cg_cs.cs_nffree -= frags; 1204 cgdirty(cgbp); 1205 return (blkno + j); 1206 } 1207 return (0); 1208 } 1209 1210 /* 1211 * Slow down IO so as to leave some disk bandwidth for other processes 1212 */ 1213 void 1214 slowio_start() 1215 { 1216 1217 /* Delay one in every 8 operations */ 1218 slowio_pollcnt = (slowio_pollcnt + 1) & 7; 1219 if (slowio_pollcnt == 0) { 1220 gettimeofday(&slowio_starttime, NULL); 1221 } 1222 } 1223 1224 void 1225 slowio_end() 1226 { 1227 struct timeval tv; 1228 int delay_usec; 1229 1230 if (slowio_pollcnt != 0) 1231 return; 1232 1233 /* Update the slowdown interval. */ 1234 gettimeofday(&tv, NULL); 1235 delay_usec = (tv.tv_sec - slowio_starttime.tv_sec) * 1000000 + 1236 (tv.tv_usec - slowio_starttime.tv_usec); 1237 if (delay_usec < 64) 1238 delay_usec = 64; 1239 if (delay_usec > 2500000) 1240 delay_usec = 2500000; 1241 slowio_delay_usec = (slowio_delay_usec * 63 + delay_usec) >> 6; 1242 /* delay by 8 times the average IO delay */ 1243 if (slowio_delay_usec > 64) 1244 usleep(slowio_delay_usec * 8); 1245 } 1246 1247 /* 1248 * Find a pathname 1249 */ 1250 void 1251 getpathname(char *namebuf, ino_t curdir, ino_t ino) 1252 { 1253 int len; 1254 char *cp; 1255 struct inode ip; 1256 struct inodesc idesc; 1257 static int busy = 0; 1258 1259 if (curdir == ino && ino == UFS_ROOTINO) { 1260 (void)strcpy(namebuf, "/"); 1261 return; 1262 } 1263 if (busy || !INO_IS_DVALID(curdir)) { 1264 (void)strcpy(namebuf, "?"); 1265 return; 1266 } 1267 busy = 1; 1268 memset(&idesc, 0, sizeof(struct inodesc)); 1269 idesc.id_type = DATA; 1270 idesc.id_fix = IGNORE; 1271 cp = &namebuf[MAXPATHLEN - 1]; 1272 *cp = '\0'; 1273 if (curdir != ino) { 1274 idesc.id_parent = curdir; 1275 goto namelookup; 1276 } 1277 while (ino != UFS_ROOTINO) { 1278 idesc.id_number = ino; 1279 idesc.id_func = findino; 1280 idesc.id_name = strdup(".."); 1281 ginode(ino, &ip); 1282 if ((ckinode(ip.i_dp, &idesc) & FOUND) == 0) { 1283 irelse(&ip); 1284 free(idesc.id_name); 1285 break; 1286 } 1287 irelse(&ip); 1288 free(idesc.id_name); 1289 namelookup: 1290 idesc.id_number = idesc.id_parent; 1291 idesc.id_parent = ino; 1292 idesc.id_func = findname; 1293 idesc.id_name = namebuf; 1294 ginode(idesc.id_number, &ip); 1295 if ((ckinode(ip.i_dp, &idesc) & FOUND) == 0) { 1296 irelse(&ip); 1297 break; 1298 } 1299 irelse(&ip); 1300 len = strlen(namebuf); 1301 cp -= len; 1302 memmove(cp, namebuf, (size_t)len); 1303 *--cp = '/'; 1304 if (cp < &namebuf[UFS_MAXNAMLEN]) 1305 break; 1306 ino = idesc.id_number; 1307 } 1308 busy = 0; 1309 if (ino != UFS_ROOTINO) 1310 *--cp = '?'; 1311 memmove(namebuf, cp, (size_t)(&namebuf[MAXPATHLEN] - cp)); 1312 } 1313 1314 void 1315 catch(int sig __unused) 1316 { 1317 1318 ckfini(0); 1319 exit(12); 1320 } 1321 1322 /* 1323 * When preening, allow a single quit to signal 1324 * a special exit after file system checks complete 1325 * so that reboot sequence may be interrupted. 1326 */ 1327 void 1328 catchquit(int sig __unused) 1329 { 1330 printf("returning to single-user after file system check\n"); 1331 returntosingle = 1; 1332 (void)signal(SIGQUIT, SIG_DFL); 1333 } 1334 1335 /* 1336 * determine whether an inode should be fixed. 1337 */ 1338 int 1339 dofix(struct inodesc *idesc, const char *msg) 1340 { 1341 1342 switch (idesc->id_fix) { 1343 1344 case DONTKNOW: 1345 if (idesc->id_type == DATA) 1346 direrror(idesc->id_number, msg); 1347 else 1348 pwarn("%s", msg); 1349 if (preen) { 1350 printf(" (SALVAGED)\n"); 1351 idesc->id_fix = FIX; 1352 return (ALTERED); 1353 } 1354 if (reply("SALVAGE") == 0) { 1355 idesc->id_fix = NOFIX; 1356 return (0); 1357 } 1358 idesc->id_fix = FIX; 1359 return (ALTERED); 1360 1361 case FIX: 1362 return (ALTERED); 1363 1364 case NOFIX: 1365 case IGNORE: 1366 return (0); 1367 1368 default: 1369 errx(EEXIT, "UNKNOWN INODESC FIX MODE %d", idesc->id_fix); 1370 } 1371 /* NOTREACHED */ 1372 return (0); 1373 } 1374 1375 #include <stdarg.h> 1376 1377 /* 1378 * Print details about a buffer. 1379 */ 1380 void 1381 prtbuf(struct bufarea *bp, const char *fmt, ...) 1382 { 1383 va_list ap; 1384 va_start(ap, fmt); 1385 if (preen) 1386 (void)fprintf(stdout, "%s: ", cdevname); 1387 (void)vfprintf(stdout, fmt, ap); 1388 va_end(ap); 1389 printf(": bp %p, type %s, bno %jd, size %d, refcnt %d, flags %s, " 1390 "index %jd\n", bp, BT_BUFTYPE(bp->b_type), (intmax_t) bp->b_bno, 1391 bp->b_size, bp->b_refcnt, bp->b_flags & B_DIRTY ? "dirty" : "clean", 1392 (intmax_t) bp->b_index); 1393 } 1394 1395 /* 1396 * An unexpected inconsistency occurred. 1397 * Die if preening or file system is running with soft dependency protocol, 1398 * otherwise just print message and continue. 1399 */ 1400 void 1401 pfatal(const char *fmt, ...) 1402 { 1403 va_list ap; 1404 va_start(ap, fmt); 1405 if (!preen) { 1406 (void)vfprintf(stdout, fmt, ap); 1407 va_end(ap); 1408 if (usedsoftdep) 1409 (void)fprintf(stdout, 1410 "\nUNEXPECTED SOFT UPDATE INCONSISTENCY\n"); 1411 /* 1412 * Force foreground fsck to clean up inconsistency. 1413 */ 1414 if (bkgrdflag) { 1415 cmd.value = FS_NEEDSFSCK; 1416 cmd.size = 1; 1417 if (sysctlbyname("vfs.ffs.setflags", 0, 0, 1418 &cmd, sizeof cmd) == -1) 1419 pwarn("CANNOT SET FS_NEEDSFSCK FLAG\n"); 1420 fprintf(stdout, "CANNOT RUN IN BACKGROUND\n"); 1421 ckfini(0); 1422 exit(EEXIT); 1423 } 1424 return; 1425 } 1426 if (cdevname == NULL) 1427 cdevname = strdup("fsck"); 1428 (void)fprintf(stdout, "%s: ", cdevname); 1429 (void)vfprintf(stdout, fmt, ap); 1430 (void)fprintf(stdout, 1431 "\n%s: UNEXPECTED%sINCONSISTENCY; RUN fsck MANUALLY.\n", 1432 cdevname, usedsoftdep ? " SOFT UPDATE " : " "); 1433 /* 1434 * Force foreground fsck to clean up inconsistency. 1435 */ 1436 if (bkgrdflag) { 1437 cmd.value = FS_NEEDSFSCK; 1438 cmd.size = 1; 1439 if (sysctlbyname("vfs.ffs.setflags", 0, 0, 1440 &cmd, sizeof cmd) == -1) 1441 pwarn("CANNOT SET FS_NEEDSFSCK FLAG\n"); 1442 } 1443 ckfini(0); 1444 exit(EEXIT); 1445 } 1446 1447 /* 1448 * Pwarn just prints a message when not preening or running soft dependency 1449 * protocol, or a warning (preceded by filename) when preening. 1450 */ 1451 void 1452 pwarn(const char *fmt, ...) 1453 { 1454 va_list ap; 1455 va_start(ap, fmt); 1456 if (preen) 1457 (void)fprintf(stdout, "%s: ", cdevname); 1458 (void)vfprintf(stdout, fmt, ap); 1459 va_end(ap); 1460 } 1461 1462 /* 1463 * Stub for routines from kernel. 1464 */ 1465 void 1466 panic(const char *fmt, ...) 1467 { 1468 va_list ap; 1469 va_start(ap, fmt); 1470 pfatal("INTERNAL INCONSISTENCY:"); 1471 (void)vfprintf(stdout, fmt, ap); 1472 va_end(ap); 1473 exit(EEXIT); 1474 } 1475