* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*
- * @(#)kern_physio.c 7.3 (Berkeley) %G%
+ * @(#)kern_physio.c 7.4 (Berkeley) %G%
*/
#include "../machine/pte.h"
u_int pfcent;
{
register struct buf *bp;
- register u_int c;
- int p2dp;
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;
#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");
#endif SECSIZE
dblkno += btodb(c);
}
- s = splbio();
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);
}
/*
* 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;
+ int s, allocbuf = 0, error = 0;
+ struct buf *getswbuf();
#ifdef SECSIZE
int bsize;
struct partinfo dpart;
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
uio->uio_iov++;
uio->uio_iovcnt--;
}
+ if (allocbuf)
+ freeswbuf(bp);
+ return (error);
}
-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));
+}