Annotation of 43BSDReno/sys/kern/vm_swp.c, revision 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.