kernel - Fix incorrect dirty/reprotect code in pageout
authorMatthew Dillon <dillon@apollo.backplane.com>
Thu, 16 Aug 2012 18:42:25 +0000 (11:42 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Tue, 21 Aug 2012 03:59:34 +0000 (20:59 -0700)
* vm_object_page_collect_flush() was trying to re-protect VM pages that
  were still marked dirty after pageout I/O was initiated without owning
  the BUSY bit on the page.  This operation could race whatever I/O was
  going on and multiple issues.  Remove the re-protect.

  Just don't do it.  It's an unnecessary operation.  We still re-set
  PG_CLEANCHK on the page and that should be fine insofar as the pageout
  daemon goes.

* Note that the pageout_flush code protects the VM pages properly (to
  read-only) prior to initiating I/O .

* Should fix bug #2350

* Might be related to the wire-count bug considering that we were messing
  with the page's pmap without owning the BUSY bit.  Small chance.

sys/vm/vm_object.c

index c4f09c5..e0cbf5e 100644 (file)
@@ -99,7 +99,7 @@
 
 static void    vm_object_qcollapse(vm_object_t object,
                                    vm_object_t backing_object);
-static int     vm_object_page_collect_flush(vm_object_t object, vm_page_t p,
+static void    vm_object_page_collect_flush(vm_object_t object, vm_page_t p,
                                             int pagerflags);
 static void    vm_object_lock_init(vm_object_t);
 
@@ -1241,7 +1241,7 @@ done:
  *
  * The caller must hold the object.
  */
-static int
+static void
 vm_object_page_collect_flush(vm_object_t object, vm_page_t p, int pagerflags)
 {
        int runlen;
@@ -1343,9 +1343,15 @@ vm_object_page_collect_flush(vm_object_t object, vm_page_t p, int pagerflags)
 
        vm_pageout_flush(ma, runlen, pagerflags);
 
+       /*
+        * WARNING: Related pages are still held but the BUSY was inherited
+        *          by the pageout I/O, so the pages might not be busy any
+        *          more.  We cannot re-protect the page without waiting
+        *          for the I/O to complete and then busying it again.
+        */
        for (i = 0; i < runlen; i++) {
                if (ma[i]->valid & ma[i]->dirty) {
-                       vm_page_protect(ma[i], VM_PROT_READ);
+                       /*vm_page_protect(ma[i], VM_PROT_READ);*/
                        vm_page_flag_set(ma[i], PG_CLEANCHK);
 
                        /*
@@ -1358,7 +1364,7 @@ vm_object_page_collect_flush(vm_object_t object, vm_page_t p, int pagerflags)
                }
                vm_page_unhold(ma[i]);
        }
-       return(maxf + 1);
+       /*return(maxf + 1);*/
 }
 
 /*