From: Matthew Dillon Date: Sun, 3 Mar 2013 01:11:19 +0000 (-0800) Subject: kernel - Make VM fault waits in low memory the same as other low memory waits X-Git-Tag: v3.4.0rc~166 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/3b47bfc4f83363f5a473ab71e6219ad84ebc6b77 kernel - Make VM fault waits in low memory the same as other low memory waits * 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. --- diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index 3adce4b933..3ee82c282d 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -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); } diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 9a65c78824..58def88750 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -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); } diff --git a/sys/vm/vm_pageout.h b/sys/vm/vm_pageout.h index 1b878b99ac..e86bfbf7f4 100644 --- a/sys/vm/vm_pageout.h +++ b/sys/vm/vm_pageout.h @@ -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);