Annotation of Net2/vm/swap_pager.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1990 University of Utah.
        !             3:  * Copyright (c) 1991 The Regents of the University of California.
        !             4:  * All rights reserved.
        !             5:  *
        !             6:  * This code is derived from software contributed to Berkeley by
        !             7:  * the Systems Programming Group of the University of Utah Computer
        !             8:  * Science Department.
        !             9:  *
        !            10:  * Redistribution and use in source and binary forms, with or without
        !            11:  * modification, are permitted provided that the following conditions
        !            12:  * are met:
        !            13:  * 1. Redistributions of source code must retain the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer.
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in the
        !            17:  *    documentation and/or other materials provided with the distribution.
        !            18:  * 3. All advertising materials mentioning features or use of this software
        !            19:  *    must display the following acknowledgement:
        !            20:  *     This product includes software developed by the University of
        !            21:  *     California, Berkeley and its contributors.
        !            22:  * 4. Neither the name of the University nor the names of its contributors
        !            23:  *    may be used to endorse or promote products derived from this software
        !            24:  *    without specific prior written permission.
        !            25:  *
        !            26:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            28:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            29:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            30:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            31:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            32:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            36:  * SUCH DAMAGE.
        !            37:  *
        !            38:  * from: Utah $Hdr: swap_pager.c 1.4 91/04/30$
        !            39:  *
        !            40:  *     @(#)swap_pager.c        7.4 (Berkeley) 5/7/91
        !            41:  */
        !            42: 
        !            43: /*
        !            44:  * Quick hack to page to dedicated partition(s).
        !            45:  * TODO:
        !            46:  *     Add multiprocessor locks
        !            47:  *     Deal with async writes in a better fashion
        !            48:  */
        !            49: 
        !            50: #include "swappager.h"
        !            51: #if NSWAPPAGER > 0
        !            52: 
        !            53: #include "param.h"
        !            54: #include "proc.h"
        !            55: #include "buf.h"
        !            56: #include "map.h"
        !            57: #include "systm.h"
        !            58: #include "specdev.h"
        !            59: #include "vnode.h"
        !            60: #include "malloc.h"
        !            61: #include "queue.h"
        !            62: 
        !            63: #include "vm_param.h"
        !            64: #include "queue.h"
        !            65: #include "lock.h"
        !            66: #include "vm_prot.h"
        !            67: #include "vm_object.h"
        !            68: #include "vm_page.h"
        !            69: #include "vm_pageout.h"
        !            70: #include "swap_pager.h"
        !            71: 
        !            72: #define NSWSIZES       16      /* size of swtab */
        !            73: #define NPENDINGIO     64      /* max # of pending cleans */
        !            74: #define MAXDADDRS      64      /* max # of disk addrs for fixed allocations */
        !            75: 
        !            76: #ifdef DEBUG
        !            77: int    swpagerdebug = 0x100;
        !            78: #define        SDB_FOLLOW      0x001
        !            79: #define SDB_INIT       0x002
        !            80: #define SDB_ALLOC      0x004
        !            81: #define SDB_IO         0x008
        !            82: #define SDB_WRITE      0x010
        !            83: #define SDB_FAIL       0x020
        !            84: #define SDB_ALLOCBLK   0x040
        !            85: #define SDB_FULL       0x080
        !            86: #define SDB_ANOM       0x100
        !            87: #define SDB_ANOMPANIC  0x200
        !            88: #endif
        !            89: 
        !            90: struct swpagerclean {
        !            91:        queue_head_t            spc_list;
        !            92:        int                     spc_flags;
        !            93:        struct buf              *spc_bp;
        !            94:        sw_pager_t              spc_swp;
        !            95:        vm_offset_t             spc_kva;
        !            96:        vm_page_t               spc_m;
        !            97: } swcleanlist[NPENDINGIO];
        !            98: typedef        struct swpagerclean     *swp_clean_t;
        !            99: 
        !           100: /* spc_flags values */
        !           101: #define SPC_FREE       0x00
        !           102: #define SPC_BUSY       0x01
        !           103: #define SPC_DONE       0x02
        !           104: #define SPC_ERROR      0x04
        !           105: #define SPC_DIRTY      0x08
        !           106: 
        !           107: struct swtab {
        !           108:        vm_size_t st_osize;     /* size of object (bytes) */
        !           109:        int       st_bsize;     /* vs. size of swap block (DEV_BSIZE units) */
        !           110: #ifdef DEBUG
        !           111:        u_long    st_inuse;     /* number in this range in use */
        !           112:        u_long    st_usecnt;    /* total used of this size */
        !           113: #endif
        !           114: } swtab[NSWSIZES+1];
        !           115: 
        !           116: #ifdef DEBUG
        !           117: int            swap_pager_pendingio;   /* max pending async "clean" ops */
        !           118: int            swap_pager_poip;        /* pageouts in progress */
        !           119: int            swap_pager_piip;        /* pageins in progress */
        !           120: #endif
        !           121: 
        !           122: queue_head_t   swap_pager_inuse;       /* list of pending page cleans */
        !           123: queue_head_t   swap_pager_free;        /* list of free pager clean structs */
        !           124: queue_head_t   swap_pager_list;        /* list of "named" anon regions */
        !           125: 
        !           126: void
        !           127: swap_pager_init()
        !           128: {
        !           129:        register swp_clean_t spc;
        !           130:        register int i, bsize;
        !           131:        extern int dmmin, dmmax;
        !           132:        int maxbsize;
        !           133: 
        !           134: #ifdef DEBUG
        !           135:        if (swpagerdebug & (SDB_FOLLOW|SDB_INIT))
        !           136:                printf("swpg_init()\n");
        !           137: #endif
        !           138:        dfltpagerops = &swappagerops;
        !           139:        queue_init(&swap_pager_list);
        !           140: 
        !           141:        /*
        !           142:         * Initialize clean lists
        !           143:         */
        !           144:        queue_init(&swap_pager_inuse);
        !           145:        queue_init(&swap_pager_free);
        !           146:        for (i = 0, spc = swcleanlist; i < NPENDINGIO; i++, spc++) {
        !           147:                queue_enter(&swap_pager_free, spc, swp_clean_t, spc_list);
        !           148:                spc->spc_flags = SPC_FREE;
        !           149:        }
        !           150: 
        !           151:        /*
        !           152:         * Calculate the swap allocation constants.
        !           153:         */
        !           154:         if (dmmin == 0) {
        !           155:                 dmmin = DMMIN;
        !           156:                if (dmmin < CLBYTES/DEV_BSIZE)
        !           157:                        dmmin = CLBYTES/DEV_BSIZE;
        !           158:        }
        !           159:         if (dmmax == 0)
        !           160:                 dmmax = DMMAX;
        !           161: 
        !           162:        /*
        !           163:         * Fill in our table of object size vs. allocation size
        !           164:         */
        !           165:        bsize = btodb(PAGE_SIZE);
        !           166:        if (bsize < dmmin)
        !           167:                bsize = dmmin;
        !           168:        maxbsize = btodb(sizeof(sw_bm_t) * NBBY * PAGE_SIZE);
        !           169:        if (maxbsize > dmmax)
        !           170:                maxbsize = dmmax;
        !           171:        for (i = 0; i < NSWSIZES; i++) {
        !           172:                swtab[i].st_osize = (vm_size_t) (MAXDADDRS * dbtob(bsize));
        !           173:                swtab[i].st_bsize = bsize;
        !           174: #ifdef DEBUG
        !           175:                if (swpagerdebug & SDB_INIT)
        !           176:                        printf("swpg_init: ix %d, size %x, bsize %x\n",
        !           177:                               i, swtab[i].st_osize, swtab[i].st_bsize);
        !           178: #endif
        !           179:                if (bsize >= maxbsize)
        !           180:                        break;
        !           181:                bsize *= 2;
        !           182:        }
        !           183:        swtab[i].st_osize = 0;
        !           184:        swtab[i].st_bsize = bsize;
        !           185: }
        !           186: 
        !           187: /*
        !           188:  * Allocate a pager structure and associated resources.
        !           189:  * Note that if we are called from the pageout daemon (handle == NULL)
        !           190:  * we should not wait for memory as it could resulting in deadlock.
        !           191:  */
        !           192: vm_pager_t
        !           193: swap_pager_alloc(handle, size, prot)
        !           194:        caddr_t handle;
        !           195:        register vm_size_t size;
        !           196:        vm_prot_t prot;
        !           197: {
        !           198:        register vm_pager_t pager;
        !           199:        register sw_pager_t swp;
        !           200:        struct swtab *swt;
        !           201:        int waitok;
        !           202: 
        !           203: #ifdef DEBUG
        !           204:        if (swpagerdebug & (SDB_FOLLOW|SDB_ALLOC))
        !           205:                printf("swpg_alloc(%x, %x, %x)\n", handle, size, prot);
        !           206: #endif
        !           207:        /*
        !           208:         * If this is a "named" anonymous region, look it up and
        !           209:         * return the appropriate pager if it exists.
        !           210:         */
        !           211:        if (handle) {
        !           212:                pager = vm_pager_lookup(&swap_pager_list, handle);
        !           213:                if (pager != NULL) {
        !           214:                        /*
        !           215:                         * Use vm_object_lookup to gain a reference
        !           216:                         * to the object and also to remove from the
        !           217:                         * object cache.
        !           218:                         */
        !           219:                        if (vm_object_lookup(pager) == NULL)
        !           220:                                panic("swap_pager_alloc: bad object");
        !           221:                        return(pager);
        !           222:                }
        !           223:        }
        !           224:        /*
        !           225:         * Pager doesn't exist, allocate swap management resources
        !           226:         * and initialize.
        !           227:         */
        !           228:        waitok = handle ? M_WAITOK : M_NOWAIT;
        !           229:        pager = (vm_pager_t)malloc(sizeof *pager, M_VMPAGER, waitok);
        !           230:        if (pager == NULL)
        !           231:                return(NULL);
        !           232:        swp = (sw_pager_t)malloc(sizeof *swp, M_VMPGDATA, waitok);
        !           233:        if (swp == NULL) {
        !           234: #ifdef DEBUG
        !           235:                if (swpagerdebug & SDB_FAIL)
        !           236:                        printf("swpg_alloc: swpager malloc failed\n");
        !           237: #endif
        !           238:                free((caddr_t)pager, M_VMPAGER);
        !           239:                return(NULL);
        !           240:        }
        !           241:        size = round_page(size);
        !           242:        for (swt = swtab; swt->st_osize; swt++)
        !           243:                if (size <= swt->st_osize)
        !           244:                        break;
        !           245: #ifdef DEBUG
        !           246:        swt->st_inuse++;
        !           247:        swt->st_usecnt++;
        !           248: #endif
        !           249:        swp->sw_osize = size;
        !           250:        swp->sw_bsize = swt->st_bsize;
        !           251:        swp->sw_nblocks = (btodb(size) + swp->sw_bsize - 1) / swp->sw_bsize;
        !           252:        swp->sw_blocks = (sw_blk_t)
        !           253:                malloc(swp->sw_nblocks*sizeof(*swp->sw_blocks),
        !           254:                       M_VMPGDATA, M_NOWAIT);
        !           255:        if (swp->sw_blocks == NULL) {
        !           256:                free((caddr_t)swp, M_VMPGDATA);
        !           257:                free((caddr_t)pager, M_VMPAGER);
        !           258: #ifdef DEBUG
        !           259:                if (swpagerdebug & SDB_FAIL)
        !           260:                        printf("swpg_alloc: sw_blocks malloc failed\n");
        !           261:                swt->st_inuse--;
        !           262:                swt->st_usecnt--;
        !           263: #endif
        !           264:                return(FALSE);
        !           265:        }
        !           266:        bzero((caddr_t)swp->sw_blocks,
        !           267:              swp->sw_nblocks * sizeof(*swp->sw_blocks));
        !           268:        swp->sw_poip = 0;
        !           269:        if (handle) {
        !           270:                vm_object_t object;
        !           271: 
        !           272:                swp->sw_flags = SW_NAMED;
        !           273:                queue_enter(&swap_pager_list, pager, vm_pager_t, pg_list);
        !           274:                /*
        !           275:                 * Consistant with other pagers: return with object
        !           276:                 * referenced.  Can't do this with handle == NULL
        !           277:                 * since it might be the pageout daemon calling.
        !           278:                 */
        !           279:                object = vm_object_allocate(size);
        !           280:                vm_object_enter(object, pager);
        !           281:                vm_object_setpager(object, pager, 0, FALSE);
        !           282:        } else {
        !           283:                swp->sw_flags = 0;
        !           284:                queue_init(&pager->pg_list);
        !           285:        }
        !           286:        pager->pg_handle = handle;
        !           287:        pager->pg_ops = &swappagerops;
        !           288:        pager->pg_type = PG_SWAP;
        !           289:        pager->pg_data = (caddr_t)swp;
        !           290: 
        !           291: #ifdef DEBUG
        !           292:        if (swpagerdebug & SDB_ALLOC)
        !           293:                printf("swpg_alloc: pg_data %x, %x of %x at %x\n",
        !           294:                       swp, swp->sw_nblocks, swp->sw_bsize, swp->sw_blocks);
        !           295: #endif
        !           296:        return(pager);
        !           297: }
        !           298: 
        !           299: void
        !           300: swap_pager_dealloc(pager)
        !           301:        vm_pager_t pager;
        !           302: {
        !           303:        register int i;
        !           304:        register sw_blk_t bp;
        !           305:        register sw_pager_t swp;
        !           306:        struct swtab *swt;
        !           307:        int s;
        !           308: 
        !           309: #ifdef DEBUG
        !           310:        /* save panic time state */
        !           311:        if ((swpagerdebug & SDB_ANOMPANIC) && panicstr)
        !           312:                return;
        !           313:        if (swpagerdebug & (SDB_FOLLOW|SDB_ALLOC))
        !           314:                printf("swpg_dealloc(%x)\n", pager);
        !           315: #endif
        !           316:        /*
        !           317:         * Remove from list right away so lookups will fail if we
        !           318:         * block for pageout completion.
        !           319:         */
        !           320:        swp = (sw_pager_t) pager->pg_data;
        !           321:        if (swp->sw_flags & SW_NAMED) {
        !           322:                queue_remove(&swap_pager_list, pager, vm_pager_t, pg_list);
        !           323:                swp->sw_flags &= ~SW_NAMED;
        !           324:        }
        !           325: #ifdef DEBUG
        !           326:        for (swt = swtab; swt->st_osize; swt++)
        !           327:                if (swp->sw_osize <= swt->st_osize)
        !           328:                        break;
        !           329:        swt->st_inuse--;
        !           330: #endif
        !           331: 
        !           332:        /*
        !           333:         * Wait for all pageouts to finish and remove
        !           334:         * all entries from cleaning list.
        !           335:         */
        !           336:        s = splbio();
        !           337:        while (swp->sw_poip) {
        !           338:                swp->sw_flags |= SW_WANTED;
        !           339:                assert_wait((int)swp);
        !           340:                thread_block();
        !           341:        }
        !           342:        splx(s);
        !           343:        (void) swap_pager_clean(NULL, B_WRITE);
        !           344: 
        !           345:        /*
        !           346:         * Free left over swap blocks
        !           347:         */
        !           348:        for (i = 0, bp = swp->sw_blocks; i < swp->sw_nblocks; i++, bp++)
        !           349:                if (bp->swb_block) {
        !           350: #ifdef DEBUG
        !           351:                        if (swpagerdebug & (SDB_ALLOCBLK|SDB_FULL))
        !           352:                                printf("swpg_dealloc: blk %x\n",
        !           353:                                       bp->swb_block);
        !           354: #endif
        !           355:                        rmfree(swapmap, swp->sw_bsize, bp->swb_block);
        !           356:                }
        !           357:        /*
        !           358:         * Free swap management resources
        !           359:         */
        !           360:        free((caddr_t)swp->sw_blocks, M_VMPGDATA);
        !           361:        free((caddr_t)swp, M_VMPGDATA);
        !           362:        free((caddr_t)pager, M_VMPAGER);
        !           363: }
        !           364: 
        !           365: swap_pager_getpage(pager, m, sync)
        !           366:        vm_pager_t pager;
        !           367:        vm_page_t m;
        !           368:        boolean_t sync;
        !           369: {
        !           370: #ifdef DEBUG
        !           371:        if (swpagerdebug & SDB_FOLLOW)
        !           372:                printf("swpg_getpage(%x, %x, %d)\n", pager, m, sync);
        !           373: #endif
        !           374:        return(swap_pager_io((sw_pager_t)pager->pg_data, m, B_READ));
        !           375: }
        !           376: 
        !           377: swap_pager_putpage(pager, m, sync)
        !           378:        vm_pager_t pager;
        !           379:        vm_page_t m;
        !           380:        boolean_t sync;
        !           381: {
        !           382:        int flags;
        !           383: 
        !           384: #ifdef DEBUG
        !           385:        if (swpagerdebug & SDB_FOLLOW)
        !           386:                printf("swpg_putpage(%x, %x, %d)\n", pager, m, sync);
        !           387: #endif
        !           388:        if (pager == NULL) {
        !           389:                (void) swap_pager_clean(NULL, B_WRITE);
        !           390:                return;
        !           391:        }
        !           392:        flags = B_WRITE;
        !           393:        if (!sync)
        !           394:                flags |= B_ASYNC;
        !           395:        return(swap_pager_io((sw_pager_t)pager->pg_data, m, flags));
        !           396: }
        !           397: 
        !           398: boolean_t
        !           399: swap_pager_haspage(pager, offset)
        !           400:        vm_pager_t pager;
        !           401:        vm_offset_t offset;
        !           402: {
        !           403:        register sw_pager_t swp;
        !           404:        register sw_blk_t swb;
        !           405:        int ix;
        !           406: 
        !           407: #ifdef DEBUG
        !           408:        if (swpagerdebug & (SDB_FOLLOW|SDB_ALLOCBLK))
        !           409:                printf("swpg_haspage(%x, %x) ", pager, offset);
        !           410: #endif
        !           411:        swp = (sw_pager_t) pager->pg_data;
        !           412:        ix = offset / dbtob(swp->sw_bsize);
        !           413:        if (swp->sw_blocks == NULL || ix >= swp->sw_nblocks) {
        !           414: #ifdef DEBUG
        !           415:                if (swpagerdebug & (SDB_FAIL|SDB_FOLLOW|SDB_ALLOCBLK))
        !           416:                        printf("swpg_haspage: %x bad offset %x, ix %x\n",
        !           417:                               swp->sw_blocks, offset, ix);
        !           418: #endif
        !           419:                return(FALSE);
        !           420:        }
        !           421:        swb = &swp->sw_blocks[ix];
        !           422:        if (swb->swb_block)
        !           423:                ix = atop(offset % dbtob(swp->sw_bsize));
        !           424: #ifdef DEBUG
        !           425:        if (swpagerdebug & SDB_ALLOCBLK)
        !           426:                printf("%x blk %x+%x ", swp->sw_blocks, swb->swb_block, ix);
        !           427:        if (swpagerdebug & (SDB_FOLLOW|SDB_ALLOCBLK))
        !           428:                printf("-> %c\n",
        !           429:                       "FT"[swb->swb_block && (swb->swb_mask & (1 << ix))]);
        !           430: #endif
        !           431:        if (swb->swb_block && (swb->swb_mask & (1 << ix)))
        !           432:                return(TRUE);
        !           433:        return(FALSE);
        !           434: }
        !           435: 
        !           436: /*
        !           437:  * Scaled down version of swap().
        !           438:  * Assumes that PAGE_SIZE < MAXPHYS; i.e. only one operation needed.
        !           439:  * BOGUS:  lower level IO routines expect a KVA so we have to map our
        !           440:  * provided physical page into the KVA to keep them happy.
        !           441:  */
        !           442: swap_pager_io(swp, m, flags)
        !           443:        register sw_pager_t swp;
        !           444:        vm_page_t m;
        !           445:        int flags;
        !           446: {
        !           447:        register struct buf *bp;
        !           448:        register sw_blk_t swb;
        !           449:        register int s;
        !           450:        int ix;
        !           451:        boolean_t rv;
        !           452:        vm_offset_t kva, off;
        !           453:        swp_clean_t spc;
        !           454: 
        !           455: #ifdef DEBUG
        !           456:        /* save panic time state */
        !           457:        if ((swpagerdebug & SDB_ANOMPANIC) && panicstr)
        !           458:                return;
        !           459:        if (swpagerdebug & (SDB_FOLLOW|SDB_IO))
        !           460:                printf("swpg_io(%x, %x, %x)\n", swp, m, flags);
        !           461: #endif
        !           462: 
        !           463:        /*
        !           464:         * For reads (pageins) and synchronous writes, we clean up
        !           465:         * all completed async pageouts.
        !           466:         */
        !           467:        if ((flags & B_ASYNC) == 0) {
        !           468:                s = splbio();
        !           469: #ifdef DEBUG
        !           470:                /*
        !           471:                 * Check to see if this page is currently being cleaned.
        !           472:                 * If it is, we just wait til the operation is done before
        !           473:                 * continuing.
        !           474:                 */
        !           475:                while (swap_pager_clean(m, flags&B_READ)) {
        !           476:                        if (swpagerdebug & SDB_ANOM)
        !           477:                                printf("swap_pager_io: page %x cleaning\n", m);
        !           478: 
        !           479:                        swp->sw_flags |= SW_WANTED;
        !           480:                        assert_wait((int)swp);
        !           481:                        thread_block();
        !           482:                }
        !           483: #else
        !           484:                (void) swap_pager_clean(m, flags&B_READ);
        !           485: #endif
        !           486:                splx(s);
        !           487:        }
        !           488:        /*
        !           489:         * For async writes (pageouts), we cleanup completed pageouts so
        !           490:         * that all available resources are freed.  Also tells us if this
        !           491:         * page is already being cleaned.  If it is, or no resources
        !           492:         * are available, we try again later.
        !           493:         */
        !           494:        else if (swap_pager_clean(m, B_WRITE) ||
        !           495:                 queue_empty(&swap_pager_free)) {
        !           496: #ifdef DEBUG
        !           497:                if ((swpagerdebug & SDB_ANOM) &&
        !           498:                    !queue_empty(&swap_pager_free))
        !           499:                        printf("swap_pager_io: page %x already cleaning\n", m);
        !           500: #endif
        !           501:                return(VM_PAGER_FAIL);
        !           502:        }
        !           503: 
        !           504:        /*
        !           505:         * Determine swap block and allocate as necessary.
        !           506:         */
        !           507:        off = m->offset + m->object->paging_offset;
        !           508:        ix = off / dbtob(swp->sw_bsize);
        !           509:        if (swp->sw_blocks == NULL || ix >= swp->sw_nblocks) {
        !           510: #ifdef DEBUG
        !           511:                if (swpagerdebug & SDB_FAIL)
        !           512:                        printf("swpg_io: bad offset %x+%x(%d) in %x\n",
        !           513:                               m->offset, m->object->paging_offset,
        !           514:                               ix, swp->sw_blocks);
        !           515: #endif
        !           516:                return(VM_PAGER_FAIL);
        !           517:        }
        !           518:        swb = &swp->sw_blocks[ix];
        !           519:        off = off % dbtob(swp->sw_bsize);
        !           520:        if (flags & B_READ) {
        !           521:                if (swb->swb_block == 0 ||
        !           522:                    (swb->swb_mask & (1 << atop(off))) == 0) {
        !           523: #ifdef DEBUG
        !           524:                        if (swpagerdebug & (SDB_ALLOCBLK|SDB_FAIL))
        !           525:                                printf("swpg_io: %x bad read: blk %x+%x, mask %x, off %x+%x\n",
        !           526:                                       swp->sw_blocks,
        !           527:                                       swb->swb_block, atop(off),
        !           528:                                       swb->swb_mask,
        !           529:                                       m->offset, m->object->paging_offset);
        !           530: #endif
        !           531:                        /* XXX: should we zero page here?? */
        !           532:                        return(VM_PAGER_FAIL);
        !           533:                }
        !           534:        } else if (swb->swb_block == 0) {
        !           535:                swb->swb_block = rmalloc(swapmap, swp->sw_bsize);
        !           536:                if (swb->swb_block == 0) {
        !           537: #ifdef DEBUG
        !           538:                        if (swpagerdebug & SDB_FAIL)
        !           539:                                printf("swpg_io: rmalloc of %x failed\n",
        !           540:                                       swp->sw_bsize);
        !           541: #endif
        !           542:                        return(VM_PAGER_FAIL);
        !           543:                }
        !           544: #ifdef DEBUG
        !           545:                if (swpagerdebug & (SDB_FULL|SDB_ALLOCBLK))
        !           546:                        printf("swpg_io: %x alloc blk %x at ix %x\n",
        !           547:                               swp->sw_blocks, swb->swb_block, ix);
        !           548: #endif
        !           549:        }
        !           550: 
        !           551:        /*
        !           552:         * Allocate a kernel virtual address and initialize so that PTE
        !           553:         * is available for lower level IO drivers.
        !           554:         */
        !           555:        kva = vm_pager_map_page(m);
        !           556: 
        !           557:        /*
        !           558:         * Get a swap buffer header and perform the IO
        !           559:         */
        !           560:        s = splbio();
        !           561:        while (bswlist.av_forw == NULL) {
        !           562: #ifdef DEBUG
        !           563:                if (swpagerdebug & SDB_ANOM)
        !           564:                        printf("swap_pager_io: wait on swbuf for %x (%d)\n",
        !           565:                               m, flags);
        !           566: #endif
        !           567:                bswlist.b_flags |= B_WANTED;
        !           568:                sleep((caddr_t)&bswlist, PSWP+1);
        !           569:        }
        !           570:        bp = bswlist.av_forw;
        !           571:        bswlist.av_forw = bp->av_forw;
        !           572:        splx(s);
        !           573:        bp->b_flags = B_BUSY | (flags & B_READ);
        !           574:        bp->b_proc = &proc0;    /* XXX (but without B_PHYS set this is ok) */
        !           575:        bp->b_un.b_addr = (caddr_t)kva;
        !           576:        bp->b_blkno = swb->swb_block + btodb(off);
        !           577:        VHOLD(swapdev_vp);
        !           578:        bp->b_vp = swapdev_vp;
        !           579:        if (swapdev_vp->v_type == VBLK)
        !           580:                bp->b_dev = swapdev_vp->v_rdev;
        !           581:        bp->b_bcount = PAGE_SIZE;
        !           582:        if ((bp->b_flags & B_READ) == 0)
        !           583:                swapdev_vp->v_numoutput++;
        !           584: 
        !           585:        /*
        !           586:         * If this is an async write we set up additional buffer fields
        !           587:         * and place a "cleaning" entry on the inuse queue.
        !           588:         */
        !           589:        if ((flags & (B_READ|B_ASYNC)) == B_ASYNC) {
        !           590: #ifdef DEBUG
        !           591:                if (queue_empty(&swap_pager_free))
        !           592:                        panic("swpg_io: lost spc");
        !           593: #endif
        !           594:                queue_remove_first(&swap_pager_free,
        !           595:                                   spc, swp_clean_t, spc_list);
        !           596: #ifdef DEBUG
        !           597:                if (spc->spc_flags != SPC_FREE)
        !           598:                        panic("swpg_io: bad free spc");
        !           599: #endif
        !           600:                spc->spc_flags = SPC_BUSY;
        !           601:                spc->spc_bp = bp;
        !           602:                spc->spc_swp = swp;
        !           603:                spc->spc_kva = kva;
        !           604:                spc->spc_m = m;
        !           605:                bp->b_flags |= B_CALL;
        !           606:                bp->b_iodone = swap_pager_iodone;
        !           607:                s = splbio();
        !           608:                swp->sw_poip++;
        !           609:                queue_enter(&swap_pager_inuse, spc, swp_clean_t, spc_list);
        !           610: 
        !           611: #ifdef DEBUG
        !           612:                swap_pager_poip++;
        !           613:                if (swpagerdebug & SDB_WRITE)
        !           614:                        printf("swpg_io: write: bp=%x swp=%x spc=%x poip=%d\n",
        !           615:                               bp, swp, spc, swp->sw_poip);
        !           616:                if ((swpagerdebug & SDB_ALLOCBLK) &&
        !           617:                    (swb->swb_mask & (1 << atop(off))) == 0)
        !           618:                        printf("swpg_io: %x write blk %x+%x\n",
        !           619:                               swp->sw_blocks, swb->swb_block, atop(off));
        !           620: #endif
        !           621:                swb->swb_mask |= (1 << atop(off));
        !           622:                splx(s);
        !           623:        }
        !           624: #ifdef DEBUG
        !           625:        if (swpagerdebug & SDB_IO)
        !           626:                printf("swpg_io: IO start: bp %x, db %x, va %x, pa %x\n",
        !           627:                       bp, swb->swb_block+btodb(off), kva, VM_PAGE_TO_PHYS(m));
        !           628: #endif
        !           629:        VOP_STRATEGY(bp);
        !           630:        if ((flags & (B_READ|B_ASYNC)) == B_ASYNC) {
        !           631: #ifdef DEBUG
        !           632:                if (swpagerdebug & SDB_IO)
        !           633:                        printf("swpg_io:  IO started: bp %x\n", bp);
        !           634: #endif
        !           635:                return(VM_PAGER_PEND);
        !           636:        }
        !           637:        s = splbio();
        !           638: #ifdef DEBUG
        !           639:        if (flags & B_READ)
        !           640:                swap_pager_piip++;
        !           641:        else
        !           642:                swap_pager_poip++;
        !           643: #endif
        !           644:        while ((bp->b_flags & B_DONE) == 0) {
        !           645:                assert_wait((int)bp);
        !           646:                thread_block();
        !           647:        }
        !           648: #ifdef DEBUG
        !           649:        if (flags & B_READ)
        !           650:                --swap_pager_piip;
        !           651:        else
        !           652:                --swap_pager_poip;
        !           653: #endif
        !           654:        rv = (bp->b_flags & B_ERROR) ? VM_PAGER_FAIL : VM_PAGER_OK;
        !           655:        bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS|B_PAGET|B_UAREA|B_DIRTY);
        !           656:        bp->av_forw = bswlist.av_forw;
        !           657:        bswlist.av_forw = bp;
        !           658:        if (bp->b_vp)
        !           659:                brelvp(bp);
        !           660:        if (bswlist.b_flags & B_WANTED) {
        !           661:                bswlist.b_flags &= ~B_WANTED;
        !           662:                thread_wakeup((int)&bswlist);
        !           663:        }
        !           664:        if ((flags & B_READ) == 0 && rv == VM_PAGER_OK) {
        !           665:                m->clean = TRUE;
        !           666:                pmap_clear_modify(VM_PAGE_TO_PHYS(m));
        !           667:        }
        !           668:        splx(s);
        !           669: #ifdef DEBUG
        !           670:        if (swpagerdebug & SDB_IO)
        !           671:                printf("swpg_io:  IO done: bp %x, rv %d\n", bp, rv);
        !           672:        if ((swpagerdebug & SDB_FAIL) && rv == VM_PAGER_FAIL)
        !           673:                printf("swpg_io: IO error\n");
        !           674: #endif
        !           675:        vm_pager_unmap_page(kva);
        !           676:        return(rv);
        !           677: }
        !           678: 
        !           679: boolean_t
        !           680: swap_pager_clean(m, rw)
        !           681:        vm_page_t m;
        !           682:        int rw;
        !           683: {
        !           684:        register swp_clean_t spc, tspc;
        !           685:        register int s;
        !           686: 
        !           687: #ifdef DEBUG
        !           688:        /* save panic time state */
        !           689:        if ((swpagerdebug & SDB_ANOMPANIC) && panicstr)
        !           690:                return;
        !           691:        if (swpagerdebug & SDB_FOLLOW)
        !           692:                printf("swpg_clean(%x, %d)\n", m, rw);
        !           693: #endif
        !           694:        tspc = NULL;
        !           695:        for (;;) {
        !           696:                /*
        !           697:                 * Look up and removal from inuse list must be done
        !           698:                 * at splbio() to avoid conflicts with swap_pager_iodone.
        !           699:                 */
        !           700:                s = splbio();
        !           701:                spc = (swp_clean_t) queue_first(&swap_pager_inuse);
        !           702:                while (!queue_end(&swap_pager_inuse, (queue_entry_t)spc)) {
        !           703:                        if ((spc->spc_flags & SPC_DONE) &&
        !           704:                            swap_pager_finish(spc)) {
        !           705:                                queue_remove(&swap_pager_inuse, spc,
        !           706:                                             swp_clean_t, spc_list);
        !           707:                                break;
        !           708:                        }
        !           709:                        if (m && m == spc->spc_m) {
        !           710: #ifdef DEBUG
        !           711:                                if (swpagerdebug & SDB_ANOM)
        !           712:                                        printf("swap_pager_clean: page %x on list, flags %x\n",
        !           713:                                               m, spc->spc_flags);
        !           714: #endif
        !           715:                                tspc = spc;
        !           716:                        }
        !           717:                        spc = (swp_clean_t) queue_next(&spc->spc_list);
        !           718:                }
        !           719: 
        !           720:                /*
        !           721:                 * No operations done, thats all we can do for now.
        !           722:                 */
        !           723:                if (queue_end(&swap_pager_inuse, (queue_entry_t)spc))
        !           724:                        break;
        !           725:                splx(s);
        !           726: 
        !           727:                /*
        !           728:                 * The desired page was found to be busy earlier in
        !           729:                 * the scan but has since completed.
        !           730:                 */
        !           731:                if (tspc && tspc == spc) {
        !           732: #ifdef DEBUG
        !           733:                        if (swpagerdebug & SDB_ANOM)
        !           734:                                printf("swap_pager_clean: page %x done while looking\n",
        !           735:                                       m);
        !           736: #endif
        !           737:                        tspc = NULL;
        !           738:                }
        !           739:                spc->spc_flags = SPC_FREE;
        !           740:                vm_pager_unmap_page(spc->spc_kva);
        !           741:                queue_enter(&swap_pager_free, spc, swp_clean_t, spc_list);
        !           742: #ifdef DEBUG
        !           743:                if (swpagerdebug & SDB_WRITE)
        !           744:                        printf("swpg_clean: free spc %x\n", spc);
        !           745: #endif
        !           746:        }
        !           747: #ifdef DEBUG
        !           748:        /*
        !           749:         * If we found that the desired page is already being cleaned
        !           750:         * mark it so that swap_pager_iodone() will not set the clean
        !           751:         * flag before the pageout daemon has another chance to clean it.
        !           752:         */
        !           753:        if (tspc && rw == B_WRITE) {
        !           754:                if (swpagerdebug & SDB_ANOM)
        !           755:                        printf("swap_pager_clean: page %x on clean list\n",
        !           756:                               tspc);
        !           757:                tspc->spc_flags |= SPC_DIRTY;
        !           758:        }
        !           759: #endif
        !           760:        splx(s);
        !           761: 
        !           762: #ifdef DEBUG
        !           763:        if (swpagerdebug & SDB_WRITE)
        !           764:                printf("swpg_clean: return %d\n", tspc ? TRUE : FALSE);
        !           765:        if ((swpagerdebug & SDB_ANOM) && tspc)
        !           766:                printf("swpg_clean: %s of cleaning page %x\n",
        !           767:                       rw == B_READ ? "get" : "put", m);
        !           768: #endif
        !           769:        return(tspc ? TRUE : FALSE);
        !           770: }
        !           771: 
        !           772: swap_pager_finish(spc)
        !           773:        register swp_clean_t spc;
        !           774: {
        !           775:        vm_object_t object = spc->spc_m->object;
        !           776: 
        !           777:        /*
        !           778:         * Mark the paging operation as done.
        !           779:         * (XXX) If we cannot get the lock, leave it til later.
        !           780:         * (XXX) Also we are assuming that an async write is a
        !           781:         *       pageout operation that has incremented the counter.
        !           782:         */
        !           783:        if (!vm_object_lock_try(object))
        !           784:                return(0);
        !           785: 
        !           786:        if (--object->paging_in_progress == 0)
        !           787:                thread_wakeup((int) object);
        !           788: 
        !           789: #ifdef DEBUG
        !           790:        /*
        !           791:         * XXX: this isn't even close to the right thing to do,
        !           792:         * introduces a variety of race conditions.
        !           793:         *
        !           794:         * If dirty, vm_pageout() has attempted to clean the page
        !           795:         * again.  In this case we do not do anything as we will
        !           796:         * see the page again shortly.
        !           797:         */
        !           798:        if (spc->spc_flags & SPC_DIRTY) {
        !           799:                if (swpagerdebug & SDB_ANOM)
        !           800:                        printf("swap_pager_finish: page %x dirty again\n",
        !           801:                               spc->spc_m);
        !           802:                spc->spc_m->busy = FALSE;
        !           803:                PAGE_WAKEUP(spc->spc_m);
        !           804:                vm_object_unlock(object);
        !           805:                return(1);
        !           806:        }
        !           807: #endif
        !           808:        /*
        !           809:         * If no error mark as clean and inform the pmap system.
        !           810:         * If error, mark as dirty so we will try again.
        !           811:         * (XXX could get stuck doing this, should give up after awhile)
        !           812:         */
        !           813:        if (spc->spc_flags & SPC_ERROR) {
        !           814:                printf("swap_pager_finish: clean of page %x failed\n",
        !           815:                       VM_PAGE_TO_PHYS(spc->spc_m));
        !           816:                spc->spc_m->laundry = TRUE;
        !           817:        } else {
        !           818:                spc->spc_m->clean = TRUE;
        !           819:                pmap_clear_modify(VM_PAGE_TO_PHYS(spc->spc_m));
        !           820:        }
        !           821:        spc->spc_m->busy = FALSE;
        !           822:        PAGE_WAKEUP(spc->spc_m);
        !           823: 
        !           824:        vm_object_unlock(object);
        !           825:        return(1);
        !           826: }
        !           827: 
        !           828: swap_pager_iodone(bp)
        !           829:        register struct buf *bp;
        !           830: {
        !           831:        register swp_clean_t spc;
        !           832:        daddr_t blk;
        !           833:        int s;
        !           834: 
        !           835: #ifdef DEBUG
        !           836:        /* save panic time state */
        !           837:        if ((swpagerdebug & SDB_ANOMPANIC) && panicstr)
        !           838:                return;
        !           839:        if (swpagerdebug & SDB_FOLLOW)
        !           840:                printf("swpg_iodone(%x)\n", bp);
        !           841: #endif
        !           842:        s = splbio();
        !           843:        spc = (swp_clean_t) queue_first(&swap_pager_inuse);
        !           844:        while (!queue_end(&swap_pager_inuse, (queue_entry_t)spc)) {
        !           845:                if (spc->spc_bp == bp)
        !           846:                        break;
        !           847:                spc = (swp_clean_t) queue_next(&spc->spc_list);
        !           848:        }
        !           849: #ifdef DEBUG
        !           850:        if (queue_end(&swap_pager_inuse, (queue_entry_t)spc))
        !           851:                panic("swap_pager_iodone: bp not found");
        !           852: #endif
        !           853: 
        !           854:        spc->spc_flags &= ~SPC_BUSY;
        !           855:        spc->spc_flags |= SPC_DONE;
        !           856:        if (bp->b_flags & B_ERROR)
        !           857:                spc->spc_flags |= SPC_ERROR;
        !           858:        spc->spc_bp = NULL;
        !           859:        blk = bp->b_blkno;
        !           860: 
        !           861: #ifdef DEBUG
        !           862:        --swap_pager_poip;
        !           863:        if (swpagerdebug & SDB_WRITE)
        !           864:                printf("swpg_iodone: bp=%x swp=%x flags=%x spc=%x poip=%x\n",
        !           865:                       bp, spc->spc_swp, spc->spc_swp->sw_flags,
        !           866:                       spc, spc->spc_swp->sw_poip);
        !           867: #endif
        !           868: 
        !           869:        spc->spc_swp->sw_poip--;
        !           870:        if (spc->spc_swp->sw_flags & SW_WANTED) {
        !           871:                spc->spc_swp->sw_flags &= ~SW_WANTED;
        !           872:                thread_wakeup((int)spc->spc_swp);
        !           873:        }
        !           874:                
        !           875:        bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS|B_PAGET|B_UAREA|B_DIRTY);
        !           876:        bp->av_forw = bswlist.av_forw;
        !           877:        bswlist.av_forw = bp;
        !           878:        if (bp->b_vp)
        !           879:                brelvp(bp);
        !           880:        if (bswlist.b_flags & B_WANTED) {
        !           881:                bswlist.b_flags &= ~B_WANTED;
        !           882:                thread_wakeup((int)&bswlist);
        !           883:        }
        !           884:        thread_wakeup((int) &vm_pages_needed);
        !           885:        splx(s);
        !           886: }
        !           887: #endif

unix.superglobalmegacorp.com

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