set/get timeouts using timevals
[unix-history] / usr / src / sys / kern / kern_physio.c
index fd5a092..b12dde4 100644 (file)
@@ -1,16 +1,13 @@
 /*
 /*
- * Copyright (c) 1982 Regents of the University of California.
+ * Copyright (c) 1982, 1986 Regents of the University of California.
  * 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       6.7 (Berkeley) %G%
+ *     @(#)kern_physio.c       7.14 (Berkeley) %G%
  */
 
  */
 
-#include "../machine/pte.h"
-
 #include "param.h"
 #include "systm.h"
 #include "param.h"
 #include "systm.h"
-#include "dir.h"
 #include "user.h"
 #include "buf.h"
 #include "conf.h"
 #include "user.h"
 #include "buf.h"
 #include "conf.h"
 #include "vm.h"
 #include "trace.h"
 #include "map.h"
 #include "vm.h"
 #include "trace.h"
 #include "map.h"
-#include "uio.h"
+#include "vnode.h"
+#include "specdev.h"
+
+#include "machine/pte.h"
+#ifdef SECSIZE
+#include "file.h"
+#include "ioctl.h"
+#include "disklabel.h"
+#endif SECSIZE
 
 /*
  * Swap IO headers -
 
 /*
  * Swap IO headers -
@@ -42,34 +47,29 @@ struct      buf *swbuf;
  * the index of the swap header that has been allocated.
  * We simply initialize the header and queue the I/O but
  * do not wait for completion. When the I/O completes,
  * the index of the swap header that has been allocated.
  * We simply initialize the header and queue the I/O but
  * do not wait for completion. When the I/O completes,
- * iodone() will link the header to a list of cleaned
+ * biodone() will link the header to a list of cleaned
  * pages to be processed by the pageout daemon.
  */
  * pages to be processed by the pageout daemon.
  */
-swap(p, dblkno, addr, nbytes, rdflg, flag, dev, pfcent)
+swap(p, dblkno, addr, nbytes, rdflg, flag, vp, pfcent)
        struct proc *p;
        swblk_t dblkno;
        caddr_t addr;
        int nbytes, rdflg, flag;
        struct proc *p;
        swblk_t dblkno;
        caddr_t addr;
        int nbytes, rdflg, flag;
-       dev_t dev;
+       struct vnode *vp;
        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();
-
-       s = 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;
-       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;
        bp->b_flags = B_BUSY | B_PHYS | rdflg | flag;
+#ifdef SECSIZE
+       bp->b_blksize = DEV_BSIZE;
+#endif SECSIZE
        if ((bp->b_flags & (B_DIRTY|B_PGIN)) == 0)
                if (rdflg == B_READ)
                        sum.v_pswpin += btoc(nbytes);
        if ((bp->b_flags & (B_DIRTY|B_PGIN)) == 0)
                if (rdflg == B_READ)
                        sum.v_pswpin += btoc(nbytes);
@@ -92,40 +92,51 @@ swap(p, dblkno, addr, nbytes, rdflg, flag, dev, pfcent)
        } else
                bp->b_un.b_addr = addr;
        while (nbytes > 0) {
        } else
                bp->b_un.b_addr = addr;
        while (nbytes > 0) {
+               bp->b_blkno = dblkno;
+               if (bp->b_vp)
+                       brelvp(bp);
+               VHOLD(vp);
+               bp->b_vp = vp;
+               bp->b_dev = vp->v_rdev;
                bp->b_bcount = nbytes;
                bp->b_bcount = nbytes;
+               if ((bp->b_flags & B_READ) == 0)
+                       vp->v_numoutput++;
                minphys(bp);
                c = bp->b_bcount;
                minphys(bp);
                c = bp->b_bcount;
-               bp->b_blkno = dblkno;
-               bp->b_dev = dev;
 #ifdef TRACE
 #ifdef TRACE
-               trace(TR_SWAPIO, dev, bp->b_blkno);
+               trace(TR_SWAPIO, vp, bp->b_blkno);
+#endif
+#if defined(hp300)
+               vmapbuf(bp);
 #endif
 #endif
-               physstrat(bp, bdevsw[major(dev)].d_strategy, PSWP);
+               VOP_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");
-                       return;
+                       return (0);
                }
                }
+#if defined(hp300)
+               vunmapbuf(bp);
+#endif
                bp->b_un.b_addr += c;
                bp->b_flags &= ~B_DONE;
                if (bp->b_flags & B_ERROR) {
                        if ((flag & (B_UAREA|B_PAGET)) || rdflg == B_WRITE)
                                panic("hard IO err in swap");
                        swkill(p, "swap: read error from swap device");
                bp->b_un.b_addr += c;
                bp->b_flags &= ~B_DONE;
                if (bp->b_flags & B_ERROR) {
                        if ((flag & (B_UAREA|B_PAGET)) || rdflg == B_WRITE)
                                panic("hard IO err in swap");
                        swkill(p, "swap: read error from swap device");
+                       error = EIO;
                }
                nbytes -= c;
                }
                nbytes -= c;
+#ifdef SECSIZE
+               if (flag & B_PGIN && nbytes > 0)
+                       panic("big pgin");
+#endif SECSIZE
                dblkno += btodb(c);
        }
                dblkno += btodb(c);
        }
-       s = spl6();
        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);
 }
 
 /*
 }
 
 /*
@@ -139,13 +150,16 @@ swdone(bp)
 
        if (bp->b_flags & B_ERROR)
                panic("IO err in push");
 
        if (bp->b_flags & B_ERROR)
                panic("IO err in push");
-       s = spl6();
+       s = splbio();
        bp->av_forw = bclnlist;
        cnt.v_pgout++;
        cnt.v_pgpgout += bp->b_bcount / NBPG;
        bclnlist = bp;
        if (bswlist.b_flags & B_WANTED)
                wakeup((caddr_t)&proc[2]);
        bp->av_forw = bclnlist;
        cnt.v_pgout++;
        cnt.v_pgpgout += bp->b_bcount / NBPG;
        bclnlist = bp;
        if (bswlist.b_flags & B_WANTED)
                wakeup((caddr_t)&proc[2]);
+#if defined(hp300)
+       vunmapbuf(bp);
+#endif
        splx(s);
 }
 
        splx(s);
 }
 
@@ -174,8 +188,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
@@ -190,71 +205,155 @@ 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;
        struct uio *uio;
 {
        register struct iovec *iov;
-       register int c;
+       register int requested, done;
        char *a;
        char *a;
-       int s, error = 0;
+       int s, allocbuf = 0, error = 0;
+       struct buf *getswbuf();
+#ifdef SECSIZE
+       int bsize;
+       struct partinfo dpart;
+#endif SECSIZE
 
 
-nextiov:
-       if (uio->uio_iovcnt == 0)
-               return (0);
-       iov = uio->uio_iov;
-       if (useracc(iov->iov_base,(u_int)iov->iov_len,rw==B_READ?B_WRITE:B_READ) == NULL)
-               return (EFAULT);
-       s = spl6();
-       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;
-       bp->b_un.b_addr = iov->iov_base;
-       while (iov->iov_len > 0) {
-               bp->b_flags = B_BUSY | B_PHYS | rw;
-               bp->b_dev = dev;
-               bp->b_blkno = btodb(uio->uio_offset);
-               bp->b_bcount = iov->iov_len;
-               (*mincnt)(bp);
-               c = bp->b_bcount;
-               u.u_procp->p_flag |= SPHYSIO;
-               vslock(a = bp->b_un.b_addr, c);
-               physstrat(bp, strat, PRIBIO);
-               (void) spl6();
-               vsunlock(a, c, rw);
-               u.u_procp->p_flag &= ~SPHYSIO;
-               if (bp->b_flags&B_WANTED)
-                       wakeup((caddr_t)bp);
-               splx(s);
-               c -= bp->b_resid;
-               bp->b_un.b_addr += c;
-               iov->iov_len -= c;
-               uio->uio_resid -= c;
-               uio->uio_offset += c;
-               /* temp kludge for tape drives */
-               if (bp->b_resid || (bp->b_flags&B_ERROR))
-                       break;
+#ifdef SECSIZE
+       if ((unsigned)major(dev) < nchrdev &&
+           (*cdevsw[major(dev)].d_ioctl)(dev, DIOCGPART, (caddr_t)&dpart,
+           FREAD) == 0)
+               bsize = dpart.disklab->d_secsize;
+       else
+               bsize = DEV_BSIZE;
+#endif SECSIZE
+       for (;;) {
+               if (uio->uio_iovcnt == 0)
+                       return (0);
+               iov = uio->uio_iov;
+               if (useracc(iov->iov_base, (u_int)iov->iov_len,
+                   rw==B_READ? B_WRITE : B_READ) == NULL)
+                       return (EFAULT);
+               s = splbio();
+               while (bp->b_flags&B_BUSY) {
+                       bp->b_flags |= B_WANTED;
+                       sleep((caddr_t)bp, PRIBIO+1);
+               }
+               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_blksize = bsize;
+#endif SECSIZE
+               bp->b_un.b_addr = iov->iov_base;
+               while (iov->iov_len > 0) {
+                       bp->b_flags = B_BUSY | B_PHYS | rw;
+                       bp->b_dev = dev;
+#ifdef SECSIZE
+                       bp->b_blkno = uio->uio_offset / bsize;
+#else SECSIZE
+                       bp->b_blkno = btodb(uio->uio_offset);
+#endif SECSIZE
+                       bp->b_bcount = iov->iov_len;
+                       (*mincnt)(bp);
+                       c = bp->b_bcount;
+                       u.u_procp->p_flag |= SPHYSIO;
+                       vslock(a = bp->b_un.b_addr, c);
+                       physstrat(bp, strat, PRIBIO);
+                       (void) splbio();
+                       vsunlock(a, c, rw);
+                       u.u_procp->p_flag &= ~SPHYSIO;
+                       if (bp->b_flags&B_WANTED)
+                               wakeup((caddr_t)bp);
+                       splx(s);
+                       c -= bp->b_resid;
+                       bp->b_un.b_addr += c;
+                       iov->iov_len -= c;
+                       uio->uio_resid -= c;
+                       uio->uio_offset += c;
+                       /* temp kludge for tape drives */
+                       if (bp->b_resid || (bp->b_flags&B_ERROR))
+                               break;
+               }
+               bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS);
+               error = geterror(bp);
+               if (bp->b_resid || error)
+                       return (error);
+               uio->uio_iov++;
+               uio->uio_iovcnt--;
        }
        }
-       bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS);
-       error = geterror(bp);
-       /* temp kludge for tape drives */
-       if (bp->b_resid || error)
-               return (error);
-       uio->uio_iov++;
-       uio->uio_iovcnt--;
-       goto nextiov;
+#if defined(hp300)
+       DCIU();
+#endif
+       if (allocbuf)
+               freeswbuf(bp);
+       return (error);
 }
 
 }
 
-#define        MAXPHYS (63 * 1024)
-
-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 (bp->b_vp)
+               brelvp(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));
+}