BSD 4_4 release
[unix-history] / usr / src / sys / vm / swap_pager.c
index 6583c86..3f863e5 100644 (file)
@@ -1,15 +1,43 @@
 /*
  * Copyright (c) 1990 University of Utah.
 /*
  * Copyright (c) 1990 University of Utah.
- * Copyright (c) 1991 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * the Systems Programming Group of the University of Utah Computer
  * Science Department.
  *
  *
  * This code is derived from software contributed to Berkeley by
  * the Systems Programming Group of the University of Utah Computer
  * Science Department.
  *
- * %sccs.include.redist.c%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
  *
- *     @(#)swap_pager.c        7.2 (Berkeley) %G%
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah $Hdr: swap_pager.c 1.4 91/04/30$
+ *
+ *     @(#)swap_pager.c        8.1 (Berkeley) 6/11/93
  */
 
 /*
  */
 
 /*
  *     Deal with async writes in a better fashion
  */
 
  *     Deal with async writes in a better fashion
  */
 
-#include "swappager.h"
-#if NSWAPPAGER > 0
-
-#include "param.h"
-#include "user.h"
-#include "proc.h"
-#include "buf.h"
-#include "map.h"
-#include "systm.h"
-#include "specdev.h"
-#include "vnode.h"
-#include "malloc.h"
-#include "queue.h"
-
-#include "../vm/vm_param.h"
-#include "../vm/vm_pager.h"
-#include "../vm/vm_page.h"
-#include "../vm/vm_pageout.h"
-#include "../vm/swap_pager.h"
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/buf.h>
+#include <sys/map.h>
+#include <sys/vnode.h>
+#include <sys/malloc.h>
+
+#include <miscfs/specfs/specdev.h>
+
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pageout.h>
+#include <vm/swap_pager.h>
 
 #define NSWSIZES       16      /* size of swtab */
 #define NPENDINGIO     64      /* max # of pending cleans */
 
 #define NSWSIZES       16      /* size of swtab */
 #define NPENDINGIO     64      /* max # of pending cleans */
@@ -65,9 +88,8 @@ struct swpagerclean {
        vm_offset_t             spc_kva;
        vm_page_t               spc_m;
 } swcleanlist[NPENDINGIO];
        vm_offset_t             spc_kva;
        vm_page_t               spc_m;
 } swcleanlist[NPENDINGIO];
-typedef        struct swpagerclean     *swp_clean_t;
+typedef struct swpagerclean *swp_clean_t;
 
 
-#define SWP_CLEAN_NULL         ((swp_clean_t)0)
 
 /* spc_flags values */
 #define SPC_FREE       0x00
 
 /* spc_flags values */
 #define SPC_FREE       0x00
@@ -95,7 +117,29 @@ queue_head_t        swap_pager_inuse;       /* list of pending page cleans */
 queue_head_t   swap_pager_free;        /* list of free pager clean structs */
 queue_head_t   swap_pager_list;        /* list of "named" anon regions */
 
 queue_head_t   swap_pager_free;        /* list of free pager clean structs */
 queue_head_t   swap_pager_list;        /* list of "named" anon regions */
 
-void
+static int             swap_pager_finish __P((swp_clean_t));
+static void            swap_pager_init __P((void));
+static vm_pager_t      swap_pager_alloc __P((caddr_t, vm_size_t, vm_prot_t));
+static boolean_t       swap_pager_clean __P((vm_page_t, int));
+static void            swap_pager_dealloc __P((vm_pager_t));
+static int             swap_pager_getpage
+                           __P((vm_pager_t, vm_page_t, boolean_t));
+static boolean_t       swap_pager_haspage __P((vm_pager_t, vm_offset_t));
+static int             swap_pager_io __P((sw_pager_t, vm_page_t, int));
+static void            swap_pager_iodone __P((struct buf *));
+static int             swap_pager_putpage
+                           __P((vm_pager_t, vm_page_t, boolean_t));
+
+struct pagerops swappagerops = {
+       swap_pager_init,
+       swap_pager_alloc,
+       swap_pager_dealloc,
+       swap_pager_getpage,
+       swap_pager_putpage,
+       swap_pager_haspage
+};
+
+static void
 swap_pager_init()
 {
        register swp_clean_t spc;
 swap_pager_init()
 {
        register swp_clean_t spc;
@@ -161,7 +205,7 @@ swap_pager_init()
  * Note that if we are called from the pageout daemon (handle == NULL)
  * we should not wait for memory as it could resulting in deadlock.
  */
  * Note that if we are called from the pageout daemon (handle == NULL)
  * we should not wait for memory as it could resulting in deadlock.
  */
-vm_pager_t
+static vm_pager_t
 swap_pager_alloc(handle, size, prot)
        caddr_t handle;
        register vm_size_t size;
 swap_pager_alloc(handle, size, prot)
        caddr_t handle;
        register vm_size_t size;
@@ -182,13 +226,13 @@ swap_pager_alloc(handle, size, prot)
         */
        if (handle) {
                pager = vm_pager_lookup(&swap_pager_list, handle);
         */
        if (handle) {
                pager = vm_pager_lookup(&swap_pager_list, handle);
-               if (pager != VM_PAGER_NULL) {
+               if (pager != NULL) {
                        /*
                         * Use vm_object_lookup to gain a reference
                         * to the object and also to remove from the
                         * object cache.
                         */
                        /*
                         * Use vm_object_lookup to gain a reference
                         * to the object and also to remove from the
                         * object cache.
                         */
-                       if (vm_object_lookup(pager) == VM_OBJECT_NULL)
+                       if (vm_object_lookup(pager) == NULL)
                                panic("swap_pager_alloc: bad object");
                        return(pager);
                }
                                panic("swap_pager_alloc: bad object");
                        return(pager);
                }
@@ -199,8 +243,8 @@ swap_pager_alloc(handle, size, prot)
         */
        waitok = handle ? M_WAITOK : M_NOWAIT;
        pager = (vm_pager_t)malloc(sizeof *pager, M_VMPAGER, waitok);
         */
        waitok = handle ? M_WAITOK : M_NOWAIT;
        pager = (vm_pager_t)malloc(sizeof *pager, M_VMPAGER, waitok);
-       if (pager == VM_PAGER_NULL)
-               return(VM_PAGER_NULL);
+       if (pager == NULL)
+               return(NULL);
        swp = (sw_pager_t)malloc(sizeof *swp, M_VMPGDATA, waitok);
        if (swp == NULL) {
 #ifdef DEBUG
        swp = (sw_pager_t)malloc(sizeof *swp, M_VMPGDATA, waitok);
        if (swp == NULL) {
 #ifdef DEBUG
@@ -208,7 +252,7 @@ swap_pager_alloc(handle, size, prot)
                        printf("swpg_alloc: swpager malloc failed\n");
 #endif
                free((caddr_t)pager, M_VMPAGER);
                        printf("swpg_alloc: swpager malloc failed\n");
 #endif
                free((caddr_t)pager, M_VMPAGER);
-               return(VM_PAGER_NULL);
+               return(NULL);
        }
        size = round_page(size);
        for (swt = swtab; swt->st_osize; swt++)
        }
        size = round_page(size);
        for (swt = swtab; swt->st_osize; swt++)
@@ -268,7 +312,7 @@ swap_pager_alloc(handle, size, prot)
        return(pager);
 }
 
        return(pager);
 }
 
-void
+static void
 swap_pager_dealloc(pager)
        vm_pager_t pager;
 {
 swap_pager_dealloc(pager)
        vm_pager_t pager;
 {
@@ -308,11 +352,11 @@ swap_pager_dealloc(pager)
        s = splbio();
        while (swp->sw_poip) {
                swp->sw_flags |= SW_WANTED;
        s = splbio();
        while (swp->sw_poip) {
                swp->sw_flags |= SW_WANTED;
-               assert_wait((int)swp);
+               assert_wait((int)swp, 0);
                thread_block();
        }
        splx(s);
                thread_block();
        }
        splx(s);
-       (void) swap_pager_clean(VM_PAGE_NULL, B_WRITE);
+       (void) swap_pager_clean(NULL, B_WRITE);
 
        /*
         * Free left over swap blocks
 
        /*
         * Free left over swap blocks
@@ -334,6 +378,7 @@ swap_pager_dealloc(pager)
        free((caddr_t)pager, M_VMPAGER);
 }
 
        free((caddr_t)pager, M_VMPAGER);
 }
 
+static int
 swap_pager_getpage(pager, m, sync)
        vm_pager_t pager;
        vm_page_t m;
 swap_pager_getpage(pager, m, sync)
        vm_pager_t pager;
        vm_page_t m;
@@ -346,6 +391,7 @@ swap_pager_getpage(pager, m, sync)
        return(swap_pager_io((sw_pager_t)pager->pg_data, m, B_READ));
 }
 
        return(swap_pager_io((sw_pager_t)pager->pg_data, m, B_READ));
 }
 
+static int
 swap_pager_putpage(pager, m, sync)
        vm_pager_t pager;
        vm_page_t m;
 swap_pager_putpage(pager, m, sync)
        vm_pager_t pager;
        vm_page_t m;
@@ -357,9 +403,9 @@ swap_pager_putpage(pager, m, sync)
        if (swpagerdebug & SDB_FOLLOW)
                printf("swpg_putpage(%x, %x, %d)\n", pager, m, sync);
 #endif
        if (swpagerdebug & SDB_FOLLOW)
                printf("swpg_putpage(%x, %x, %d)\n", pager, m, sync);
 #endif
-       if (pager == VM_PAGER_NULL) {
-               (void) swap_pager_clean(VM_PAGE_NULL, B_WRITE);
-               return;
+       if (pager == NULL) {
+               (void) swap_pager_clean(NULL, B_WRITE);
+               return (VM_PAGER_OK);           /* ??? */
        }
        flags = B_WRITE;
        if (!sync)
        }
        flags = B_WRITE;
        if (!sync)
@@ -367,7 +413,7 @@ swap_pager_putpage(pager, m, sync)
        return(swap_pager_io((sw_pager_t)pager->pg_data, m, flags));
 }
 
        return(swap_pager_io((sw_pager_t)pager->pg_data, m, flags));
 }
 
-boolean_t
+static boolean_t
 swap_pager_haspage(pager, offset)
        vm_pager_t pager;
        vm_offset_t offset;
 swap_pager_haspage(pager, offset)
        vm_pager_t pager;
        vm_offset_t offset;
@@ -411,6 +457,7 @@ swap_pager_haspage(pager, offset)
  * BOGUS:  lower level IO routines expect a KVA so we have to map our
  * provided physical page into the KVA to keep them happy.
  */
  * BOGUS:  lower level IO routines expect a KVA so we have to map our
  * provided physical page into the KVA to keep them happy.
  */
+static int
 swap_pager_io(swp, m, flags)
        register sw_pager_t swp;
        vm_page_t m;
 swap_pager_io(swp, m, flags)
        register sw_pager_t swp;
        vm_page_t m;
@@ -427,24 +474,34 @@ swap_pager_io(swp, m, flags)
 #ifdef DEBUG
        /* save panic time state */
        if ((swpagerdebug & SDB_ANOMPANIC) && panicstr)
 #ifdef DEBUG
        /* save panic time state */
        if ((swpagerdebug & SDB_ANOMPANIC) && panicstr)
-               return;
+               return (VM_PAGER_FAIL);         /* XXX: correct return? */
        if (swpagerdebug & (SDB_FOLLOW|SDB_IO))
                printf("swpg_io(%x, %x, %x)\n", swp, m, flags);
 #endif
 
        /*
         * For reads (pageins) and synchronous writes, we clean up
        if (swpagerdebug & (SDB_FOLLOW|SDB_IO))
                printf("swpg_io(%x, %x, %x)\n", swp, m, flags);
 #endif
 
        /*
         * For reads (pageins) and synchronous writes, we clean up
-        * all completed async pageouts and check to see if this
-        * page is currently being cleaned.  If it is, we just wait
-        * til the operation is done before continuing.
+        * all completed async pageouts.
         */
        if ((flags & B_ASYNC) == 0) {
                s = splbio();
         */
        if ((flags & B_ASYNC) == 0) {
                s = splbio();
+#ifdef DEBUG
+               /*
+                * Check to see if this page is currently being cleaned.
+                * If it is, we just wait til the operation is done before
+                * continuing.
+                */
                while (swap_pager_clean(m, flags&B_READ)) {
                while (swap_pager_clean(m, flags&B_READ)) {
+                       if (swpagerdebug & SDB_ANOM)
+                               printf("swap_pager_io: page %x cleaning\n", m);
+
                        swp->sw_flags |= SW_WANTED;
                        swp->sw_flags |= SW_WANTED;
-                       assert_wait((int)swp);
+                       assert_wait((int)swp, 0);
                        thread_block();
                }
                        thread_block();
                }
+#else
+               (void) swap_pager_clean(m, flags&B_READ);
+#endif
                splx(s);
        }
        /*
                splx(s);
        }
        /*
@@ -453,8 +510,15 @@ swap_pager_io(swp, m, flags)
         * page is already being cleaned.  If it is, or no resources
         * are available, we try again later.
         */
         * page is already being cleaned.  If it is, or no resources
         * are available, we try again later.
         */
-       else if (swap_pager_clean(m, B_WRITE) || queue_empty(&swap_pager_free))
+       else if (swap_pager_clean(m, B_WRITE) ||
+                queue_empty(&swap_pager_free)) {
+#ifdef DEBUG
+               if ((swpagerdebug & SDB_ANOM) &&
+                   !queue_empty(&swap_pager_free))
+                       printf("swap_pager_io: page %x already cleaning\n", m);
+#endif
                return(VM_PAGER_FAIL);
                return(VM_PAGER_FAIL);
+       }
 
        /*
         * Determine swap block and allocate as necessary.
 
        /*
         * Determine swap block and allocate as necessary.
@@ -513,20 +577,20 @@ swap_pager_io(swp, m, flags)
         * Get a swap buffer header and perform the IO
         */
        s = splbio();
         * Get a swap buffer header and perform the IO
         */
        s = splbio();
-       while (bswlist.av_forw == NULL) {
+       while (bswlist.b_actf == NULL) {
 #ifdef DEBUG
                if (swpagerdebug & SDB_ANOM)
 #ifdef DEBUG
                if (swpagerdebug & SDB_ANOM)
-                       printf("swpg_io: wait on swbuf for %x (%d)\n",
+                       printf("swap_pager_io: wait on swbuf for %x (%d)\n",
                               m, flags);
 #endif
                bswlist.b_flags |= B_WANTED;
                sleep((caddr_t)&bswlist, PSWP+1);
        }
                               m, flags);
 #endif
                bswlist.b_flags |= B_WANTED;
                sleep((caddr_t)&bswlist, PSWP+1);
        }
-       bp = bswlist.av_forw;
-       bswlist.av_forw = bp->av_forw;
+       bp = bswlist.b_actf;
+       bswlist.b_actf = bp->b_actf;
        splx(s);
        bp->b_flags = B_BUSY | (flags & B_READ);
        splx(s);
        bp->b_flags = B_BUSY | (flags & B_READ);
-       bp->b_proc = &proc[0];  /* XXX (but without B_PHYS set this is ok) */
+       bp->b_proc = &proc0;    /* XXX (but without B_PHYS set this is ok) */
        bp->b_un.b_addr = (caddr_t)kva;
        bp->b_blkno = swb->swb_block + btodb(off);
        VHOLD(swapdev_vp);
        bp->b_un.b_addr = (caddr_t)kva;
        bp->b_blkno = swb->swb_block + btodb(off);
        VHOLD(swapdev_vp);
@@ -534,8 +598,11 @@ swap_pager_io(swp, m, flags)
        if (swapdev_vp->v_type == VBLK)
                bp->b_dev = swapdev_vp->v_rdev;
        bp->b_bcount = PAGE_SIZE;
        if (swapdev_vp->v_type == VBLK)
                bp->b_dev = swapdev_vp->v_rdev;
        bp->b_bcount = PAGE_SIZE;
-       if ((bp->b_flags & B_READ) == 0)
+       if ((bp->b_flags & B_READ) == 0) {
+               bp->b_dirtyoff = 0;
+               bp->b_dirtyend = PAGE_SIZE;
                swapdev_vp->v_numoutput++;
                swapdev_vp->v_numoutput++;
+       }
 
        /*
         * If this is an async write we set up additional buffer fields
 
        /*
         * If this is an async write we set up additional buffer fields
@@ -557,9 +624,6 @@ swap_pager_io(swp, m, flags)
                spc->spc_swp = swp;
                spc->spc_kva = kva;
                spc->spc_m = m;
                spc->spc_swp = swp;
                spc->spc_kva = kva;
                spc->spc_m = m;
-#ifdef DEBUG
-               m->pagerowned = 1;
-#endif
                bp->b_flags |= B_CALL;
                bp->b_iodone = swap_pager_iodone;
                s = splbio();
                bp->b_flags |= B_CALL;
                bp->b_iodone = swap_pager_iodone;
                s = splbio();
@@ -577,12 +641,6 @@ swap_pager_io(swp, m, flags)
                               swp->sw_blocks, swb->swb_block, atop(off));
 #endif
                swb->swb_mask |= (1 << atop(off));
                               swp->sw_blocks, swb->swb_block, atop(off));
 #endif
                swb->swb_mask |= (1 << atop(off));
-               /*
-                * XXX: Block write faults til we are done.
-                */
-               m->page_lock = VM_PROT_WRITE;
-               m->unlock_request = VM_PROT_ALL;
-               pmap_copy_on_write(VM_PAGE_TO_PHYS(m));
                splx(s);
        }
 #ifdef DEBUG
                splx(s);
        }
 #ifdef DEBUG
@@ -606,7 +664,7 @@ swap_pager_io(swp, m, flags)
                swap_pager_poip++;
 #endif
        while ((bp->b_flags & B_DONE) == 0) {
                swap_pager_poip++;
 #endif
        while ((bp->b_flags & B_DONE) == 0) {
-               assert_wait((int)bp);
+               assert_wait((int)bp, 0);
                thread_block();
        }
 #ifdef DEBUG
                thread_block();
        }
 #ifdef DEBUG
@@ -615,10 +673,10 @@ swap_pager_io(swp, m, flags)
        else
                --swap_pager_poip;
 #endif
        else
                --swap_pager_poip;
 #endif
-       rv = (bp->b_flags & B_ERROR) ? VM_PAGER_FAIL : VM_PAGER_OK;
+       rv = (bp->b_flags & B_ERROR) ? VM_PAGER_ERROR : VM_PAGER_OK;
        bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS|B_PAGET|B_UAREA|B_DIRTY);
        bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS|B_PAGET|B_UAREA|B_DIRTY);
-       bp->av_forw = bswlist.av_forw;
-       bswlist.av_forw = bp;
+       bp->b_actf = bswlist.b_actf;
+       bswlist.b_actf = bp;
        if (bp->b_vp)
                brelvp(bp);
        if (bswlist.b_flags & B_WANTED) {
        if (bp->b_vp)
                brelvp(bp);
        if (bswlist.b_flags & B_WANTED) {
@@ -626,21 +684,21 @@ swap_pager_io(swp, m, flags)
                thread_wakeup((int)&bswlist);
        }
        if ((flags & B_READ) == 0 && rv == VM_PAGER_OK) {
                thread_wakeup((int)&bswlist);
        }
        if ((flags & B_READ) == 0 && rv == VM_PAGER_OK) {
-               m->clean = 1;
+               m->flags |= PG_CLEAN;
                pmap_clear_modify(VM_PAGE_TO_PHYS(m));
        }
        splx(s);
 #ifdef DEBUG
        if (swpagerdebug & SDB_IO)
                printf("swpg_io:  IO done: bp %x, rv %d\n", bp, rv);
                pmap_clear_modify(VM_PAGE_TO_PHYS(m));
        }
        splx(s);
 #ifdef DEBUG
        if (swpagerdebug & SDB_IO)
                printf("swpg_io:  IO done: bp %x, rv %d\n", bp, rv);
-       if ((swpagerdebug & SDB_FAIL) && rv == VM_PAGER_FAIL)
+       if ((swpagerdebug & SDB_FAIL) && rv == VM_PAGER_ERROR)
                printf("swpg_io: IO error\n");
 #endif
        vm_pager_unmap_page(kva);
        return(rv);
 }
 
                printf("swpg_io: IO error\n");
 #endif
        vm_pager_unmap_page(kva);
        return(rv);
 }
 
-boolean_t
+static boolean_t
 swap_pager_clean(m, rw)
        vm_page_t m;
        int rw;
 swap_pager_clean(m, rw)
        vm_page_t m;
        int rw;
@@ -651,11 +709,11 @@ swap_pager_clean(m, rw)
 #ifdef DEBUG
        /* save panic time state */
        if ((swpagerdebug & SDB_ANOMPANIC) && panicstr)
 #ifdef DEBUG
        /* save panic time state */
        if ((swpagerdebug & SDB_ANOMPANIC) && panicstr)
-               return;
+               return (FALSE);                 /* ??? */
        if (swpagerdebug & SDB_FOLLOW)
                printf("swpg_clean(%x, %d)\n", m, rw);
 #endif
        if (swpagerdebug & SDB_FOLLOW)
                printf("swpg_clean(%x, %d)\n", m, rw);
 #endif
-       tspc = SWP_CLEAN_NULL;
+       tspc = NULL;
        for (;;) {
                /*
                 * Look up and removal from inuse list must be done
        for (;;) {
                /*
                 * Look up and removal from inuse list must be done
@@ -673,7 +731,7 @@ swap_pager_clean(m, rw)
                        if (m && m == spc->spc_m) {
 #ifdef DEBUG
                                if (swpagerdebug & SDB_ANOM)
                        if (m && m == spc->spc_m) {
 #ifdef DEBUG
                                if (swpagerdebug & SDB_ANOM)
-                                       printf("swpg_clean: %x on list, flags %x\n",
+                                       printf("swap_pager_clean: page %x on list, flags %x\n",
                                               m, spc->spc_flags);
 #endif
                                tspc = spc;
                                               m, spc->spc_flags);
 #endif
                                tspc = spc;
@@ -695,10 +753,10 @@ swap_pager_clean(m, rw)
                if (tspc && tspc == spc) {
 #ifdef DEBUG
                        if (swpagerdebug & SDB_ANOM)
                if (tspc && tspc == spc) {
 #ifdef DEBUG
                        if (swpagerdebug & SDB_ANOM)
-                               printf("swpg_clean: %x done while looking\n",
+                               printf("swap_pager_clean: page %x done while looking\n",
                                       m);
 #endif
                                       m);
 #endif
-                       tspc = SWP_CLEAN_NULL;
+                       tspc = NULL;
                }
                spc->spc_flags = SPC_FREE;
                vm_pager_unmap_page(spc->spc_kva);
                }
                spc->spc_flags = SPC_FREE;
                vm_pager_unmap_page(spc->spc_kva);
@@ -708,18 +766,19 @@ swap_pager_clean(m, rw)
                        printf("swpg_clean: free spc %x\n", spc);
 #endif
        }
                        printf("swpg_clean: free spc %x\n", spc);
 #endif
        }
+#ifdef DEBUG
        /*
         * If we found that the desired page is already being cleaned
         * mark it so that swap_pager_iodone() will not set the clean
         * flag before the pageout daemon has another chance to clean it.
         */
        if (tspc && rw == B_WRITE) {
        /*
         * If we found that the desired page is already being cleaned
         * mark it so that swap_pager_iodone() will not set the clean
         * flag before the pageout daemon has another chance to clean it.
         */
        if (tspc && rw == B_WRITE) {
-#ifdef DEBUG
                if (swpagerdebug & SDB_ANOM)
                if (swpagerdebug & SDB_ANOM)
-                       printf("swpg_clean: %x on clean list\n", tspc);
-#endif
+                       printf("swap_pager_clean: page %x on clean list\n",
+                              tspc);
                tspc->spc_flags |= SPC_DIRTY;
        }
                tspc->spc_flags |= SPC_DIRTY;
        }
+#endif
        splx(s);
 
 #ifdef DEBUG
        splx(s);
 
 #ifdef DEBUG
@@ -732,6 +791,7 @@ swap_pager_clean(m, rw)
        return(tspc ? TRUE : FALSE);
 }
 
        return(tspc ? TRUE : FALSE);
 }
 
+static int
 swap_pager_finish(spc)
        register swp_clean_t spc;
 {
 swap_pager_finish(spc)
        register swp_clean_t spc;
 {
@@ -746,44 +806,49 @@ swap_pager_finish(spc)
        if (!vm_object_lock_try(object))
                return(0);
 
        if (!vm_object_lock_try(object))
                return(0);
 
-#ifdef DEBUG
-       spc->spc_m->pagerowned = 0;
-#endif
-
        if (--object->paging_in_progress == 0)
                thread_wakeup((int) object);
 
        if (--object->paging_in_progress == 0)
                thread_wakeup((int) object);
 
+#ifdef DEBUG
        /*
         * XXX: this isn't even close to the right thing to do,
         * introduces a variety of race conditions.
         *
         * If dirty, vm_pageout() has attempted to clean the page
         * again.  In this case we do not do anything as we will
        /*
         * XXX: this isn't even close to the right thing to do,
         * introduces a variety of race conditions.
         *
         * If dirty, vm_pageout() has attempted to clean the page
         * again.  In this case we do not do anything as we will
-        * see the page again shortly.  Otherwise, if no error mark
-        * as clean and inform the pmap system.  If error, mark as
-        * dirty so we will try again (XXX: could get stuck doing
-        * this, should give up after awhile).
+        * see the page again shortly.
         */
         */
-       if ((spc->spc_flags & SPC_DIRTY) == 0) {
-               if (spc->spc_flags & SPC_ERROR) {
-                       printf("swap_pager: clean of %x failed\n",
-                              VM_PAGE_TO_PHYS(spc->spc_m));
-                       spc->spc_m->laundry = TRUE;
-               } else {
-                       spc->spc_m->clean = TRUE;
-                       pmap_clear_modify(VM_PAGE_TO_PHYS(spc->spc_m));
-               }
+       if (spc->spc_flags & SPC_DIRTY) {
+               if (swpagerdebug & SDB_ANOM)
+                       printf("swap_pager_finish: page %x dirty again\n",
+                              spc->spc_m);
+               spc->spc_m->flags &= ~PG_BUSY;
+               PAGE_WAKEUP(spc->spc_m);
+               vm_object_unlock(object);
+               return(1);
        }
        }
+#endif
        /*
        /*
-        * XXX: allow blocked write faults to continue
+        * If no error mark as clean and inform the pmap system.
+        * If error, mark as dirty so we will try again.
+        * (XXX could get stuck doing this, should give up after awhile)
         */
         */
-       spc->spc_m->page_lock = spc->spc_m->unlock_request = VM_PROT_NONE;
+       if (spc->spc_flags & SPC_ERROR) {
+               printf("swap_pager_finish: clean of page %x failed\n",
+                      VM_PAGE_TO_PHYS(spc->spc_m));
+               spc->spc_m->flags |= PG_LAUNDRY;
+       } else {
+               spc->spc_m->flags |= PG_CLEAN;
+               pmap_clear_modify(VM_PAGE_TO_PHYS(spc->spc_m));
+       }
+       spc->spc_m->flags &= ~PG_BUSY;
        PAGE_WAKEUP(spc->spc_m);
 
        vm_object_unlock(object);
        return(1);
 }
 
        PAGE_WAKEUP(spc->spc_m);
 
        vm_object_unlock(object);
        return(1);
 }
 
+static void
 swap_pager_iodone(bp)
        register struct buf *bp;
 {
 swap_pager_iodone(bp)
        register struct buf *bp;
 {
@@ -807,7 +872,7 @@ swap_pager_iodone(bp)
        }
 #ifdef DEBUG
        if (queue_end(&swap_pager_inuse, (queue_entry_t)spc))
        }
 #ifdef DEBUG
        if (queue_end(&swap_pager_inuse, (queue_entry_t)spc))
-               panic("swpg_iodone: bp not found");
+               panic("swap_pager_iodone: bp not found");
 #endif
 
        spc->spc_flags &= ~SPC_BUSY;
 #endif
 
        spc->spc_flags &= ~SPC_BUSY;
@@ -832,44 +897,19 @@ swap_pager_iodone(bp)
        }
                
        bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS|B_PAGET|B_UAREA|B_DIRTY);
        }
                
        bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS|B_PAGET|B_UAREA|B_DIRTY);
-       bp->av_forw = bswlist.av_forw;
-       bswlist.av_forw = bp;
+       bp->b_actf = bswlist.b_actf;
+       bswlist.b_actf = bp;
        if (bp->b_vp)
                brelvp(bp);
        if (bswlist.b_flags & B_WANTED) {
                bswlist.b_flags &= ~B_WANTED;
                thread_wakeup((int)&bswlist);
        }
        if (bp->b_vp)
                brelvp(bp);
        if (bswlist.b_flags & B_WANTED) {
                bswlist.b_flags &= ~B_WANTED;
                thread_wakeup((int)&bswlist);
        }
-#if 0
        /*
        /*
-        * XXX: this isn't even close to the right thing to do,
-        * introduces a variety of race conditions.
-        *
-        * If dirty, vm_pageout() has attempted to clean the page
-        * again.  In this case we do not do anything as we will
-        * see the page again shortly.  Otherwise, if no error mark
-        * as clean and inform the pmap system.  If error, mark as
-        * dirty so we will try again (XXX: could get stuck doing
-        * this, should give up after awhile).
+        * Only kick the pageout daemon if we are really hurting
+        * for pages, otherwise this page will be picked up later.
         */
         */
-       if ((spc->spc_flags & SPC_DIRTY) == 0) {
-               if (spc->spc_flags & SPC_ERROR) {
-                       printf("swap_pager: clean of %x (block %x) failed\n",
-                              VM_PAGE_TO_PHYS(spc->spc_m), blk);
-                       spc->spc_m->laundry = TRUE;
-               } else {
-                       spc->spc_m->clean = TRUE;
-                       pmap_clear_modify(VM_PAGE_TO_PHYS(spc->spc_m));
-               }
-       }
-       /*
-        * XXX: allow blocked write faults to continue
-        */
-       spc->spc_m->page_lock = spc->spc_m->unlock_request = VM_PROT_NONE;
-       PAGE_WAKEUP(spc->spc_m);
-#endif
-
-       thread_wakeup((int) &vm_pages_needed);
+       if (cnt.v_free_count < cnt.v_free_min)
+               thread_wakeup((int) &vm_pages_needed);
        splx(s);
 }
        splx(s);
 }
-#endif