kernel - Make VM fault waits in low memory the same as other low memory waits
authorMatthew Dillon <dillon@apollo.backplane.com>
Sun, 3 Mar 2013 01:11:19 +0000 (17:11 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Sun, 3 Mar 2013 01:11:19 +0000 (17:11 -0800)
* Nominal memory allocations, particularly by tmpfs, allow allocations
  down to the 'min' before waiting for memory to recover to 'target'.
  The VM fault code required memory to be at or above the 'target'
  at all times.  This led to extreme starvation because other user-accessible
  subsystems could force free memory to remain below 'target'.

* Change the VM code to use substantially the same down-to 'min' and
  recover-to 'target' parameters that other subsystems use.  This
  should reduce the excessive stalls under low memory conditions.

* Rename vm_waitpfault() to vm_wait_pfault() to conform with other
  naming schemes in the same API.

sys/vm/vm_fault.c
sys/vm/vm_page.c
sys/vm/vm_pageout.h

index 3adce4b..3ee82c2 100644 (file)
@@ -1202,7 +1202,7 @@ vm_fault_object(struct faultstate *fs,
                                if (fs->object != fs->first_object)
                                        vm_object_drop(fs->object);
                                unlock_and_deallocate(fs);
-                               vm_waitpfault();
+                               vm_wait_pfault();
                                return (KERN_TRY_AGAIN);
                        }
 
@@ -1285,7 +1285,7 @@ vm_fault_object(struct faultstate *fs,
                                if (fs->object != fs->first_object)
                                        vm_object_drop(fs->object);
                                unlock_and_deallocate(fs);
-                               vm_waitpfault();
+                               vm_wait_pfault();
                                return (KERN_TRY_AGAIN);
                        }
 
index 9a65c78..58def88 100644 (file)
@@ -1828,20 +1828,22 @@ vm_wait(int timo)
  * easily tracked.
  */
 void
-vm_waitpfault(void)
+vm_wait_pfault(void)
 {
        /*
         * Wakeup the pageout daemon if necessary and wait.
         */
-       if (vm_page_count_target()) {
+       if (vm_page_count_min(0)) {
                lwkt_gettoken(&vm_token);
-               if (vm_page_count_target()) {
-                       if (vm_pages_needed == 0) {
-                               vm_pages_needed = 1;
-                               wakeup(&vm_pages_needed);
+               while (vm_page_count_severe()) {
+                       if (vm_page_count_target()) {
+                               if (vm_pages_needed == 0) {
+                                       vm_pages_needed = 1;
+                                       wakeup(&vm_pages_needed);
+                               }
+                               ++vm_pages_waiting;     /* SMP race ok */
+                               tsleep(&vmstats.v_free_count, 0, "pfault", hz);
                        }
-                       ++vm_pages_waiting;     /* SMP race ok */
-                       tsleep(&vmstats.v_free_count, 0, "pfault", hz);
                }
                lwkt_reltoken(&vm_token);
        }
index 1b878b9..e86bfbf 100644 (file)
@@ -105,7 +105,7 @@ extern int vm_pageout_deficit;
 
 extern void pagedaemon_wakeup (void);
 extern void vm_wait (int timo);
-extern void vm_waitpfault (void);
+extern void vm_wait_pfault (void);
 
 #ifdef _KERNEL
 void vm_pageout_page (vm_page_t, vm_object_t);