missing fsbtodb!
[unix-history] / usr / src / sbin / fsck / utilities.c
index 3f6d9b0..3052033 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)utilities.c        5.7 (Berkeley) %G%";
+static char sccsid[] = "@(#)utilities.c        5.13 (Berkeley) %G%";
 #endif not lint
 
 #include <stdio.h>
 #endif not lint
 
 #include <stdio.h>
@@ -16,6 +16,7 @@ static char sccsid[] = "@(#)utilities.c       5.7 (Berkeley) %G%";
 #include <sys/dir.h>
 #include "fsck.h"
 
 #include <sys/dir.h>
 #include "fsck.h"
 
+long   diskreads, totalreads;  /* Disk cache statistics */
 long   lseek();
 
 ftypeok(dp)
 long   lseek();
 
 ftypeok(dp)
@@ -42,15 +43,16 @@ reply(s)
        char *s;
 {
        char line[80];
        char *s;
 {
        char line[80];
+       int cont = (strcmp(s, "CONTINUE") == 0);
 
        if (preen)
                pfatal("INTERNAL ERROR: GOT TO reply()");
        printf("\n%s? ", s);
 
        if (preen)
                pfatal("INTERNAL ERROR: GOT TO reply()");
        printf("\n%s? ", s);
-       if (nflag || dfile.wfdes < 0) {
+       if (!cont && (nflag || dfile.wfdes < 0)) {
                printf(" no\n\n");
                return (0);
        }
                printf(" no\n\n");
                return (0);
        }
-       if (yflag) {
+       if (yflag || (cont && nflag)) {
                printf(" yes\n\n");
                return (1);
        }
                printf(" yes\n\n");
                return (1);
        }
@@ -82,6 +84,74 @@ getline(fp, loc, maxlen)
        return (p - loc);
 }
 
        return (p - loc);
 }
 
+/*
+ * Malloc buffers and set up cache.
+ */
+bufinit()
+{
+       register BUFAREA *bp;
+       long bufcnt, i;
+       char *bufp;
+
+       bufp = (char *)malloc(sblock.fs_bsize);
+       if (bufp == 0)
+               errexit("cannot allocate buffer pool\n");
+       cgblk.b_un.b_buf = bufp;
+       initbarea(&cgblk);
+       bufhead.b_next = bufhead.b_prev = &bufhead;
+       bufcnt = MAXBUFSPACE / sblock.fs_bsize;
+       if (bufcnt < MINBUFS)
+               bufcnt = MINBUFS;
+       for (i = 0; i < bufcnt; i++) {
+               bp = (BUFAREA *)malloc(sizeof(BUFAREA));
+               bufp = (char *)malloc(sblock.fs_bsize);
+               if (bp == 0 || bufp == 0) {
+                       if (i >= MINBUFS)
+                               break;
+                       errexit("cannot allocate buffer pool\n");
+               }
+               bp->b_un.b_buf = bufp;
+               bp->b_prev = &bufhead;
+               bp->b_next = bufhead.b_next;
+               bufhead.b_next->b_prev = bp;
+               bufhead.b_next = bp;
+               initbarea(bp);
+       }
+       bufhead.b_size = i;     /* save number of buffers */
+}
+
+/*
+ * Manage a cache of directory blocks.
+ */
+BUFAREA *
+getdatablk(blkno, size)
+       daddr_t blkno;
+       long size;
+{
+       register BUFAREA *bp;
+
+       for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next)
+               if (bp->b_bno == blkno)
+                       goto foundit;
+       for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev)
+               if ((bp->b_flags & B_INUSE) == 0)
+                       break;
+       if (bp == &bufhead)
+               errexit("deadlocked buffer pool\n");
+       getblk(bp, blkno, size);
+       /* fall through */
+foundit:
+       totalreads++;
+       bp->b_prev->b_next = bp->b_next;
+       bp->b_next->b_prev = bp->b_prev;
+       bp->b_prev = &bufhead;
+       bp->b_next = bufhead.b_next;
+       bufhead.b_next->b_prev = bp;
+       bufhead.b_next = bp;
+       bp->b_flags |= B_INUSE;
+       return (bp);
+}
+
 BUFAREA *
 getblk(bp, blk, size)
        register BUFAREA *bp;
 BUFAREA *
 getblk(bp, blk, size)
        register BUFAREA *bp;
@@ -92,12 +162,12 @@ getblk(bp, blk, size)
        daddr_t dblk;
 
        fcp = &dfile;
        daddr_t dblk;
 
        fcp = &dfile;
-       dblk = fsbtodb(&sblock, blk);
-       if (bp->b_bno == dblk)
+       if (bp->b_bno == blk)
                return (bp);
        flush(fcp, bp);
                return (bp);
        flush(fcp, bp);
-       bp->b_errs = bread(fcp, bp->b_un.b_buf, dblk, size);
-       bp->b_bno = dblk;
+       diskreads++;
+       bp->b_errs = bread(fcp, bp->b_un.b_buf, fsbtodb(&sblock, blk), size);
+       bp->b_bno = blk;
        bp->b_size = size;
        return (bp);
 }
        bp->b_size = size;
        return (bp);
 }
@@ -111,7 +181,9 @@ flush(fcp, bp)
        if (!bp->b_dirty)
                return;
        if (bp->b_errs != 0)
        if (!bp->b_dirty)
                return;
        if (bp->b_errs != 0)
-               pfatal("WRITING ZERO'ED BLOCK %d TO DISK\n", bp->b_bno);
+               pfatal("WRITING %sZERO'ED BLOCK %d TO DISK\n",
+                   (bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ",
+                   bp->b_bno);
        bp->b_dirty = 0;
        bp->b_errs = 0;
        bwrite(fcp, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size);
        bp->b_dirty = 0;
        bp->b_errs = 0;
        bwrite(fcp, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size);
@@ -139,17 +211,26 @@ rwerr(s, blk)
 
 ckfini()
 {
 
 ckfini()
 {
+       register BUFAREA *bp;
+       int cnt = 0;
 
 
-       flush(&dfile, &fileblk);
        flush(&dfile, &sblk);
        flush(&dfile, &sblk);
-       if (sblk.b_bno != SBOFF / dev_bsize &&
+       if (havesb && sblk.b_bno != SBOFF / dev_bsize &&
            !preen && reply("UPDATE STANDARD SUPERBLOCK")) {
                sblk.b_bno = SBOFF / dev_bsize;
                sbdirty();
                flush(&dfile, &sblk);
        }
            !preen && reply("UPDATE STANDARD SUPERBLOCK")) {
                sblk.b_bno = SBOFF / dev_bsize;
                sbdirty();
                flush(&dfile, &sblk);
        }
-       flush(&dfile, &inoblk);
        flush(&dfile, &cgblk);
        flush(&dfile, &cgblk);
+       for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev) {
+               cnt++;
+               flush(&dfile, bp);
+       }
+       if (bufhead.b_size != cnt)
+               errexit("Panic: lost %d buffers\n", bufhead.b_size - cnt);
+       if (debug)
+               printf("cache missed %d of %d (%d%%)\n", diskreads,
+                   totalreads, diskreads * 100 / totalreads);
        (void)close(dfile.rfdes);
        (void)close(dfile.wfdes);
 }
        (void)close(dfile.rfdes);
        (void)close(dfile.wfdes);
 }
@@ -163,20 +244,25 @@ bread(fcp, buf, blk, size)
        char *cp;
        int i, errs;
 
        char *cp;
        int i, errs;
 
-       if (lseek(fcp->rfdes, (long)dbtob(blk), 0) < 0)
+       if (lseek(fcp->rfdes, blk * dev_bsize, 0) < 0)
                rwerr("SEEK", blk);
        else if (read(fcp->rfdes, buf, (int)size) == size)
                return (0);
        rwerr("READ", blk);
                rwerr("SEEK", blk);
        else if (read(fcp->rfdes, buf, (int)size) == size)
                return (0);
        rwerr("READ", blk);
-       if (lseek(fcp->rfdes, (long)dbtob(blk), 0) < 0)
+       if (lseek(fcp->rfdes, blk * dev_bsize, 0) < 0)
                rwerr("SEEK", blk);
        errs = 0;
        bzero(buf, size);
                rwerr("SEEK", blk);
        errs = 0;
        bzero(buf, size);
-       pfatal("THE FOLLOWING SECTORS COULD NOT BE READ:");
-       for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize) {
-               if (read(fcp->rfdes, cp, dev_bsize) < 0) {
-                       lseek(fcp->rfdes, (long)dbtob(blk) + i + dev_bsize, 0);
-                       printf(" %d,", blk + i / dev_bsize);
+       printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:");
+       for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) {
+               if (read(fcp->rfdes, cp, secsize) < 0) {
+                       lseek(fcp->rfdes, blk * dev_bsize + i + secsize, 0);
+                       if (secsize != dev_bsize && dev_bsize != 1)
+                               printf(" %d (%d),",
+                                   (blk * dev_bsize + i) / secsize,
+                                   blk + i / dev_bsize);
+                       else
+                               printf(" %d,", blk + i / dev_bsize);
                        errs++;
                }
        }
                        errs++;
                }
        }
@@ -195,19 +281,19 @@ bwrite(fcp, buf, blk, size)
 
        if (fcp->wfdes < 0)
                return;
 
        if (fcp->wfdes < 0)
                return;
-       if (lseek(fcp->wfdes, (long)dbtob(blk), 0) < 0)
+       if (lseek(fcp->wfdes, blk * dev_bsize, 0) < 0)
                rwerr("SEEK", blk);
        else if (write(fcp->wfdes, buf, (int)size) == size) {
                fcp->mod = 1;
                return;
        }
        rwerr("WRITE", blk);
                rwerr("SEEK", blk);
        else if (write(fcp->wfdes, buf, (int)size) == size) {
                fcp->mod = 1;
                return;
        }
        rwerr("WRITE", blk);
-       if (lseek(fcp->wfdes, (long)dbtob(blk), 0) < 0)
+       if (lseek(fcp->wfdes, blk * dev_bsize, 0) < 0)
                rwerr("SEEK", blk);
                rwerr("SEEK", blk);
-       pfatal("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:");
+       printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:");
        for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize)
                if (write(fcp->wfdes, cp, dev_bsize) < 0) {
        for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize)
                if (write(fcp->wfdes, cp, dev_bsize) < 0) {
-                       lseek(fcp->rfdes, (long)dbtob(blk) + i + dev_bsize, 0);
+                       lseek(fcp->rfdes, blk * dev_bsize + i + dev_bsize, 0);
                        printf(" %d,", blk + i / dev_bsize);
                }
        printf("\n");
                        printf(" %d,", blk + i / dev_bsize);
                }
        printf("\n");