buffer invalidate routine and checks for B_INVAL flag
[unix-history] / usr / src / sys / kern / kern_physio.c
index 6b98ded..ef91a45 100644 (file)
@@ -1,4 +1,4 @@
-/*     kern_physio.c   3.3     %H%     */
+/*     kern_physio.c   4.5     %G%     */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -10,6 +10,7 @@
 #include "../h/seg.h"
 #include "../h/pte.h"
 #include "../h/vm.h"
 #include "../h/seg.h"
 #include "../h/pte.h"
 #include "../h/vm.h"
+#include "../h/trace.h"
 
 /*
  * The following several routines allocate and free
 
 /*
  * The following several routines allocate and free
@@ -99,6 +100,9 @@ daddr_t blkno;
 
        bp = getblk(dev, blkno);
        if (bp->b_flags&B_DONE) {
 
        bp = getblk(dev, blkno);
        if (bp->b_flags&B_DONE) {
+#ifdef EPAWNJ
+               trace(TR_BREAD|TR_HIT, dev, blkno);
+#endif
 #ifdef DISKMON
                io_info.ncache++;
 #endif
 #ifdef DISKMON
                io_info.ncache++;
 #endif
@@ -107,6 +111,9 @@ daddr_t blkno;
        bp->b_flags |= B_READ;
        bp->b_bcount = BSIZE;
        (*bdevsw[major(dev)].d_strategy)(bp);
        bp->b_flags |= B_READ;
        bp->b_bcount = BSIZE;
        (*bdevsw[major(dev)].d_strategy)(bp);
+#ifdef EPAWNJ
+       trace(TR_BREAD|TR_MISS, dev, blkno);
+#endif
 #ifdef DISKMON
        io_info.nread++;
 #endif
 #ifdef DISKMON
        io_info.nread++;
 #endif
@@ -133,20 +140,33 @@ daddr_t blkno, rablkno;
                        bp->b_flags |= B_READ;
                        bp->b_bcount = BSIZE;
                        (*bdevsw[major(dev)].d_strategy)(bp);
                        bp->b_flags |= B_READ;
                        bp->b_bcount = BSIZE;
                        (*bdevsw[major(dev)].d_strategy)(bp);
+#ifdef EPAWNJ
+                       trace(TR_BREAD|TR_MISS, dev, blkno);
+#endif
 #ifdef DISKMON
                        io_info.nread++;
 #endif
                        u.u_vm.vm_inblk++;              /* pay for read */
                }
 #ifdef DISKMON
                        io_info.nread++;
 #endif
                        u.u_vm.vm_inblk++;              /* pay for read */
                }
+#ifdef EPAWNJ
+               else
+                       trace(TR_BREAD|TR_HIT, dev, blkno);
+#endif
        }
        if (rablkno && !incore(dev, rablkno)) {
                rabp = getblk(dev, rablkno);
        }
        if (rablkno && !incore(dev, rablkno)) {
                rabp = getblk(dev, rablkno);
-               if (rabp->b_flags & B_DONE)
+               if (rabp->b_flags & B_DONE) {
                        brelse(rabp);
                        brelse(rabp);
-               else {
+#ifdef EPAWNJ
+                       trace(TR_BREAD|TR_HIT|TR_RA, dev, blkno);
+#endif
+               } else {
                        rabp->b_flags |= B_READ|B_ASYNC;
                        rabp->b_bcount = BSIZE;
                        (*bdevsw[major(dev)].d_strategy)(rabp);
                        rabp->b_flags |= B_READ|B_ASYNC;
                        rabp->b_bcount = BSIZE;
                        (*bdevsw[major(dev)].d_strategy)(rabp);
+#ifdef EPAWNJ
+                       trace(TR_BREAD|TR_MISS|TR_RA, dev, rablock);
+#endif
 #ifdef DISKMON
                        io_info.nreada++;
 #endif
 #ifdef DISKMON
                        io_info.nreada++;
 #endif
@@ -176,6 +196,9 @@ register struct buf *bp;
 #endif
        if ((flag&B_DELWRI) == 0)
                u.u_vm.vm_oublk++;              /* noone paid yet */
 #endif
        if ((flag&B_DELWRI) == 0)
                u.u_vm.vm_oublk++;              /* noone paid yet */
+#ifdef EPAWNJ
+       trace(TR_BWRITE, bp->b_dev, dbtofsb(bp->b_blkno));
+#endif
        (*bdevsw[major(bp->b_dev)].d_strategy)(bp);
        if ((flag&B_ASYNC) == 0) {
                iowait(bp);
        (*bdevsw[major(bp->b_dev)].d_strategy)(bp);
        if ((flag&B_ASYNC) == 0) {
                iowait(bp);
@@ -271,7 +294,8 @@ daddr_t blkno;
 
        for (bp = &buf[bufhash[BUFHASH(blkno)]]; bp != &buf[-1];
            bp = &buf[bp->b_hlink])
 
        for (bp = &buf[bufhash[BUFHASH(blkno)]]; bp != &buf[-1];
            bp = &buf[bp->b_hlink])
-               if (bp->b_blkno == dblkno && bp->b_dev == dev)
+               if (bp->b_blkno == dblkno && bp->b_dev == dev
+                                       && !(bp->b_flags & B_INVAL))
                        return (1);
        return (0);
 }
                        return (1);
        return (0);
 }
@@ -298,22 +322,25 @@ dev_t dev;
 daddr_t blkno;
 {
        register struct buf *bp, *dp, *ep;
 daddr_t blkno;
 {
        register struct buf *bp, *dp, *ep;
-       register int i, x;
-       register int dblkno = fsbtodb(blkno);
+       register int i, x, dblkno;
 
 
+       if ((unsigned)blkno >= 1 << (sizeof(int)*NBBY-PGSHIFT))
+               blkno = 1 << ((sizeof(int)*NBBY-PGSHIFT) + 1);
+       dblkno = fsbtodb(blkno);
     loop:
     loop:
-       VOID spl0();
+       (void) spl0();
        for (bp = &buf[bufhash[BUFHASH(blkno)]]; bp != &buf[-1];
            bp = &buf[bp->b_hlink]) {
        for (bp = &buf[bufhash[BUFHASH(blkno)]]; bp != &buf[-1];
            bp = &buf[bp->b_hlink]) {
-               if (bp->b_blkno != dblkno || bp->b_dev != dev)
+               if (bp->b_blkno != dblkno || bp->b_dev != dev
+                                       || bp->b_flags & B_INVAL)
                        continue;
                        continue;
-               VOID spl6();
+               (void) spl6();
                if (bp->b_flags&B_BUSY) {
                        bp->b_flags |= B_WANTED;
                        sleep((caddr_t)bp, PRIBIO+1);
                        goto loop;
                }
                if (bp->b_flags&B_BUSY) {
                        bp->b_flags |= B_WANTED;
                        sleep((caddr_t)bp, PRIBIO+1);
                        goto loop;
                }
-               VOID spl0();
+               (void) spl0();
 #ifdef DISKMON
                i = 0;
                dp = bp->av_forw;
 #ifdef DISKMON
                i = 0;
                dp = bp->av_forw;
@@ -333,13 +360,13 @@ daddr_t blkno;
        dp = bdevsw[major(dev)].d_tab;
        if (dp == NULL)
                panic("devtab");
        dp = bdevsw[major(dev)].d_tab;
        if (dp == NULL)
                panic("devtab");
-       VOID spl6();
+       (void) spl6();
        if (bfreelist.av_forw == &bfreelist) {
                bfreelist.b_flags |= B_WANTED;
                sleep((caddr_t)&bfreelist, PRIBIO+1);
                goto loop;
        }
        if (bfreelist.av_forw == &bfreelist) {
                bfreelist.b_flags |= B_WANTED;
                sleep((caddr_t)&bfreelist, PRIBIO+1);
                goto loop;
        }
-       spl0();
+       (void) spl0();
        bp = bfreelist.av_forw;
        notavail(bp);
        if (bp->b_flags & B_DELWRI) {
        bp = bfreelist.av_forw;
        notavail(bp);
        if (bp->b_flags & B_DELWRI) {
@@ -350,6 +377,10 @@ daddr_t blkno;
        if (bp->b_dev == NODEV)
                goto done;
        /* INLINE EXPANSION OF bunhash(bp) */
        if (bp->b_dev == NODEV)
                goto done;
        /* INLINE EXPANSION OF bunhash(bp) */
+#ifdef EPAWNJ
+       trace(TR_BRELSE, bp->b_dev, dbtofsb(bp->b_blkno));
+#endif
+       (void) spl6();
        i = BUFHASH(dbtofsb(bp->b_blkno));
        x = bp - buf;
        if (bufhash[i] == x) {
        i = BUFHASH(dbtofsb(bp->b_blkno));
        x = bp - buf;
        if (bufhash[i] == x) {
@@ -364,6 +395,7 @@ daddr_t blkno;
                panic("getblk");
        }
 done:
                panic("getblk");
        }
 done:
+       (void) spl0();
        /* END INLINE EXPANSION */
        bp->b_flags = B_BUSY;
        bp->b_back->b_forw = bp->b_forw;
        /* END INLINE EXPANSION */
        bp->b_flags = B_BUSY;
        bp->b_back->b_forw = bp->b_forw;
@@ -387,16 +419,15 @@ done:
 struct buf *
 geteblk()
 {
 struct buf *
 geteblk()
 {
-       register struct buf *bp, *dp, *ep;
-       register int i, x;
+       register struct buf *bp, *dp;
 
 loop:
 
 loop:
-       VOID spl6();
+       (void) spl6();
        while (bfreelist.av_forw == &bfreelist) {
                bfreelist.b_flags |= B_WANTED;
                sleep((caddr_t)&bfreelist, PRIBIO+1);
        }
        while (bfreelist.av_forw == &bfreelist) {
                bfreelist.b_flags |= B_WANTED;
                sleep((caddr_t)&bfreelist, PRIBIO+1);
        }
-       VOID spl0();
+       (void) spl0();
        dp = &bfreelist;
        bp = bfreelist.av_forw;
        notavail(bp);
        dp = &bfreelist;
        bp = bfreelist.av_forw;
        notavail(bp);
@@ -405,8 +436,12 @@ loop:
                bwrite(bp);
                goto loop;
        }
                bwrite(bp);
                goto loop;
        }
-       if (bp->b_dev != NODEV)
+       if (bp->b_dev != NODEV) {
+#ifdef EPAWNJ
+               trace(TR_BRELSE, bp->b_dev, dbtofsb(bp->b_blkno));
+#endif
                bunhash(bp);
                bunhash(bp);
+       }
        bp->b_flags = B_BUSY;
        bp->b_back->b_forw = bp->b_forw;
        bp->b_forw->b_back = bp->b_back;
        bp->b_flags = B_BUSY;
        bp->b_back->b_forw = bp->b_forw;
        bp->b_forw->b_back = bp->b_back;
@@ -423,23 +458,26 @@ bunhash(bp)
        register struct buf *bp;
 {
        register struct buf *ep;
        register struct buf *bp;
 {
        register struct buf *ep;
-       register int i, x;
+       register int i, x, s;
 
        if (bp->b_dev == NODEV)
                return;
 
        if (bp->b_dev == NODEV)
                return;
+       s = spl6();
        i = BUFHASH(dbtofsb(bp->b_blkno));
        x = bp - buf;
        if (bufhash[i] == x) {
                bufhash[i] = bp->b_hlink;
        i = BUFHASH(dbtofsb(bp->b_blkno));
        x = bp - buf;
        if (bufhash[i] == x) {
                bufhash[i] = bp->b_hlink;
-               return;
+               goto ret;
        }
        for (ep = &buf[bufhash[i]]; ep != &buf[-1];
            ep = &buf[ep->b_hlink])
                if (ep->b_hlink == x) {
                        ep->b_hlink = bp->b_hlink;
        }
        for (ep = &buf[bufhash[i]]; ep != &buf[-1];
            ep = &buf[ep->b_hlink])
                if (ep->b_hlink == x) {
                        ep->b_hlink = bp->b_hlink;
-                       return;
+                       goto ret;
                }
        panic("bunhash");
                }
        panic("bunhash");
+ret:
+       splx(s);
 }
 
 /*
 }
 
 /*
@@ -450,10 +488,10 @@ iowait(bp)
 register struct buf *bp;
 {
 
 register struct buf *bp;
 {
 
-       VOID spl6();
+       (void) spl6();
        while ((bp->b_flags&B_DONE)==0)
                sleep((caddr_t)bp, PRIBIO);
        while ((bp->b_flags&B_DONE)==0)
                sleep((caddr_t)bp, PRIBIO);
-       VOID spl0();
+       (void) spl0();
        geterror(bp);
 }
 
        geterror(bp);
 }
 
@@ -488,6 +526,8 @@ register struct buf *bp;
 {
        register int s;
 
 {
        register int s;
 
+       if (bp->b_flags & B_DONE)
+               panic("dup iodone");
        bp->b_flags |= B_DONE;
        if (bp->b_flags & B_DIRTY) {
                if (bp->b_flags & B_ERROR)
        bp->b_flags |= B_DONE;
        if (bp->b_flags & B_DIRTY) {
                if (bp->b_flags & B_ERROR)
@@ -501,6 +541,7 @@ register struct buf *bp;
                if (bswlist.b_flags & B_WANTED)
                        wakeup((caddr_t)&proc[2]);
                splx(s);
                if (bswlist.b_flags & B_WANTED)
                        wakeup((caddr_t)&proc[2]);
                splx(s);
+               return;
        }
        if (bp->b_flags&B_ASYNC)
                brelse(bp);
        }
        if (bp->b_flags&B_ASYNC)
                brelse(bp);
@@ -552,14 +593,14 @@ swap(p, dblkno, addr, nbytes, rdflg, flag, dev, pfcent)
        int p2dp;
        register struct pte *dpte, *vpte;
 
        int p2dp;
        register struct pte *dpte, *vpte;
 
-       VOID spl6();
+       (void) spl6();
        while (bswlist.av_forw == NULL) {
                bswlist.b_flags |= B_WANTED;
                sleep((caddr_t)&bswlist, PSWP+1);
        }
        bp = bswlist.av_forw;
        bswlist.av_forw = bp->av_forw;
        while (bswlist.av_forw == NULL) {
                bswlist.b_flags |= B_WANTED;
                sleep((caddr_t)&bswlist, PSWP+1);
        }
        bp = bswlist.av_forw;
        bswlist.av_forw = bp->av_forw;
-       VOID spl0();
+       (void) spl0();
 
        bp->b_flags = B_BUSY | B_PHYS | rdflg | flag;
        if ((bp->b_flags & (B_DIRTY|B_PGIN)) == 0)
 
        bp->b_flags = B_BUSY | B_PHYS | rdflg | flag;
        if ((bp->b_flags & (B_DIRTY|B_PGIN)) == 0)
@@ -585,20 +626,20 @@ swap(p, dblkno, addr, nbytes, rdflg, flag, dev, pfcent)
                bp->b_bcount = c;
                bp->b_blkno = dblkno;
                bp->b_dev = dev;
                bp->b_bcount = c;
                bp->b_blkno = dblkno;
                bp->b_dev = dev;
-               if (dev == swapdev)
-                       bp->b_blkno += swplo;
+               if (flag & B_DIRTY) {
+                       swpf[bp - swbuf] = pfcent;
+                       swsize[bp - swbuf] = nbytes;
+               }
                (*bdevsw[major(dev)].d_strategy)(bp);
                if (flag & B_DIRTY) {
                        if (c < nbytes)
                                panic("big push");
                (*bdevsw[major(dev)].d_strategy)(bp);
                if (flag & B_DIRTY) {
                        if (c < nbytes)
                                panic("big push");
-                       swsize[bp - swbuf] = nbytes;
-                       swpf[bp - swbuf] = pfcent;
                        return;
                }
                        return;
                }
-               VOID spl6();
+               (void) spl6();
                while((bp->b_flags&B_DONE)==0)
                        sleep((caddr_t)bp, PSWP);
                while((bp->b_flags&B_DONE)==0)
                        sleep((caddr_t)bp, PSWP);
-               VOID spl0();
+               (void) spl0();
                bp->b_un.b_addr += c;
                bp->b_flags &= ~B_DONE;
                if (bp->b_flags & B_ERROR) {
                bp->b_un.b_addr += c;
                bp->b_flags &= ~B_DONE;
                if (bp->b_flags & B_ERROR) {
@@ -609,7 +650,7 @@ swap(p, dblkno, addr, nbytes, rdflg, flag, dev, pfcent)
                nbytes -= c;
                dblkno += btoc(c);
        }
                nbytes -= c;
                dblkno += btoc(c);
        }
-       VOID spl6();
+       (void) spl6();
        bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS|B_PAGET|B_UAREA|B_DIRTY);
        bp->av_forw = bswlist.av_forw;
        bswlist.av_forw = bp;
        bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS|B_PAGET|B_UAREA|B_DIRTY);
        bp->av_forw = bswlist.av_forw;
        bswlist.av_forw = bp;
@@ -618,7 +659,7 @@ swap(p, dblkno, addr, nbytes, rdflg, flag, dev, pfcent)
                wakeup((caddr_t)&bswlist);
                wakeup((caddr_t)&proc[2]);
        }
                wakeup((caddr_t)&bswlist);
                wakeup((caddr_t)&proc[2]);
        }
-       VOID spl0();
+       (void) spl0();
 }
 
 /*
 }
 
 /*
@@ -642,7 +683,7 @@ swkill(p, rout)
         * done by user) after killing it so noone will try
         * to swap it out.
         */
         * done by user) after killing it so noone will try
         * to swap it out.
         */
-       psignal(p, SIGKIL);
+       psignal(p, SIGKILL);
        p->p_flag |= SULOCK;
 }
 
        p->p_flag |= SULOCK;
 }
 
@@ -658,7 +699,7 @@ dev_t dev;
        register struct buf *bp;
 
 loop:
        register struct buf *bp;
 
 loop:
-       VOID spl6();
+       (void) spl6();
        for (bp = bfreelist.av_forw; bp != &bfreelist; bp = bp->av_forw) {
                if (bp->b_flags&B_DELWRI && (dev == NODEV||dev==bp->b_dev)) {
                        bp->b_flags |= B_ASYNC;
        for (bp = bfreelist.av_forw; bp != &bfreelist; bp = bp->av_forw) {
                if (bp->b_flags&B_DELWRI && (dev == NODEV||dev==bp->b_dev)) {
                        bp->b_flags |= B_ASYNC;
@@ -667,7 +708,7 @@ loop:
                        goto loop;
                }
        }
                        goto loop;
                }
        }
-       VOID spl0();
+       (void) spl0();
 }
 
 /*
 }
 
 /*
@@ -696,7 +737,7 @@ unsigned (*mincnt)();
                u.u_error = EFAULT;
                return;
        }
                u.u_error = EFAULT;
                return;
        }
-       VOID spl6();
+       (void) spl6();
        while (bp->b_flags&B_BUSY) {
                bp->b_flags |= B_WANTED;
                sleep((caddr_t)bp, PRIBIO+1);
        while (bp->b_flags&B_BUSY) {
                bp->b_flags |= B_WANTED;
                sleep((caddr_t)bp, PRIBIO+1);
@@ -714,14 +755,14 @@ unsigned (*mincnt)();
                u.u_procp->p_flag |= SPHYSIO;
                vslock(a = bp->b_un.b_addr, c);
                (*strat)(bp);
                u.u_procp->p_flag |= SPHYSIO;
                vslock(a = bp->b_un.b_addr, c);
                (*strat)(bp);
-               VOID spl6();
+               (void) spl6();
                while ((bp->b_flags&B_DONE) == 0)
                        sleep((caddr_t)bp, PRIBIO);
                vsunlock(a, c, rw);
                u.u_procp->p_flag &= ~SPHYSIO;
                if (bp->b_flags&B_WANTED)
                        wakeup((caddr_t)bp);
                while ((bp->b_flags&B_DONE) == 0)
                        sleep((caddr_t)bp, PRIBIO);
                vsunlock(a, c, rw);
                u.u_procp->p_flag &= ~SPHYSIO;
                if (bp->b_flags&B_WANTED)
                        wakeup((caddr_t)bp);
-               VOID spl0();
+               (void) spl0();
                bp->b_un.b_addr += c;
                u.u_count -= c;
                u.u_offset += c;
                bp->b_un.b_addr += c;
                u.u_count -= c;
                u.u_offset += c;
@@ -755,3 +796,26 @@ register struct buf *bp;
                if ((u.u_error = bp->b_error)==0)
                        u.u_error = EIO;
 }
                if ((u.u_error = bp->b_error)==0)
                        u.u_error = EIO;
 }
+
+/*
+ * Invalidate in core blocks belonging to closed or umounted filesystem
+ *
+ * This is not nicely done at all - the buffer ought to be removed from the
+ * hash chains & have its dev/blkno fields clobbered, but unfortunately we
+ * can't do that here, as it is quite possible that the block is still
+ * being used for i/o. Eventually, all disc drivers should be forced to
+ * have a close routine, which ought ensure that the queue is empty, then
+ * properly flush the queues. Until that happy day, this suffices for
+ * correctness.                                                ... kre
+ */
+binval(dev)
+dev_t dev;
+{
+       register struct buf *bp, *dp;
+
+       dp = bdevsw[major(dev)].d_tab;
+
+       for (bp = dp->b_forw; bp != dp; bp = bp->b_forw)
+               if (bp->b_dev == dev)
+                       bp->b_flags |= B_INVAL;
+}