expand from three static buffer to a dynamic buffer pool;
authorKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Sat, 7 May 1988 16:04:19 +0000 (08:04 -0800)
committerKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Sat, 7 May 1988 16:04:19 +0000 (08:04 -0800)
initial sizing of the buffer pool is 128K (For 8K fs == 16 buffers)

SCCS-vsn: sbin/fsck/fsck.h 5.7
SCCS-vsn: sbin/fsck/dir.c 5.4
SCCS-vsn: sbin/fsck/inode.c 5.6
SCCS-vsn: sbin/fsck/setup.c 5.19
SCCS-vsn: sbin/fsck/utilities.c 5.11

usr/src/sbin/fsck/dir.c
usr/src/sbin/fsck/fsck.h
usr/src/sbin/fsck/inode.c
usr/src/sbin/fsck/setup.c
usr/src/sbin/fsck/utilities.c

index 396a190..56dc498 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)dir.c      5.3 (Berkeley) %G%";
+static char sccsid[] = "@(#)dir.c      5.4 (Berkeley) %G%";
 #endif not lint
 
 #include <sys/param.h>
 #endif not lint
 
 #include <sys/param.h>
@@ -24,6 +24,7 @@ struct        dirtemplate emptydir = { 0, DIRBLKSIZ };
 struct dirtemplate dirhead = { 0, 12, 1, ".", 0, DIRBLKSIZ - 12, 2, ".." };
 
 DIRECT *fsck_readdir();
 struct dirtemplate dirhead = { 0, 12, 1, ".", 0, DIRBLKSIZ - 12, 2, ".." };
 
 DIRECT *fsck_readdir();
+BUFAREA        *getdirblk();
 
 descend(parentino, inumber)
        struct inodesc *parentino;
 
 descend(parentino, inumber)
        struct inodesc *parentino;
@@ -74,6 +75,7 @@ dirscan(idesc)
        register struct inodesc *idesc;
 {
        register DIRECT *dp;
        register struct inodesc *idesc;
 {
        register DIRECT *dp;
+       register BUFAREA *bp;
        int dsize, n;
        long blksiz;
        char dbuf[DIRBLKSIZ];
        int dsize, n;
        long blksiz;
        char dbuf[DIRBLKSIZ];
@@ -94,9 +96,9 @@ dirscan(idesc)
                bcopy((char *)dp, dbuf, dsize);
                idesc->id_dirp = (DIRECT *)dbuf;
                if ((n = (*idesc->id_func)(idesc)) & ALTERED) {
                bcopy((char *)dp, dbuf, dsize);
                idesc->id_dirp = (DIRECT *)dbuf;
                if ((n = (*idesc->id_func)(idesc)) & ALTERED) {
-                       getblk(&fileblk, idesc->id_blkno, blksiz);
+                       bp = getdirblk(idesc->id_blkno, blksiz);
                        bcopy(dbuf, (char *)dp, dsize);
                        bcopy(dbuf, (char *)dp, dsize);
-                       dirty(&fileblk);
+                       dirty(bp);
                        sbdirty();
                }
                if (n & STOP) 
                        sbdirty();
                }
                if (n & STOP) 
@@ -113,13 +115,14 @@ fsck_readdir(idesc)
        register struct inodesc *idesc;
 {
        register DIRECT *dp, *ndp;
        register struct inodesc *idesc;
 {
        register DIRECT *dp, *ndp;
+       register BUFAREA *bp;
        long size, blksiz;
 
        blksiz = idesc->id_numfrags * sblock.fs_fsize;
        long size, blksiz;
 
        blksiz = idesc->id_numfrags * sblock.fs_fsize;
-       getblk(&fileblk, idesc->id_blkno, blksiz);
+       bp = getdirblk(idesc->id_blkno, blksiz);
        if (idesc->id_loc % DIRBLKSIZ == 0 && idesc->id_filesize > 0 &&
            idesc->id_loc < blksiz) {
        if (idesc->id_loc % DIRBLKSIZ == 0 && idesc->id_filesize > 0 &&
            idesc->id_loc < blksiz) {
-               dp = (DIRECT *)(dirblk.b_buf + idesc->id_loc);
+               dp = (DIRECT *)(bp->b_un.b_buf + idesc->id_loc);
                if (dircheck(idesc, dp))
                        goto dpok;
                idesc->id_loc += DIRBLKSIZ;
                if (dircheck(idesc, dp))
                        goto dpok;
                idesc->id_loc += DIRBLKSIZ;
@@ -129,18 +132,18 @@ fsck_readdir(idesc)
                dp->d_namlen = 0;
                dp->d_name[0] = '\0';
                if (dofix(idesc, "DIRECTORY CORRUPTED"))
                dp->d_namlen = 0;
                dp->d_name[0] = '\0';
                if (dofix(idesc, "DIRECTORY CORRUPTED"))
-                       dirty(&fileblk);
+                       dirty(bp);
                return (dp);
        }
 dpok:
        if (idesc->id_filesize <= 0 || idesc->id_loc >= blksiz)
                return NULL;
                return (dp);
        }
 dpok:
        if (idesc->id_filesize <= 0 || idesc->id_loc >= blksiz)
                return NULL;
-       dp = (DIRECT *)(dirblk.b_buf + idesc->id_loc);
+       dp = (DIRECT *)(bp->b_un.b_buf + idesc->id_loc);
        idesc->id_loc += dp->d_reclen;
        idesc->id_filesize -= dp->d_reclen;
        if ((idesc->id_loc % DIRBLKSIZ) == 0)
                return (dp);
        idesc->id_loc += dp->d_reclen;
        idesc->id_filesize -= dp->d_reclen;
        if ((idesc->id_loc % DIRBLKSIZ) == 0)
                return (dp);
-       ndp = (DIRECT *)(dirblk.b_buf + idesc->id_loc);
+       ndp = (DIRECT *)(bp->b_un.b_buf + idesc->id_loc);
        if (idesc->id_loc < blksiz && idesc->id_filesize > 0 &&
            dircheck(idesc, ndp) == 0) {
                size = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
        if (idesc->id_loc < blksiz && idesc->id_filesize > 0 &&
            dircheck(idesc, ndp) == 0) {
                size = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
@@ -148,7 +151,7 @@ dpok:
                idesc->id_loc += size;
                idesc->id_filesize -= size;
                if (dofix(idesc, "DIRECTORY CORRUPTED"))
                idesc->id_loc += size;
                idesc->id_filesize -= size;
                if (dofix(idesc, "DIRECTORY CORRUPTED"))
-                       dirty(&fileblk);
+                       dirty(bp);
        }
        return (dp);
 }
        }
        return (dp);
 }
@@ -431,6 +434,7 @@ expanddir(dp)
        register DINODE *dp;
 {
        daddr_t lastbn, newblk;
        register DINODE *dp;
 {
        daddr_t lastbn, newblk;
+       register BUFAREA *bp;
        char *cp, firstblk[DIRBLKSIZ];
 
        lastbn = lblkno(&sblock, dp->di_size);
        char *cp, firstblk[DIRBLKSIZ];
 
        lastbn = lblkno(&sblock, dp->di_size);
@@ -442,31 +446,31 @@ expanddir(dp)
        dp->di_db[lastbn] = newblk;
        dp->di_size += sblock.fs_bsize;
        dp->di_blocks += btodb(sblock.fs_bsize);
        dp->di_db[lastbn] = newblk;
        dp->di_size += sblock.fs_bsize;
        dp->di_blocks += btodb(sblock.fs_bsize);
-       getblk(&fileblk, dp->di_db[lastbn + 1],
-           dblksize(&sblock, dp, lastbn + 1));
-       if (fileblk.b_errs != NULL)
+       bp = getdirblk(dp->di_db[lastbn + 1],
+               dblksize(&sblock, dp, lastbn + 1));
+       if (bp->b_errs != NULL)
                goto bad;
                goto bad;
-       bcopy(dirblk.b_buf, firstblk, DIRBLKSIZ);
-       getblk(&fileblk, newblk, sblock.fs_bsize);
-       if (fileblk.b_errs != NULL)
+       bcopy(bp->b_un.b_buf, firstblk, DIRBLKSIZ);
+       bp = getdirblk(newblk, sblock.fs_bsize);
+       if (bp->b_errs != NULL)
                goto bad;
                goto bad;
-       bcopy(firstblk, dirblk.b_buf, DIRBLKSIZ);
-       for (cp = &dirblk.b_buf[DIRBLKSIZ];
-            cp < &dirblk.b_buf[sblock.fs_bsize];
+       bcopy(firstblk, bp->b_un.b_buf, DIRBLKSIZ);
+       for (cp = &bp->b_un.b_buf[DIRBLKSIZ];
+            cp < &bp->b_un.b_buf[sblock.fs_bsize];
             cp += DIRBLKSIZ)
                bcopy((char *)&emptydir, cp, sizeof emptydir);
             cp += DIRBLKSIZ)
                bcopy((char *)&emptydir, cp, sizeof emptydir);
-       dirty(&fileblk);
-       getblk(&fileblk, dp->di_db[lastbn + 1],
-           dblksize(&sblock, dp, lastbn + 1));
-       if (fileblk.b_errs != NULL)
+       dirty(bp);
+       bp = getdirblk(dp->di_db[lastbn + 1],
+               dblksize(&sblock, dp, lastbn + 1));
+       if (bp->b_errs != NULL)
                goto bad;
                goto bad;
-       bcopy((char *)&emptydir, dirblk.b_buf, sizeof emptydir);
+       bcopy((char *)&emptydir, bp->b_un.b_buf, sizeof emptydir);
        pwarn("NO SPACE LEFT IN %s", pathname);
        if (preen)
                printf(" (EXPANDED)\n");
        else if (reply("EXPAND") == 0)
                goto bad;
        pwarn("NO SPACE LEFT IN %s", pathname);
        if (preen)
                printf(" (EXPANDED)\n");
        else if (reply("EXPAND") == 0)
                goto bad;
-       dirty(&fileblk);
+       dirty(bp);
        inodirty();
        return (1);
 bad:
        inodirty();
        return (1);
 bad:
@@ -487,22 +491,23 @@ allocdir(parent, request)
        ino_t ino;
        char *cp;
        DINODE *dp;
        ino_t ino;
        char *cp;
        DINODE *dp;
+       register BUFAREA *bp;
 
        ino = allocino(request, IFDIR|0755);
        dirhead.dot_ino = ino;
        dirhead.dotdot_ino = parent;
        dp = ginode(ino);
 
        ino = allocino(request, IFDIR|0755);
        dirhead.dot_ino = ino;
        dirhead.dotdot_ino = parent;
        dp = ginode(ino);
-       getblk(&fileblk, dp->di_db[0], sblock.fs_fsize);
-       if (fileblk.b_errs != NULL) {
+       bp = getdirblk(dp->di_db[0], sblock.fs_fsize);
+       if (bp->b_errs != NULL) {
                freeino(ino);
                return (0);
        }
                freeino(ino);
                return (0);
        }
-       bcopy((char *)&dirhead, dirblk.b_buf, sizeof dirhead);
-       for (cp = &dirblk.b_buf[DIRBLKSIZ];
-            cp < &dirblk.b_buf[sblock.fs_fsize];
+       bcopy((char *)&dirhead, bp->b_un.b_buf, sizeof dirhead);
+       for (cp = &bp->b_un.b_buf[DIRBLKSIZ];
+            cp < &bp->b_un.b_buf[sblock.fs_fsize];
             cp += DIRBLKSIZ)
                bcopy((char *)&emptydir, cp, sizeof emptydir);
             cp += DIRBLKSIZ)
                bcopy((char *)&emptydir, cp, sizeof emptydir);
-       dirty(&fileblk);
+       dirty(bp);
        dp->di_nlink = 2;
        inodirty();
        if (ino == ROOTINO) {
        dp->di_nlink = 2;
        inodirty();
        if (ino == ROOTINO) {
@@ -564,3 +569,20 @@ lftempname(bufp, ino)
        *cp = '#';
        return (namlen);
 }
        *cp = '#';
        return (namlen);
 }
+
+/*
+ * Get a directory block.
+ * Insure that it is held until another is requested.
+ */
+BUFAREA *
+getdirblk(blkno, size)
+       daddr_t blkno;
+       long size;
+{
+       static BUFAREA *pbp = 0;
+
+       if (pbp != 0)
+               pbp->b_flags &= ~B_INUSE;
+       pbp = getdatablk(blkno, size);
+       return (pbp);
+}
index 4cc8c19..14a6499 100644 (file)
@@ -3,11 +3,12 @@
  * All rights reserved.  The Berkeley software License Agreement
  * specifies the terms and conditions for redistribution.
  *
  * All rights reserved.  The Berkeley software License Agreement
  * specifies the terms and conditions for redistribution.
  *
- *     @(#)fsck.h      5.6 (Berkeley) %G%
+ *     @(#)fsck.h      5.7 (Berkeley) %G%
  */
 
  */
 
-#define        MAXDUP          10      /* limit on dup blks (per inode) */
-#define        MAXBAD          10      /* limit on bad blks (per inode) */
+#define        MAXDUP          10       /* limit on dup blks (per inode) */
+#define        MAXBAD          10       /* limit on bad blks (per inode) */
+#define MAXBUFSPACE    128*1024 /* maximum space to allocate to buffers */
 
 typedef        int     (*SIG_TYP)();
 
 
 typedef        int     (*SIG_TYP)();
 
@@ -30,42 +31,45 @@ typedef struct direct       DIRECT;
 #define        SPECIAL(dip) \
        (((dip)->di_mode & IFMT) == IFBLK || ((dip)->di_mode & IFMT) == IFCHR)
 
 #define        SPECIAL(dip) \
        (((dip)->di_mode & IFMT) == IFBLK || ((dip)->di_mode & IFMT) == IFCHR)
 
-#define        MAXNINDIR       (MAXBSIZE / sizeof (daddr_t))
-#define        MAXINOPB        (MAXBSIZE / sizeof (struct dinode))
-#define        SPERB           (MAXBSIZE / sizeof(short))
-
+/*
+ * buffer cache structure.
+ */
 struct bufarea {
 struct bufarea {
-       struct bufarea  *b_next;                /* must be first */
+       struct bufarea  *b_next;                /* free list queue */
+       struct bufarea  *b_prev;                /* free list queue */
        daddr_t b_bno;
        int     b_size;
        int     b_errs;
        daddr_t b_bno;
        int     b_size;
        int     b_errs;
+       int     b_flags;
        union {
        union {
-               char    b_buf[MAXBSIZE];        /* buffer space */
-               short   b_lnks[SPERB];          /* link counts */
-               daddr_t b_indir[MAXNINDIR];     /* indirect block */
-               struct  fs b_fs;                /* super block */
-               struct  cg b_cg;                /* cylinder group */
-               struct dinode b_dinode[MAXINOPB]; /* inode block */
+               char    *b_buf;                 /* buffer space */
+               daddr_t *b_indir;               /* indirect block */
+               struct  fs *b_fs;               /* super block */
+               struct  cg *b_cg;               /* cylinder group */
+               struct dinode *b_dinode;        /* inode block */
        } b_un;
        char    b_dirty;
 };
 
        } b_un;
        char    b_dirty;
 };
 
+#define        B_INUSE 1
 typedef struct bufarea BUFAREA;
 
 typedef struct bufarea BUFAREA;
 
-BUFAREA        inoblk;                 /* inode blocks */
-BUFAREA        fileblk;                /* other blks in filesys */
+#define        MINBUFS         5       /* minimum number of buffers required */
+BUFAREA        bufhead;                /* head of list of other blks in filesys */
 BUFAREA        sblk;                   /* file system superblock */
 BUFAREA        cgblk;                  /* cylinder group blocks */
 BUFAREA        sblk;                   /* file system superblock */
 BUFAREA        cgblk;                  /* cylinder group blocks */
+BUFAREA        *getdatablk();
 
 
-#define        initbarea(x)    (x)->b_dirty = 0;(x)->b_bno = (daddr_t)-1
 #define        dirty(x)        (x)->b_dirty = 1
 #define        dirty(x)        (x)->b_dirty = 1
-#define        inodirty()      inoblk.b_dirty = 1
+#define        initbarea(x) \
+       (x)->b_dirty = 0; \
+       (x)->b_bno = (daddr_t)-1; \
+       (x)->b_flags = 0;
+
 #define        sbdirty()       sblk.b_dirty = 1
 #define        cgdirty()       cgblk.b_dirty = 1
 #define        sbdirty()       sblk.b_dirty = 1
 #define        cgdirty()       cgblk.b_dirty = 1
-
-#define        dirblk          fileblk.b_un
-#define        sblock          sblk.b_un.b_fs
-#define        cgrp            cgblk.b_un.b_cg
+#define        sblock          (*sblk.b_un.b_fs)
+#define        cgrp            (*cgblk.b_un.b_cg)
 
 struct filecntl {
        int     rfdes;
 
 struct filecntl {
        int     rfdes;
index e09195e..b8df7cd 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)inode.c    5.5 (Berkeley) %G%";
+static char sccsid[] = "@(#)inode.c    5.6 (Berkeley) %G%";
 #endif not lint
 
 #include <pwd.h>
 #endif not lint
 
 #include <pwd.h>
@@ -15,6 +15,8 @@ static char sccsid[] = "@(#)inode.c   5.5 (Berkeley) %G%";
 #include <sys/dir.h>
 #include "fsck.h"
 
 #include <sys/dir.h>
 #include "fsck.h"
 
+BUFAREA *pbp = 0;
+
 ckinode(dp, idesc)
        DINODE *dp;
        register struct inodesc *idesc;
 ckinode(dp, idesc)
        DINODE *dp;
        register struct inodesc *idesc;
@@ -67,7 +69,7 @@ iblock(idesc, ilevel, isize)
        register daddr_t *ap;
        register daddr_t *aplim;
        int i, n, (*func)(), nif, sizepb;
        register daddr_t *ap;
        register daddr_t *aplim;
        int i, n, (*func)(), nif, sizepb;
-       BUFAREA ib;
+       register BUFAREA *bp;
        char buf[BUFSIZ];
        extern int dirscan(), pass1check();
 
        char buf[BUFSIZ];
        extern int dirscan(), pass1check();
 
@@ -79,8 +81,7 @@ iblock(idesc, ilevel, isize)
                func = dirscan;
        if (outrange(idesc->id_blkno, idesc->id_numfrags)) /* protect thyself */
                return (SKIP);
                func = dirscan;
        if (outrange(idesc->id_blkno, idesc->id_numfrags)) /* protect thyself */
                return (SKIP);
-       initbarea(&ib);
-       getblk(&ib, idesc->id_blkno, sblock.fs_bsize);
+       bp = getdatablk(idesc->id_blkno, sblock.fs_bsize);
        ilevel--;
        for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++)
                sizepb *= NINDIR(&sblock);
        ilevel--;
        for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++)
                sizepb *= NINDIR(&sblock);
@@ -88,30 +89,34 @@ iblock(idesc, ilevel, isize)
        if (nif > NINDIR(&sblock))
                nif = NINDIR(&sblock);
        if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) {
        if (nif > NINDIR(&sblock))
                nif = NINDIR(&sblock);
        if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) {
-               aplim = &ib.b_un.b_indir[NINDIR(&sblock)];
-               for (ap = &ib.b_un.b_indir[nif]; ap < aplim; ap++) {
+               aplim = &bp->b_un.b_indir[NINDIR(&sblock)];
+               for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) {
                        if (*ap == 0)
                                continue;
                        (void)sprintf(buf, "PARTIALLY TRUNCATED INODE I=%d",
                                idesc->id_number);
                        if (dofix(idesc, buf)) {
                                *ap = 0;
                        if (*ap == 0)
                                continue;
                        (void)sprintf(buf, "PARTIALLY TRUNCATED INODE I=%d",
                                idesc->id_number);
                        if (dofix(idesc, buf)) {
                                *ap = 0;
-                               dirty(&ib);
+                               dirty(bp);
                        }
                }
                        }
                }
-               flush(&dfile, &ib);
+               flush(&dfile, bp);
        }
        }
-       aplim = &ib.b_un.b_indir[nif];
-       for (ap = ib.b_un.b_indir, i = 1; ap < aplim; ap++, i++)
+       aplim = &bp->b_un.b_indir[nif];
+       for (ap = bp->b_un.b_indir, i = 1; ap < aplim; ap++, i++) {
                if (*ap) {
                        idesc->id_blkno = *ap;
                        if (ilevel > 0)
                                n = iblock(idesc, ilevel, isize - i * sizepb);
                        else
                                n = (*func)(idesc);
                if (*ap) {
                        idesc->id_blkno = *ap;
                        if (ilevel > 0)
                                n = iblock(idesc, ilevel, isize - i * sizepb);
                        else
                                n = (*func)(idesc);
-                       if (n & STOP)
+                       if (n & STOP) {
+                               bp->b_flags &= ~B_INUSE;
                                return (n);
                                return (n);
+                       }
                }
                }
+       }
+       bp->b_flags &= ~B_INUSE;
        return (KEEPON);
 }
 
        return (KEEPON);
 }
 
@@ -160,10 +165,18 @@ ginode(inumber)
        if (startinum == 0 ||
            inumber < startinum || inumber >= startinum + INOPB(&sblock)) {
                iblk = itod(&sblock, inumber);
        if (startinum == 0 ||
            inumber < startinum || inumber >= startinum + INOPB(&sblock)) {
                iblk = itod(&sblock, inumber);
-               getblk(&inoblk, iblk, sblock.fs_bsize);
+               if (pbp != 0)
+                       pbp->b_flags &= ~B_INUSE;
+               pbp = getdatablk(iblk, sblock.fs_bsize);
                startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock);
        }
                startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock);
        }
-       return (&inoblk.b_un.b_dinode[inumber % INOPB(&sblock)]);
+       return (&pbp->b_un.b_dinode[inumber % INOPB(&sblock)]);
+}
+
+inodirty()
+{
+       
+       dirty(pbp);
 }
 
 clri(idesc, s, flg)
 }
 
 clri(idesc, s, flg)
index f385f65..df94dfb 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)setup.c    5.18 (Berkeley) %G%";
+static char sccsid[] = "@(#)setup.c    5.19 (Berkeley) %G%";
 #endif not lint
 
 #define DKTYPENAMES
 #endif not lint
 
 #define DKTYPENAMES
@@ -21,7 +21,7 @@ static char sccsid[] = "@(#)setup.c   5.18 (Berkeley) %G%";
 #include "fsck.h"
 
 BUFAREA asblk;
 #include "fsck.h"
 
 BUFAREA asblk;
-#define altsblock asblk.b_un.b_fs
+#define altsblock (*asblk.b_un.b_fs)
 #define POWEROF2(num)  (((num) & ((num) - 1)) == 0)
 
 char   *calloc();
 #define POWEROF2(num)  (((num) & ((num) - 1)) == 0)
 
 char   *calloc();
@@ -74,10 +74,11 @@ setup(dev)
        dfile.mod = 0;
        lfdir = 0;
        initbarea(&sblk);
        dfile.mod = 0;
        lfdir = 0;
        initbarea(&sblk);
-       initbarea(&fileblk);
-       initbarea(&inoblk);
-       initbarea(&cgblk);
        initbarea(&asblk);
        initbarea(&asblk);
+       sblk.b_un.b_buf = (char *)malloc(SBSIZE);
+       asblk.b_un.b_buf = (char *)malloc(SBSIZE);
+       if (sblk.b_un.b_buf == 0 || asblk.b_un.b_buf == 0)
+               errexit("cannot allocate space for superblock\n");
        if (lp = getdisklabel((char *)NULL, dfile.rfdes))
                dev_bsize = secsize = lp->d_secsize;
        else
        if (lp = getdisklabel((char *)NULL, dfile.rfdes))
                dev_bsize = secsize = lp->d_secsize;
        else
@@ -238,6 +239,7 @@ setup(dev)
                goto badsb;
        }
 
                goto badsb;
        }
 
+       bufinit();
        return (1);
 
 badsb:
        return (1);
 
 badsb:
index a2140c3..b888a54 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)utilities.c        5.10 (Berkeley) %G%";
+static char sccsid[] = "@(#)utilities.c        5.11 (Berkeley) %G%";
 #endif not lint
 
 #include <stdio.h>
 #endif not lint
 
 #include <stdio.h>
@@ -16,6 +16,7 @@ static char sccsid[] = "@(#)utilities.c       5.10 (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)
@@ -83,6 +84,73 @@ 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);
+       }
+}
+
+/*
+ * 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;
@@ -93,12 +161,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);
 }
@@ -142,8 +210,8 @@ rwerr(s, blk)
 
 ckfini()
 {
 
 ckfini()
 {
+       register BUFAREA *bp;
 
 
-       flush(&dfile, &fileblk);
        flush(&dfile, &sblk);
        if (havesb && sblk.b_bno != SBOFF / dev_bsize &&
            !preen && reply("UPDATE STANDARD SUPERBLOCK")) {
        flush(&dfile, &sblk);
        if (havesb && sblk.b_bno != SBOFF / dev_bsize &&
            !preen && reply("UPDATE STANDARD SUPERBLOCK")) {
@@ -151,8 +219,12 @@ ckfini()
                sbdirty();
                flush(&dfile, &sblk);
        }
                sbdirty();
                flush(&dfile, &sblk);
        }
-       flush(&dfile, &inoblk);
        flush(&dfile, &cgblk);
        flush(&dfile, &cgblk);
+       for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev)
+               flush(&dfile, bp);
+       if (debug)
+               printf("cache hit %d of %d (%d%%)\n", totalreads - diskreads,
+                   totalreads, (totalreads - diskreads) * 100 / totalreads);
        (void)close(dfile.rfdes);
        (void)close(dfile.wfdes);
 }
        (void)close(dfile.rfdes);
        (void)close(dfile.wfdes);
 }