lint
[unix-history] / usr / src / sys / kern / vfs_cluster.c
index 67bc608..52033ba 100644 (file)
@@ -1,4 +1,4 @@
-/*     vfs_cluster.c   4.31    82/05/31        */
+/*     vfs_cluster.c   4.38    82/10/17        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -12,6 +12,8 @@
 #include "../h/vm.h"
 #include "../h/trace.h"
 
 #include "../h/vm.h"
 #include "../h/trace.h"
 
+int bioprintfs = 0;
+
 /*
  * Read in (if necessary) the block and return a buffer pointer.
  */
 /*
  * Read in (if necessary) the block and return a buffer pointer.
  */
@@ -31,7 +33,7 @@ bread(dev, blkno, size)
        bp->b_flags |= B_READ;
        (*bdevsw[major(dev)].d_strategy)(bp);
        trace(TR_BREADMISS, dev, blkno);
        bp->b_flags |= B_READ;
        (*bdevsw[major(dev)].d_strategy)(bp);
        trace(TR_BREADMISS, dev, blkno);
-       u.u_vm.vm_inblk++;              /* pay for read */
+       u.u_ru.ru_inblock++;            /* pay for read */
        biowait(bp);
        return(bp);
 }
        biowait(bp);
        return(bp);
 }
@@ -41,10 +43,10 @@ bread(dev, blkno, size)
  * read-ahead block (which is not allocated to the caller)
  */
 struct buf *
  * read-ahead block (which is not allocated to the caller)
  */
 struct buf *
-breada(dev, blkno, rablkno, size)
+breada(dev, blkno, size, rablkno, rabsize)
        dev_t dev;
        dev_t dev;
-       daddr_t blkno, rablkno;
-       int size;
+       daddr_t blkno; int size;
+       daddr_t rablkno; int rabsize;
 {
        register struct buf *bp, *rabp;
 
 {
        register struct buf *bp, *rabp;
 
@@ -60,7 +62,7 @@ breada(dev, blkno, rablkno, size)
                        bp->b_flags |= B_READ;
                        (*bdevsw[major(dev)].d_strategy)(bp);
                        trace(TR_BREADMISS, dev, blkno);
                        bp->b_flags |= B_READ;
                        (*bdevsw[major(dev)].d_strategy)(bp);
                        trace(TR_BREADMISS, dev, blkno);
-                       u.u_vm.vm_inblk++;              /* pay for read */
+                       u.u_ru.ru_inblock++;            /* pay for read */
                } else
                        trace(TR_BREADHIT, dev, blkno);
        }
                } else
                        trace(TR_BREADHIT, dev, blkno);
        }
@@ -70,7 +72,7 @@ breada(dev, blkno, rablkno, size)
         * on it also (as above).
         */
        if (rablkno && !incore(dev, rablkno)) {
         * on it also (as above).
         */
        if (rablkno && !incore(dev, rablkno)) {
-               rabp = getblk(dev, rablkno, size);
+               rabp = getblk(dev, rablkno, rabsize);
                if (rabp->b_flags & B_DONE) {
                        brelse(rabp);
                        trace(TR_BREADHITRA, dev, blkno);
                if (rabp->b_flags & B_DONE) {
                        brelse(rabp);
                        trace(TR_BREADHITRA, dev, blkno);
@@ -78,18 +80,19 @@ breada(dev, blkno, rablkno, size)
                        rabp->b_flags |= B_READ|B_ASYNC;
                        (*bdevsw[major(dev)].d_strategy)(rabp);
                        trace(TR_BREADMISSRA, dev, rablock);
                        rabp->b_flags |= B_READ|B_ASYNC;
                        (*bdevsw[major(dev)].d_strategy)(rabp);
                        trace(TR_BREADMISSRA, dev, rablock);
-                       u.u_vm.vm_inblk++;              /* pay in advance */
+                       u.u_ru.ru_inblock++;            /* pay in advance */
                }
        }
 
        /*
                }
        }
 
        /*
-        * If we get here with bp NULL, then the block
-        * must've been in core and bread will find it for us.
+        * If block was in core, let bread get it.
+        * If block wasn't in core, then the read was started
+        * above, and just wait for it.
         */
         */
-       if(bp == NULL)
-               return(bread(dev, blkno, size));
+       if (bp == NULL)
+               return (bread(dev, blkno, size));
        biowait(bp);
        biowait(bp);
-       return(bp);
+       return (bp);
 }
 
 /*
 }
 
 /*
@@ -104,8 +107,10 @@ bwrite(bp)
        flag = bp->b_flags;
        bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI | B_AGE);
        if ((flag&B_DELWRI) == 0)
        flag = bp->b_flags;
        bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI | B_AGE);
        if ((flag&B_DELWRI) == 0)
-               u.u_vm.vm_oublk++;              /* noone paid yet */
+               u.u_ru.ru_oublock++;            /* noone paid yet */
        trace(TR_BWRITE, bp->b_dev, bp->b_blkno);
        trace(TR_BWRITE, bp->b_dev, bp->b_blkno);
+if (bioprintfs)
+printf("write %x blk %d count %d\n", bp->b_dev, bp->b_blkno, bp->b_bcount);
        (*bdevsw[major(bp->b_dev)].d_strategy)(bp);
 
        /*
        (*bdevsw[major(bp->b_dev)].d_strategy)(bp);
 
        /*
@@ -121,7 +126,7 @@ bwrite(bp)
        } else if (flag & B_DELWRI)
                bp->b_flags |= B_AGE;
        else
        } else if (flag & B_DELWRI)
                bp->b_flags |= B_AGE;
        else
-               geterror(bp);
+               u.u_error = geterror(bp);
 }
 
 /*
 }
 
 /*
@@ -138,7 +143,7 @@ bdwrite(bp)
        register int flags;
 
        if ((bp->b_flags&B_DELWRI) == 0)
        register int flags;
 
        if ((bp->b_flags&B_DELWRI) == 0)
-               u.u_vm.vm_oublk++;              /* noone paid yet */
+               u.u_ru.ru_oublock++;            /* noone paid yet */
        flags = bdevsw[major(bp->b_dev)].d_flags;
        if(flags & B_TAPE)
                bawrite(bp);
        flags = bdevsw[major(bp->b_dev)].d_flags;
        if(flags & B_TAPE)
                bawrite(bp);
@@ -276,7 +281,8 @@ loop:
                }
                splx(s);
                notavail(bp);
                }
                splx(s);
                notavail(bp);
-               brealloc(bp, size);
+               if (brealloc(bp, size) == 0)
+                       goto loop;
                bp->b_flags |= B_CACHE;
                return(bp);
        }
                bp->b_flags |= B_CACHE;
                return(bp);
        }
@@ -311,7 +317,8 @@ loop:
        binshash(bp, dp);
        bp->b_dev = dev;
        bp->b_blkno = blkno;
        binshash(bp, dp);
        bp->b_dev = dev;
        bp->b_blkno = blkno;
-       brealloc(bp, size);
+       if (brealloc(bp, size) == 0)
+               goto loop;
        return(bp);
 }
 
        return(bp);
 }
 
@@ -350,7 +357,8 @@ loop:
        bremhash(bp);
        binshash(bp, dp);
        bp->b_dev = (dev_t)NODEV;
        bremhash(bp);
        binshash(bp, dp);
        bp->b_dev = (dev_t)NODEV;
-       bp->b_bcount = size;
+       if (brealloc(bp, size) == 0)
+               goto loop;
        return(bp);
 }
 
        return(bp);
 }
 
@@ -371,24 +379,44 @@ brealloc(bp, size)
         * is dispatched with.
         */
        if (size == bp->b_bcount)
         * is dispatched with.
         */
        if (size == bp->b_bcount)
-               return;
-       if (size < bp->b_bcount) {
-               bp->b_bcount = size;
-               return;
-       }
-       start = bp->b_blkno + (bp->b_bcount / DEV_BSIZE);
-       last = bp->b_blkno + (size / DEV_BSIZE) - 1;
-       if (bp->b_bcount == 0) {
-               start++;
-               if (start == last)
-                       goto allocit;
+               return (1);
+       if (size < bp->b_bcount) { 
+               if (bp->b_flags & B_DELWRI) {
+                       bwrite(bp);
+                       return (0);
+               }
+               if (bp->b_flags & B_LOCKED)
+                       panic("brealloc");
+               goto allocit;
        }
        }
+       bp->b_flags &= ~B_DONE;
+       if (bp->b_dev == NODEV)
+               goto allocit;
+
+       /*
+        * Search cache for any buffers that overlap the one that we
+        * are trying to allocate. Overlapping buffers must be marked
+        * invalid, after being written out if they are dirty. (indicated
+        * by B_DELWRI) A disk block must be mapped by at most one buffer
+        * at any point in time. Care must be taken to avoid deadlocking
+        * when two buffer are trying to get the same set of disk blocks.
+        */
+       start = bp->b_blkno;
+       last = start + (size / DEV_BSIZE) - 1;
        dp = BUFHASH(bp->b_dev, bp->b_blkno);
 loop:
        for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) {
        dp = BUFHASH(bp->b_dev, bp->b_blkno);
 loop:
        for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) {
-               if (ep->b_blkno < start || ep->b_blkno > last ||
-                   ep->b_dev != bp->b_dev || ep->b_flags&B_INVAL)
+               if (ep == bp || ep->b_dev != bp->b_dev || (ep->b_flags&B_INVAL))
+                       continue;
+               /* look for overlap */
+               if (ep->b_bcount == 0 || ep->b_blkno > last ||
+                   ep->b_blkno + (ep->b_bcount / DEV_BSIZE) <= start)
                        continue;
                        continue;
+if (bioprintfs)
+if (ep->b_flags&B_BUSY)
+printf("sleeping on:dev 0x%x, blks %d-%d, flg 0%o allocing dev 0x%x, blks %d-%d, flg 0%o\n",
+ep->b_dev, ep->b_blkno, ep->b_blkno + (ep->b_bcount / DEV_BSIZE) - 1,
+ep->b_flags, bp->b_dev, start, last, bp->b_flags);
                s = spl6();
                if (ep->b_flags&B_BUSY) {
                        ep->b_flags |= B_WANTED;
                s = spl6();
                if (ep->b_flags&B_BUSY) {
                        ep->b_flags |= B_WANTED;
@@ -397,18 +425,17 @@ loop:
                        goto loop;
                }
                (void) splx(s);
                        goto loop;
                }
                (void) splx(s);
-               /*
-                * What we would really like to do is kill this
-                * I/O since it is now useless. We cannot do that
-                * so we force it to complete, so that it cannot
-                * over-write our useful data later.
-                */
+               notavail(ep);
                if (ep->b_flags & B_DELWRI) {
                if (ep->b_flags & B_DELWRI) {
-                       notavail(ep);
-                       ep->b_flags |= B_ASYNC;
+if (bioprintfs)
+printf("DELWRI:dev 0x%x, blks %d-%d, flg 0%o allocing dev 0x%x, blks %d-%d, flg 0%o\n",
+ep->b_dev, ep->b_blkno, ep->b_blkno + (ep->b_bcount / DEV_BSIZE) - 1,
+ep->b_flags, bp->b_dev, start, last, bp->b_flags);
                        bwrite(ep);
                        goto loop;
                }
                        bwrite(ep);
                        goto loop;
                }
+               ep->b_flags |= B_INVAL;
+               brelse(ep);
        }
 allocit:
        /*
        }
 allocit:
        /*
@@ -417,6 +444,7 @@ allocit:
         * management scheme will be implemented.
         */
        bp->b_bcount = size;
         * management scheme will be implemented.
         */
        bp->b_bcount = size;
+       return (1);
 }
 
 /*
 }
 
 /*
@@ -446,7 +474,7 @@ biowait(bp)
        while ((bp->b_flags&B_DONE)==0)
                sleep((caddr_t)bp, PRIBIO);
        splx(s);
        while ((bp->b_flags&B_DONE)==0)
                sleep((caddr_t)bp, PRIBIO);
        splx(s);
-       geterror(bp);
+       u.u_error = geterror(bp);
 }
 
 /*
 }
 
 /*
@@ -527,10 +555,12 @@ loop:
 geterror(bp)
        register struct buf *bp;
 {
 geterror(bp)
        register struct buf *bp;
 {
+       int error = 0;
 
        if (bp->b_flags&B_ERROR)
 
        if (bp->b_flags&B_ERROR)
-               if ((u.u_error = bp->b_error)==0)
-                       u.u_error = EIO;
+               if ((error = bp->b_error)==0)
+                       return (EIO);
+       return (error);
 }
 
 /*
 }
 
 /*