Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/uvm add support for ``swapctl -d'' (removing swap space).



details:   https://anonhg.NetBSD.org/src/rev/5e442c0df940
branches:  trunk
changeset: 480398:5e442c0df940
user:      chs <chs%NetBSD.org@localhost>
date:      Tue Jan 11 06:57:49 2000 +0000

description:
add support for ``swapctl -d'' (removing swap space).
improve handling of i/o errors in swap space.

reviewed by:  Chuck Cranor

diffstat:

 sys/uvm/uvm_anon.c    |  237 +++++++++++++++++++++++++++---
 sys/uvm/uvm_anon.h    |    5 +-
 sys/uvm/uvm_aobj.c    |  369 ++++++++++++++++++++++++++++++++++++++++++------
 sys/uvm/uvm_aobj.h    |    4 +-
 sys/uvm/uvm_extern.h  |    4 +-
 sys/uvm/uvm_fault.c   |   47 ++++-
 sys/uvm/uvm_fault_i.h |   19 ++-
 sys/uvm/uvm_km.c      |    3 +-
 sys/uvm/uvm_pager.c   |  123 ++++++++-------
 sys/uvm/uvm_pager.h   |    4 +-
 sys/uvm/uvm_stat.c    |    7 +-
 sys/uvm/uvm_swap.c    |  377 ++++++++++++++++++++++---------------------------
 sys/uvm/uvm_swap.h    |   12 +-
 13 files changed, 838 insertions(+), 373 deletions(-)

diffs (truncated from 2224 to 300 lines):

diff -r df0e67adb6c2 -r 5e442c0df940 sys/uvm/uvm_anon.c
--- a/sys/uvm/uvm_anon.c        Tue Jan 11 05:48:27 2000 +0000
+++ b/sys/uvm/uvm_anon.c        Tue Jan 11 06:57:49 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvm_anon.c,v 1.4 1999/09/12 01:17:34 chs Exp $ */
+/*     $NetBSD: uvm_anon.c,v 1.5 2000/01/11 06:57:49 chs Exp $ */
 
 /*
  *
@@ -43,6 +43,7 @@
 #include <sys/proc.h>
 #include <sys/malloc.h>
 #include <sys/pool.h>
+#include <sys/kernel.h>
 
 #include <vm/vm.h>
 #include <vm/vm_page.h>
@@ -52,61 +53,80 @@
 #include <uvm/uvm_swap.h>
 
 /*
+ * anonblock_list: global list of anon blocks,
+ * locked by swap_syscall_lock (since we never remove
+ * anything from this list and we only add to it via swapctl(2)).
+ */
+
+struct uvm_anonblock {
+       LIST_ENTRY(uvm_anonblock) list;
+       int count;
+       struct vm_anon *anons;
+};
+static LIST_HEAD(anonlist, uvm_anonblock) anonblock_list;
+
+
+static boolean_t anon_pagein __P((struct vm_anon *));
+
+
+/*
  * allocate anons
  */
 void
 uvm_anon_init()
 {
-       struct vm_anon *anon;
        int nanon = uvmexp.free - (uvmexp.free / 16); /* XXXCDC ??? */
-       int lcv;
+
+       simple_lock_init(&uvm.afreelock);
+       LIST_INIT(&anonblock_list);
 
        /*
         * Allocate the initial anons.
         */
-       anon = (struct vm_anon *)uvm_km_alloc(kernel_map,
-           sizeof(*anon) * nanon);
-       if (anon == NULL) {
-               printf("uvm_anon_init: can not allocate %d anons\n", nanon);
-               panic("uvm_anon_init");
-       }
-
-       memset(anon, 0, sizeof(*anon) * nanon);
-       uvm.afree = NULL;
-       uvmexp.nanon = uvmexp.nfreeanon = nanon;
-       for (lcv = 0 ; lcv < nanon ; lcv++) {
-               anon[lcv].u.an_nxt = uvm.afree;
-               uvm.afree = &anon[lcv];
-               simple_lock_init(&uvm.afree->an_lock);
-       }
-       simple_lock_init(&uvm.afreelock);
+       uvm_anon_add(nanon);
 }
 
 /*
  * add some more anons to the free pool.  called when we add
  * more swap space.
+ *
+ * => swap_syscall_lock should be held (protects anonblock_list).
  */
 void
-uvm_anon_add(pages)
-       int     pages;
+uvm_anon_add(count)
+       int     count;
 {
+       struct uvm_anonblock *anonblock;
        struct vm_anon *anon;
-       int lcv;
+       int lcv, needed;
+
+       simple_lock(&uvm.afreelock);
+       uvmexp.nanonneeded += count;
+       needed = uvmexp.nanonneeded - uvmexp.nanon;
+       simple_unlock(&uvm.afreelock);
 
-       anon = (struct vm_anon *)uvm_km_alloc(kernel_map,
-           sizeof(*anon) * pages);
+       if (needed <= 0) {
+               return;
+       }
+ 
+       MALLOC(anonblock, void *, sizeof(*anonblock), M_UVMAMAP, M_WAITOK);
+       anon = (void *)uvm_km_alloc(kernel_map, sizeof(*anon) * needed);
 
        /* XXX Should wait for VM to free up. */
-       if (anon == NULL) {
-               printf("uvm_anon_add: can not allocate %d anons\n", pages);
+       if (anonblock == NULL || anon == NULL) {
+               printf("uvm_anon_add: can not allocate %d anons\n", needed);
                panic("uvm_anon_add");
        }
 
+       anonblock->count = needed;
+       anonblock->anons = anon;
+       LIST_INSERT_HEAD(&anonblock_list, anonblock, list);
+       memset(anon, 0, sizeof(*anon) * needed);
+ 
        simple_lock(&uvm.afreelock);
-       memset(anon, 0, sizeof(*anon) * pages);
-       uvmexp.nanon += pages;
-       uvmexp.nfreeanon += pages;
-       for (lcv = 0; lcv < pages; lcv++) {
+       uvmexp.nanon += needed;
+       uvmexp.nfreeanon += needed;
+       for (lcv = 0; lcv < needed; lcv++) {
                simple_lock_init(&anon->an_lock);
                anon[lcv].u.an_nxt = uvm.afree;
                uvm.afree = &anon[lcv];
@@ -116,6 +136,23 @@
 }
 
 /*
+ * remove anons from the free pool.
+ */
+void
+uvm_anon_remove(count)
+       int count;
+{
+       /*
+        * we never actually free any anons, to avoid allocation overhead.
+        * XXX someday we might want to try to free anons.
+        */
+
+       simple_lock(&uvm.afreelock);
+       uvmexp.nanonneeded -= count;
+       simple_unlock(&uvm.afreelock);
+}
+
+/*
  * allocate an anon
  */
 struct vm_anon *
@@ -363,3 +400,143 @@
 
        return(pg);
 }
+
+
+
+/*
+ * page in every anon that is paged out to a range of swslots.
+ * 
+ * swap_syscall_lock should be held (protects anonblock_list).
+ */
+
+boolean_t
+anon_swap_off(startslot, endslot)
+       int startslot, endslot;
+{
+       struct uvm_anonblock *anonblock;
+
+       for (anonblock = LIST_FIRST(&anonblock_list);
+            anonblock != NULL;
+            anonblock = LIST_NEXT(anonblock, list)) {
+               int i;
+
+               /*
+                * loop thru all the anons in the anonblock,
+                * paging in where needed.
+                */
+
+               for (i = 0; i < anonblock->count; i++) {
+                       struct vm_anon *anon = &anonblock->anons[i];
+                       int slot;
+
+                       /*
+                        * lock anon to work on it.
+                        */
+
+                       simple_lock(&anon->an_lock);
+
+                       /*
+                        * is this anon's swap slot in range?
+                        */
+
+                       slot = anon->an_swslot;
+                       if (slot >= startslot && slot < endslot) {
+                               boolean_t rv;
+
+                               /*
+                                * yup, page it in.
+                                */
+
+                               /* locked: anon */
+                               rv = anon_pagein(anon);
+                               /* unlocked: anon */
+
+                               if (rv) {
+                                       return rv;
+                               }
+                       } else {
+
+                               /*
+                                * nope, unlock and proceed.
+                                */
+
+                               simple_unlock(&anon->an_lock);
+                       }
+               }
+       }
+       return FALSE;
+}
+
+
+/*
+ * fetch an anon's page.
+ *
+ * => anon must be locked, and is unlocked upon return.
+ * => returns TRUE if pagein was aborted due to lack of memory.
+ */
+
+static boolean_t
+anon_pagein(anon)
+       struct vm_anon *anon;
+{
+       struct vm_page *pg;
+       struct uvm_object *uobj;
+       int rv;
+       UVMHIST_FUNC("anon_pagein"); UVMHIST_CALLED(pdhist);
+       
+       /* locked: anon */
+       rv = uvmfault_anonget(NULL, NULL, anon);
+       /* unlocked: anon */
+
+       switch (rv) {
+       case VM_PAGER_OK:
+               break;
+
+       case VM_PAGER_ERROR:
+       case VM_PAGER_REFAULT:
+
+               /*
+                * nothing more to do on errors.
+                * VM_PAGER_REFAULT can only mean that the anon was freed,
+                * so again there's nothing to do.
+                */
+
+               return FALSE;
+
+#ifdef DIAGNOSTIC
+       default:
+               panic("anon_pagein: uvmfault_anonget -> %d", rv);
+#endif
+       }
+
+       /*
+        * ok, we've got the page now.
+        * mark it as dirty, clear its swslot and un-busy it.
+        */
+
+       pg = anon->u.an_page;
+       uobj = pg->uobject;
+       uvm_swap_free(anon->an_swslot, 1);
+       anon->an_swslot = 0;
+       pg->flags &= ~(PG_CLEAN);
+
+       /*
+        * deactivate the page (to put it on a page queue)
+        */
+
+       pmap_clear_reference(pg);
+       pmap_page_protect(pg, VM_PROT_NONE);
+       uvm_lock_pageq();
+       uvm_pagedeactivate(pg);
+       uvm_unlock_pageq();
+
+       /*
+        * unlock the anon and we're done.
+        */
+
+       simple_unlock(&anon->an_lock);
+       if (uobj) {
+               simple_unlock(&uobj->vmobjlock);
+       }
+       return FALSE;
+}
diff -r df0e67adb6c2 -r 5e442c0df940 sys/uvm/uvm_anon.h
--- a/sys/uvm/uvm_anon.h        Tue Jan 11 05:48:27 2000 +0000
+++ b/sys/uvm/uvm_anon.h        Tue Jan 11 06:57:49 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvm_anon.h,v 1.11 1999/06/21 17:25:11 thorpej Exp $    */



Home | Main Index | Thread Index | Old Index