Annotation of 43BSDReno/sys/kern/vm_swp.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  *
                      6:  *     @(#)vm_swp.c    7.15 (Berkeley) 6/30/90
                      7:  */
                      8: 
                      9: #include "param.h"
                     10: #include "systm.h"
                     11: #include "user.h"
                     12: #include "buf.h"
                     13: #include "conf.h"
                     14: #include "proc.h"
                     15: #include "seg.h"
                     16: #include "vm.h"
                     17: #include "trace.h"
                     18: #include "map.h"
                     19: #include "vnode.h"
                     20: #include "specdev.h"
                     21: 
                     22: #include "machine/pte.h"
                     23: 
                     24: /*
                     25:  * Swap IO headers -
                     26:  * They contain the necessary information for the swap I/O.
                     27:  * At any given time, a swap header can be in three
                     28:  * different lists. When free it is in the free list, 
                     29:  * when allocated and the I/O queued, it is on the swap 
                     30:  * device list, and finally, if the operation was a dirty 
                     31:  * page push, when the I/O completes, it is inserted 
                     32:  * in a list of cleaned pages to be processed by the pageout daemon.
                     33:  */
                     34: struct buf *swbuf;
                     35: 
                     36: /*
                     37:  * swap I/O -
                     38:  *
                     39:  * If the flag indicates a dirty page push initiated
                     40:  * by the pageout daemon, we map the page into the i th
                     41:  * virtual page of process 2 (the daemon itself) where i is
                     42:  * the index of the swap header that has been allocated.
                     43:  * We simply initialize the header and queue the I/O but
                     44:  * do not wait for completion. When the I/O completes,
                     45:  * biodone() will link the header to a list of cleaned
                     46:  * pages to be processed by the pageout daemon.
                     47:  */
                     48: swap(p, dblkno, addr, nbytes, rdflg, flag, vp, pfcent)
                     49:        struct proc *p;
                     50:        swblk_t dblkno;
                     51:        caddr_t addr;
                     52:        int nbytes, rdflg, flag;
                     53:        struct vnode *vp;
                     54:        u_int pfcent;
                     55: {
                     56:        register struct buf *bp;
                     57:        register struct pte *dpte, *vpte;
                     58:        register u_int c;
                     59:        int p2dp, s, error = 0;
                     60:        struct buf *getswbuf();
                     61:        int swdone();
                     62: 
                     63:        bp = getswbuf(PSWP+1);
                     64:        bp->b_flags = B_BUSY | B_PHYS | rdflg | flag;
                     65:        if ((bp->b_flags & (B_DIRTY|B_PGIN)) == 0)
                     66:                if (rdflg == B_READ)
                     67:                        sum.v_pswpin += btoc(nbytes);
                     68:                else
                     69:                        sum.v_pswpout += btoc(nbytes);
                     70:        bp->b_proc = p;
                     71:        if (flag & B_DIRTY) {
                     72:                p2dp = ((bp - swbuf) * CLSIZE) * KLMAX;
                     73:                dpte = dptopte(&proc[2], p2dp);
                     74:                vpte = vtopte(p, btop(addr));
                     75:                for (c = 0; c < nbytes; c += NBPG) {
                     76:                        if (vpte->pg_pfnum == 0 || vpte->pg_fod)
                     77:                                panic("swap bad pte");
                     78:                        *dpte++ = *vpte++;
                     79:                }
                     80:                bp->b_un.b_addr = (caddr_t)ctob(dptov(&proc[2], p2dp));
                     81:                bp->b_flags |= B_CALL;
                     82:                bp->b_iodone = swdone;
                     83:                bp->b_pfcent = pfcent;
                     84:        } else
                     85:                bp->b_un.b_addr = addr;
                     86:        while (nbytes > 0) {
                     87:                bp->b_blkno = dblkno;
                     88:                if (bp->b_vp)
                     89:                        brelvp(bp);
                     90:                VHOLD(vp);
                     91:                bp->b_vp = vp;
                     92:                bp->b_dev = vp->v_rdev;
                     93:                bp->b_bcount = nbytes;
                     94:                if ((bp->b_flags & B_READ) == 0)
                     95:                        vp->v_numoutput++;
                     96:                minphys(bp);
                     97:                c = bp->b_bcount;
                     98: #ifdef TRACE
                     99:                trace(TR_SWAPIO, vp, bp->b_blkno);
                    100: #endif
                    101: #if defined(hp300) || defined(i386)
                    102:                vmapbuf(bp);
                    103: #endif
                    104:                VOP_STRATEGY(bp);
                    105:                /* pageout daemon doesn't wait for pushed pages */
                    106:                if (flag & B_DIRTY) {
                    107:                        if (c < nbytes)
                    108:                                panic("big push");
                    109:                        return (0);
                    110:                } else {
                    111:                        s = splbio();
                    112:                        while ((bp->b_flags & B_DONE) == 0)
                    113:                                sleep((caddr_t)bp, PSWP);
                    114:                        splx(s);
                    115:                }
                    116: #if defined(hp300) || defined(i386)
                    117:                vunmapbuf(bp);
                    118: #endif
                    119:                bp->b_un.b_addr += c;
                    120:                bp->b_flags &= ~B_DONE;
                    121:                if (bp->b_flags & B_ERROR) {
                    122:                        if ((flag & (B_UAREA|B_PAGET)) || rdflg == B_WRITE)
                    123:                                panic("hard IO err in swap");
                    124:                        swkill(p, "swap: read error from swap device");
                    125:                        error = EIO;
                    126:                }
                    127:                nbytes -= c;
                    128:                dblkno += btodb(c);
                    129:        }
                    130:        bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS|B_PAGET|B_UAREA|B_DIRTY);
                    131:        freeswbuf(bp);
                    132:        return (error);
                    133: }
                    134: 
                    135: /*
                    136:  * Put a buffer on the clean list after I/O is done.
                    137:  * Called from biodone.
                    138:  */
                    139: swdone(bp)
                    140:        register struct buf *bp;
                    141: {
                    142:        register int s;
                    143: 
                    144:        if (bp->b_flags & B_ERROR)
                    145:                panic("IO err in push");
                    146:        s = splbio();
                    147:        bp->av_forw = bclnlist;
                    148:        cnt.v_pgout++;
                    149:        cnt.v_pgpgout += bp->b_bcount / NBPG;
                    150:        bclnlist = bp;
                    151:        if (bswlist.b_flags & B_WANTED)
                    152:                wakeup((caddr_t)&proc[2]);
                    153: #if defined(hp300) || defined(i386)
                    154:        vunmapbuf(bp);
                    155: #endif
                    156:        splx(s);
                    157: }
                    158: 
                    159: /*
                    160:  * If rout == 0 then killed on swap error, else
                    161:  * rout is the name of the routine where we ran out of
                    162:  * swap space.
                    163:  */
                    164: swkill(p, rout)
                    165:        struct proc *p;
                    166:        char *rout;
                    167: {
                    168: 
                    169:        printf("pid %d: %s\n", p->p_pid, rout);
                    170:        uprintf("sorry, pid %d was killed in %s\n", p->p_pid, rout);
                    171:        /*
                    172:         * To be sure no looping (e.g. in vmsched trying to
                    173:         * swap out) mark process locked in core (as though
                    174:         * done by user) after killing it so noone will try
                    175:         * to swap it out.
                    176:         */
                    177:        psignal(p, SIGKILL);
                    178:        p->p_flag |= SULOCK;
                    179: }
                    180: 
                    181: /*
                    182:  * Raw I/O. The arguments are
                    183:  *     The strategy routine for the device
                    184:  *     A buffer, which will either be a special buffer header owned
                    185:  *         exclusively by the device for this purpose, or NULL,
                    186:  *         indicating that we should use a swap buffer
                    187:  *     The device number
                    188:  *     Read/write flag
                    189:  * Essentially all the work is computing physical addresses and
                    190:  * validating them.
                    191:  * If the user has the proper access privilidges, the process is
                    192:  * marked 'delayed unlock' and the pages involved in the I/O are
                    193:  * faulted and locked. After the completion of the I/O, the above pages
                    194:  * are unlocked.
                    195:  */
                    196: physio(strat, bp, dev, rw, mincnt, uio)
                    197:        int (*strat)(); 
                    198:        register struct buf *bp;
                    199:        dev_t dev;
                    200:        int rw;
                    201:        u_int (*mincnt)();
                    202:        struct uio *uio;
                    203: {
                    204:        register struct iovec *iov;
                    205:        register int requested, done;
                    206:        char *a;
                    207:        int s, allocbuf = 0, error = 0;
                    208:        struct buf *getswbuf();
                    209: 
                    210:        if (bp == NULL) {
                    211:                allocbuf = 1;
                    212:                bp = getswbuf(PRIBIO+1);
                    213:        }
                    214:        for (; uio->uio_iovcnt; uio->uio_iov++, uio->uio_iovcnt--) {
                    215:                iov = uio->uio_iov;
                    216:                if (!useracc(iov->iov_base, (u_int)iov->iov_len,
                    217:                    rw == B_READ ? B_WRITE : B_READ)) {
                    218:                        error = EFAULT;
                    219:                        break;
                    220:                }
                    221:                if (!allocbuf) {        /* only if sharing caller's buffer */
                    222:                        s = splbio();
                    223:                        while (bp->b_flags&B_BUSY) {
                    224:                                bp->b_flags |= B_WANTED;
                    225:                                sleep((caddr_t)bp, PRIBIO+1);
                    226:                        }
                    227:                        splx(s);
                    228:                }
                    229:                bp->b_error = 0;
                    230:                bp->b_proc = u.u_procp;
                    231: #ifdef HPUXCOMPAT
                    232:                if (ISHPMMADDR(iov->iov_base))
                    233:                        bp->b_un.b_addr = (caddr_t)HPMMBASEADDR(iov->iov_base);
                    234:                else
                    235: #endif
                    236:                bp->b_un.b_addr = iov->iov_base;
                    237:                while (iov->iov_len > 0) {
                    238:                        bp->b_flags = B_BUSY | B_PHYS | B_RAW | rw;
                    239:                        bp->b_dev = dev;
                    240:                        bp->b_blkno = btodb(uio->uio_offset);
                    241:                        bp->b_bcount = iov->iov_len;
                    242:                        (*mincnt)(bp);
                    243:                        requested = bp->b_bcount;
                    244:                        u.u_procp->p_flag |= SPHYSIO;
                    245:                        vslock(a = bp->b_un.b_addr, requested);
                    246: #if defined(hp300) || defined(i386)
                    247:                        vmapbuf(bp);
                    248: #endif
                    249:                        (*strat)(bp);
                    250:                        s = splbio();
                    251:                        while ((bp->b_flags & B_DONE) == 0)
                    252:                                sleep((caddr_t)bp, PRIBIO);
                    253: #if defined(hp300) || defined(i386)
                    254:                        vunmapbuf(bp);
                    255: #endif
                    256:                        vsunlock(a, requested, rw);
                    257:                        u.u_procp->p_flag &= ~SPHYSIO;
                    258:                        if (bp->b_flags&B_WANTED)       /* rare */
                    259:                                wakeup((caddr_t)bp);
                    260:                        splx(s);
                    261:                        done = bp->b_bcount - bp->b_resid;
                    262:                        bp->b_un.b_addr += done;
                    263:                        iov->iov_len -= done;
                    264:                        uio->uio_resid -= done;
                    265:                        uio->uio_offset += done;
                    266:                        /* temp kludge for disk drives */
                    267:                        if (done < requested || bp->b_flags & B_ERROR)
                    268:                                break;
                    269:                }
                    270:                bp->b_flags &= ~(B_BUSY | B_WANTED | B_PHYS | B_RAW);
                    271:                error = biowait(bp);
                    272:                /* temp kludge for disk drives */
                    273:                if (done < requested || bp->b_flags & B_ERROR)
                    274:                        break;
                    275:        }
                    276: #if defined(hp300)
                    277:        DCIU();
                    278: #endif
                    279:        if (allocbuf)
                    280:                freeswbuf(bp);
                    281:        return (error);
                    282: }
                    283: 
                    284: u_int
                    285: minphys(bp)
                    286:        struct buf *bp;
                    287: {
                    288:        if (bp->b_bcount > MAXPHYS)
                    289:                bp->b_bcount = MAXPHYS;
                    290: }
                    291: 
                    292: static
                    293: struct buf *
                    294: getswbuf(prio)
                    295:        int prio;
                    296: {
                    297:        int s;
                    298:        struct buf *bp;
                    299: 
                    300:        s = splbio();
                    301:        while (bswlist.av_forw == NULL) {
                    302:                bswlist.b_flags |= B_WANTED;
                    303:                sleep((caddr_t)&bswlist, prio);
                    304:        }
                    305:        bp = bswlist.av_forw;
                    306:        bswlist.av_forw = bp->av_forw;
                    307:        splx(s);
                    308:        return (bp);
                    309: }
                    310: 
                    311: static
                    312: freeswbuf(bp)
                    313:        struct buf *bp;
                    314: {
                    315:        int s;
                    316: 
                    317:        s = splbio();
                    318:        bp->av_forw = bswlist.av_forw;
                    319:        bswlist.av_forw = bp;
                    320:        if (bp->b_vp)
                    321:                brelvp(bp);
                    322:        if (bswlist.b_flags & B_WANTED) {
                    323:                bswlist.b_flags &= ~B_WANTED;
                    324:                wakeup((caddr_t)&bswlist);
                    325:                wakeup((caddr_t)&proc[2]);
                    326:        }
                    327:        splx(s);
                    328: }
                    329: 
                    330: rawread(dev, uio)
                    331:        dev_t dev;
                    332:        struct uio *uio;
                    333: {
                    334:        return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL,
                    335:            dev, B_READ, minphys, uio));
                    336: }
                    337: 
                    338: rawwrite(dev, uio)
                    339:        dev_t dev;
                    340:        struct uio *uio;
                    341: {
                    342:        return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL,
                    343:            dev, B_WRITE, minphys, uio));
                    344: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.