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

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

unix.superglobalmegacorp.com

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