This is becoming less of a problem recently due to km_alloc (which
doesn't put stuff in the kernel object) but is still an issue.

on free of va space (and backing pages) that was allocated into the
kernel object we would hit a problem if a page was swapped out (this is
generally only pipebuffers). In that case we would not free the
swapslot.

I have seen panics before where nswpgsonly and nswpgs were different
(one bigger than should be possible) this is quite possibly. why.

ariane@ has already eyeballed this, and i've been running with it for a
couple of weeks (I do hit swap).

ok?

-0-


Index: uvm_aobj.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_aobj.c,v
retrieving revision 1.51
diff -u -p -r1.51 uvm_aobj.c
--- uvm_aobj.c  2 Jul 2010 02:08:53 -0000       1.51
+++ uvm_aobj.c  27 Apr 2011 12:37:35 -0000
@@ -1135,7 +1139,7 @@ uao_get(struct uvm_object *uobj, voff_t 
  * => aobj must be locked or have a reference count of 0.
  */
 
-void
+int
 uao_dropswap(struct uvm_object *uobj, int pageidx)
 {
        int slot;
@@ -1144,6 +1148,7 @@ uao_dropswap(struct uvm_object *uobj, in
        if (slot) {
                uvm_swap_free(slot, 1);
        }
+       return (slot);
 }
 
 
Index: uvm_aobj.h
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_aobj.h,v
retrieving revision 1.12
diff -u -p -r1.12 uvm_aobj.h
--- uvm_aobj.h  22 Jul 2009 21:05:37 -0000      1.12
+++ uvm_aobj.h  27 Apr 2011 12:35:41 -0000
@@ -65,7 +65,7 @@
 
 void uao_init(void);
 int uao_set_swslot(struct uvm_object *, int, int);
-void uao_dropswap(struct uvm_object *, int);
+int uao_dropswap(struct uvm_object *, int);
 int uao_swap_off(int, int);
 
 /*
Index: uvm_km.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_km.c,v
retrieving revision 1.100
diff -u -p -r1.100 uvm_km.c
--- uvm_km.c    23 Apr 2011 17:48:48 -0000      1.100
+++ uvm_km.c    27 Apr 2011 12:40:36 -0000
@@ -267,36 +267,33 @@ uvm_km_pgremove(struct uvm_object *uobj,
 {
        struct vm_page *pp;
        voff_t curoff;
+       int slot;
        UVMHIST_FUNC("uvm_km_pgremove"); UVMHIST_CALLED(maphist);
 
        KASSERT(uobj->pgops == &aobj_pager);
 
        for (curoff = start ; curoff < end ; curoff += PAGE_SIZE) {
                pp = uvm_pagelookup(uobj, curoff);
-               if (pp == NULL)
-                       continue;
-
-               UVMHIST_LOG(maphist,"  page %p, busy=%ld", pp,
-                   pp->pg_flags & PG_BUSY, 0, 0);
-
-               if (pp->pg_flags & PG_BUSY) {
+               if (pp && pp->pg_flags & PG_BUSY) {
                        atomic_setbits_int(&pp->pg_flags, PG_WANTED);
                        UVM_UNLOCK_AND_WAIT(pp, &uobj->vmobjlock, 0,
                            "km_pgrm", 0);
                        simple_lock(&uobj->vmobjlock);
                        curoff -= PAGE_SIZE; /* loop back to us */
                        continue;
-               } else {
-                       /* free the swap slot... */
-                       uao_dropswap(uobj, curoff >> PAGE_SHIFT);
+               }
+
+               /* free the swap slot, then the page */
+               slot = uao_dropswap(uobj, curoff >> PAGE_SHIFT);
 
-                       /*
-                        * ...and free the page; note it may be on the
-                        * active or inactive queues.
-                        */
+               if (pp != NULL) {
                        uvm_lock_pageq();
                        uvm_pagefree(pp);
                        uvm_unlock_pageq();
+               } else if (slot != 0) {
+                       simple_lock(&uvm.swap_data_lock);
+                       uvmexp.swpgonly--;
+                       simple_unlock(&uvm.swap_data_lock);
                }
        }
 }
-- 
First Law of Socio-Genetics:
        Celibacy is not hereditary.

Reply via email to