../machine => machine
[unix-history] / usr / src / sys / kern / kern_physio.c
index 96d7120..79e2e03 100644 (file)
@@ -3,11 +3,9 @@
  * 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.
  *
- *     @(#)kern_physio.c       7.2.1.1 (Berkeley) %G%
+ *     @(#)kern_physio.c       7.5 (Berkeley) %G%
  */
 
  */
 
-#include "../machine/pte.h"
-
 #include "param.h"
 #include "systm.h"
 #include "dir.h"
 #include "param.h"
 #include "systm.h"
 #include "dir.h"
@@ -20,6 +18,8 @@
 #include "trace.h"
 #include "map.h"
 #include "uio.h"
 #include "trace.h"
 #include "map.h"
 #include "uio.h"
+
+#include "machine/pte.h"
 #ifdef SECSIZE
 #include "file.h"
 #include "ioctl.h"
 #ifdef SECSIZE
 #include "file.h"
 #include "ioctl.h"
@@ -59,22 +59,13 @@ swap(p, dblkno, addr, nbytes, rdflg, flag, dev, pfcent)
        u_int pfcent;
 {
        register struct buf *bp;
        u_int pfcent;
 {
        register struct buf *bp;
-       register u_int c;
-       int p2dp;
        register struct pte *dpte, *vpte;
        register struct pte *dpte, *vpte;
-       int s;
-       extern swdone();
-       int error = 0;
-
-       s = splbio();
-       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;
-       splx(s);
+       register u_int c;
+       int p2dp, s, error = 0;
+       struct buf *getswbuf();
+       int swdone();
 
 
+       bp = getswbuf(PSWP+1);
        bp->b_flags = B_BUSY | B_PHYS | rdflg | flag;
 #ifdef SECSIZE
        bp->b_blksize = DEV_BSIZE;
        bp->b_flags = B_BUSY | B_PHYS | rdflg | flag;
 #ifdef SECSIZE
        bp->b_blksize = DEV_BSIZE;
@@ -109,7 +100,8 @@ swap(p, dblkno, addr, nbytes, rdflg, flag, dev, pfcent)
 #ifdef TRACE
                trace(TR_SWAPIO, dev, bp->b_blkno);
 #endif
 #ifdef TRACE
                trace(TR_SWAPIO, dev, bp->b_blkno);
 #endif
-               physstrat(bp, bdevsw[major(dev)].d_strategy, PSWP);
+               (*bdevsw[major(dev)].d_strategy)(bp);
+               /* pageout daemon doesn't wait for pushed pages */
                if (flag & B_DIRTY) {
                        if (c < nbytes)
                                panic("big push");
                if (flag & B_DIRTY) {
                        if (c < nbytes)
                                panic("big push");
@@ -130,16 +122,8 @@ swap(p, dblkno, addr, nbytes, rdflg, flag, dev, pfcent)
 #endif SECSIZE
                dblkno += btodb(c);
        }
 #endif SECSIZE
                dblkno += btodb(c);
        }
-       s = splbio();
        bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS|B_PAGET|B_UAREA|B_DIRTY);
        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;
-       if (bswlist.b_flags & B_WANTED) {
-               bswlist.b_flags &= ~B_WANTED;
-               wakeup((caddr_t)&bswlist);
-               wakeup((caddr_t)&proc[2]);
-       }
-       splx(s);
+       freeswbuf(bp);
        return (error);
 }
 
        return (error);
 }
 
@@ -189,8 +173,9 @@ swkill(p, rout)
 /*
  * Raw I/O. The arguments are
  *     The strategy routine for the device
 /*
  * Raw I/O. The arguments are
  *     The strategy routine for the device
- *     A buffer, which will always be a special buffer
- *       header owned exclusively by the device for this purpose
+ *     A buffer, which will either be a special buffer header owned
+ *         exclusively by the device for this purpose, or NULL,
+ *         indicating that we should use a swap buffer
  *     The device number
  *     Read/write flag
  * Essentially all the work is computing physical addresses and
  *     The device number
  *     Read/write flag
  * Essentially all the work is computing physical addresses and
@@ -205,13 +190,14 @@ physio(strat, bp, dev, rw, mincnt, uio)
        register struct buf *bp;
        dev_t dev;
        int rw;
        register struct buf *bp;
        dev_t dev;
        int rw;
-       unsigned (*mincnt)();
+       u_int (*mincnt)();
        struct uio *uio;
 {
        register struct iovec *iov;
        register int c;
        char *a;
        struct uio *uio;
 {
        register struct iovec *iov;
        register int c;
        char *a;
-       int s, error = 0;
+       int s, allocbuf = 0, error = 0;
+       struct buf *getswbuf();
 #ifdef SECSIZE
        int bsize;
        struct partinfo dpart;
 #ifdef SECSIZE
        int bsize;
        struct partinfo dpart;
@@ -237,7 +223,14 @@ physio(strat, bp, dev, rw, mincnt, uio)
                        bp->b_flags |= B_WANTED;
                        sleep((caddr_t)bp, PRIBIO+1);
                }
                        bp->b_flags |= B_WANTED;
                        sleep((caddr_t)bp, PRIBIO+1);
                }
-               splx(s);
+               if (!allocbuf) {        /* only if sharing caller's buffer */
+                       s = splbio();
+                       while (bp->b_flags&B_BUSY) {
+                               bp->b_flags |= B_WANTED;
+                               sleep((caddr_t)bp, PRIBIO+1);
+                       }
+                       splx(s);
+               }
                bp->b_error = 0;
                bp->b_proc = u.u_procp;
 #ifdef SECSIZE
                bp->b_error = 0;
                bp->b_proc = u.u_procp;
 #ifdef SECSIZE
@@ -281,13 +274,67 @@ physio(strat, bp, dev, rw, mincnt, uio)
                uio->uio_iov++;
                uio->uio_iovcnt--;
        }
                uio->uio_iov++;
                uio->uio_iovcnt--;
        }
+       if (allocbuf)
+               freeswbuf(bp);
+       return (error);
 }
 
 }
 
-unsigned
+u_int
 minphys(bp)
        struct buf *bp;
 {
 minphys(bp)
        struct buf *bp;
 {
-
        if (bp->b_bcount > MAXPHYS)
                bp->b_bcount = MAXPHYS;
 }
        if (bp->b_bcount > MAXPHYS)
                bp->b_bcount = MAXPHYS;
 }
+
+static
+struct buf *
+getswbuf(prio)
+       int prio;
+{
+       int s;
+       struct buf *bp;
+
+       s = splbio();
+       while (bswlist.av_forw == NULL) {
+               bswlist.b_flags |= B_WANTED;
+               sleep((caddr_t)&bswlist, prio);
+       }
+       bp = bswlist.av_forw;
+       bswlist.av_forw = bp->av_forw;
+       splx(s);
+       return (bp);
+}
+
+static
+freeswbuf(bp)
+       struct buf *bp;
+{
+       int s;
+
+       s = splbio();
+       bp->av_forw = bswlist.av_forw;
+       bswlist.av_forw = bp;
+       if (bswlist.b_flags & B_WANTED) {
+               bswlist.b_flags &= ~B_WANTED;
+               wakeup((caddr_t)&bswlist);
+               wakeup((caddr_t)&proc[2]);
+       }
+       splx(s);
+}
+
+rawread(dev, uio)
+       dev_t dev;
+       struct uio *uio;
+{
+       return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL,
+           dev, B_READ, minphys, uio));
+}
+
+rawwrite(dev, uio)
+       dev_t dev;
+       struct uio *uio;
+{
+       return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL,
+           dev, B_WRITE, minphys, uio));
+}