-/* kern_physio.c 6.5 85/03/12 */
+/*
+ * 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.
+ *
+ * @(#)kern_physio.c 7.4 (Berkeley) %G%
+ */
#include "../machine/pte.h"
#include "trace.h"
#include "map.h"
#include "uio.h"
+#ifdef SECSIZE
+#include "file.h"
+#include "ioctl.h"
+#include "disklabel.h"
+#endif SECSIZE
/*
* Swap IO headers -
* 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.
*/
swap(p, dblkno, addr, nbytes, rdflg, flag, dev, pfcent)
u_int pfcent;
{
register struct buf *bp;
- register u_int c;
- int p2dp;
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;
+#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);
#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");
- return;
+ return (0);
}
bp->b_un.b_addr += c;
bp->b_flags &= ~B_DONE;
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;
+#ifdef SECSIZE
+ if (flag & B_PGIN && nbytes > 0)
+ panic("big pgin");
+#endif SECSIZE
dblkno += btodb(c);
}
- s = 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;
- 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);
}
/*
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;
char *rout;
{
- printf("pid %d: %s", p->p_pid, rout);
- uprintf("sorry, pid %d was killed in %s", p->p_pid, rout);
+ printf("pid %d: %s\n", p->p_pid, rout);
+ uprintf("sorry, pid %d was killed in %s\n", p->p_pid, rout);
/*
* To be sure no looping (e.g. in vmsched trying to
* swap out) mark process locked in core (as though
/*
* 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
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;
- int s, error = 0;
-
-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;
+ int s, allocbuf = 0, error = 0;
+ struct buf *getswbuf();
+#ifdef SECSIZE
+ int bsize;
+ struct partinfo dpart;
+#endif SECSIZE
+
+#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);
/* temp kludge for tape drives */
- if (bp->b_resid || (bp->b_flags&B_ERROR))
- break;
+ 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 (allocbuf)
+ freeswbuf(bp);
+ return (error);
}
-#define MAXPHYS (63 * 1024)
-
-unsigned
+u_int
minphys(bp)
struct buf *bp;
{
-
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));
+}