X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/bd841446bdf4b00d2eaa875496e82563a285b5a3..1eebc1a70802d2bd87f4a95eba439778ff6803ae:/usr/src/sys/kern/kern_physio.c diff --git a/usr/src/sys/kern/kern_physio.c b/usr/src/sys/kern/kern_physio.c index 4a34d8c6a9..eedca3ad2d 100644 --- a/usr/src/sys/kern/kern_physio.c +++ b/usr/src/sys/kern/kern_physio.c @@ -1,16 +1,30 @@ -/* kern_physio.c 4.30 82/05/22 */ +/* + * 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.3 (Berkeley) %G% + */ + +#include "../machine/pte.h" -#include "../h/param.h" -#include "../h/systm.h" -#include "../h/dir.h" -#include "../h/user.h" -#include "../h/buf.h" -#include "../h/conf.h" -#include "../h/proc.h" -#include "../h/seg.h" -#include "../h/pte.h" -#include "../h/vm.h" -#include "../h/trace.h" +#include "param.h" +#include "systm.h" +#include "dir.h" +#include "user.h" +#include "buf.h" +#include "conf.h" +#include "proc.h" +#include "seg.h" +#include "vm.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 - @@ -23,8 +37,6 @@ * in a list of cleaned pages to be processed by the pageout daemon. */ struct buf *swbuf; -short *swsize; /* CAN WE JUST USE B_BCOUNT? */ -int *swpf; /* * swap I/O - @@ -35,24 +47,26 @@ int *swpf; * 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) struct proc *p; swblk_t dblkno; caddr_t addr; - int flag, nbytes; + int nbytes, rdflg, flag; dev_t dev; - unsigned pfcent; + u_int pfcent; { register struct buf *bp; - register int c; + register u_int c; int p2dp; register struct pte *dpte, *vpte; int s; + extern swdone(); + int error = 0; - s = spl6(); + s = splbio(); while (bswlist.av_forw == NULL) { bswlist.b_flags |= B_WANTED; sleep((caddr_t)&bswlist, PSWP+1); @@ -62,6 +76,9 @@ swap(p, dblkno, addr, nbytes, rdflg, flag, dev, pfcent) splx(s); 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); @@ -77,42 +94,43 @@ swap(p, dblkno, addr, nbytes, rdflg, flag, dev, pfcent) panic("swap bad pte"); *dpte++ = *vpte++; } - bp->b_un.b_addr = (caddr_t)ctob(p2dp); + bp->b_un.b_addr = (caddr_t)ctob(dptov(&proc[2], p2dp)); + bp->b_flags |= B_CALL; + bp->b_iodone = swdone; + bp->b_pfcent = pfcent; } else bp->b_un.b_addr = addr; while (nbytes > 0) { - c = imin(ctob(120), nbytes); - bp->b_bcount = c; + bp->b_bcount = nbytes; + minphys(bp); + c = bp->b_bcount; bp->b_blkno = dblkno; bp->b_dev = dev; - if (flag & B_DIRTY) { - swpf[bp - swbuf] = pfcent; - swsize[bp - swbuf] = nbytes; - } #ifdef TRACE trace(TR_SWAPIO, dev, bp->b_blkno); #endif - (*bdevsw[major(dev)].d_strategy)(bp); + physstrat(bp, bdevsw[major(dev)].d_strategy, PSWP); if (flag & B_DIRTY) { if (c < nbytes) panic("big push"); - return; + return (0); } - s = spl6(); - while((bp->b_flags&B_DONE)==0) - sleep((caddr_t)bp, PSWP); - splx(s); 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, (char *)0); + swkill(p, "swap: read error from swap device"); + error = EIO; } nbytes -= c; - dblkno += btoc(c); +#ifdef SECSIZE + if (flag & B_PGIN && nbytes > 0) + panic("big pgin"); +#endif SECSIZE + dblkno += btodb(c); } - s = spl6(); + 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; @@ -122,6 +140,28 @@ swap(p, dblkno, addr, nbytes, rdflg, flag, dev, pfcent) wakeup((caddr_t)&proc[2]); } splx(s); + return (error); +} + +/* + * Put a buffer on the clean list after I/O is done. + * Called from biodone. + */ +swdone(bp) + register struct buf *bp; +{ + register int s; + + if (bp->b_flags & B_ERROR) + panic("IO err in push"); + 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]); + splx(s); } /* @@ -133,14 +173,9 @@ swkill(p, rout) struct proc *p; char *rout; { - char *mesg; - printf("pid %d: ", p->p_pid); - if (rout) - printf(mesg = "killed due to no swap space\n"); - else - printf(mesg = "killed on swap error\n"); - uprintf("sorry, pid %d was %s", p->p_pid, mesg); + 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 @@ -165,64 +200,94 @@ swkill(p, rout) * faulted and locked. After the completion of the I/O, the above pages * are unlocked. */ -physio(strat, bp, dev, rw, mincnt) -int (*strat)(); -register struct buf *bp; -unsigned (*mincnt)(); +physio(strat, bp, dev, rw, mincnt, uio) + int (*strat)(); + register struct buf *bp; + dev_t dev; + int rw; + unsigned (*mincnt)(); + struct uio *uio; { + register struct iovec *iov; register int c; char *a; - int s; + int s, error = 0; +#ifdef SECSIZE + int bsize; + struct partinfo dpart; +#endif SECSIZE - if (useracc(u.u_base,u.u_count,rw==B_READ?B_WRITE:B_READ) == NULL) { - u.u_error = EFAULT; - return; - } - 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 = u.u_base; - while (u.u_count != 0) { - bp->b_flags = B_BUSY | B_PHYS | rw; - bp->b_dev = dev; - bp->b_blkno = u.u_offset >> PGSHIFT; - bp->b_bcount = u.u_count; - (*mincnt)(bp); - c = bp->b_bcount; - u.u_procp->p_flag |= SPHYSIO; - vslock(a = bp->b_un.b_addr, c); - (*strat)(bp); - (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); +#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); + } splx(s); - bp->b_un.b_addr += c; - u.u_count -= c; - u.u_offset += c; - if (bp->b_flags&B_ERROR) - break; + 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 || error) + return (error); + uio->uio_iov++; + uio->uio_iovcnt--; } - bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS); - u.u_count = bp->b_resid; - geterror(bp); } -/*ARGSUSED*/ unsigned minphys(bp) -struct buf *bp; + struct buf *bp; { - if (bp->b_bcount > 63 * 1024) - bp->b_bcount = 63 * 1024; + if (bp->b_bcount > MAXPHYS) + bp->b_bcount = MAXPHYS; } -