From 0a4d482811b78282cf243f23694d804716050c98 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Mon, 24 Oct 2011 21:53:43 -0700 Subject: [PATCH] kernel - Increase VM page free minimums for allocations * Recent work removed the global vm_token and moved to per-vm_page_queue spin locks, which allows cpus to allocate VM pages concurrently. This could result in a situation where remaining free pages got blown out without giving the system a chance to replentish them. * Symptoms included the BUF/BIO system complaining of memory exhaustion and the pageout daemon deadlocking on low memory (which would deadlock the whole machine in a memory-exhausted state). * Increase minimums to prevent this. In particular, the interrupt_free_min was previously hardwired to a value of 2.. as in 2 pages (8192 bytes), which is an excessively low value. The new calculations place this value (typically) around a few-hundred pages. --- sys/vm/vm_pageout.c | 22 ++++++++++++---------- sys/vm/vnode_pager.c | 4 +++- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index 855084a298..cd8b0cd9c5 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -1678,18 +1678,21 @@ vm_pageout_free_page_calc(vm_size_t count) /* * free_reserved needs to include enough for the largest swap pager * structures plus enough for any pv_entry structs when paging. + * + * v_free_min normal allocations + * v_free_reserved system allocations + * v_pageout_free_min allocations by pageout daemon + * v_interrupt_free_min low level allocations (e.g swap structures) */ if (vmstats.v_page_count > 1024) - vmstats.v_free_min = 4 + (vmstats.v_page_count - 1024) / 200; + vmstats.v_free_min = 64 + (vmstats.v_page_count - 1024) / 200; else - vmstats.v_free_min = 4; - vmstats.v_pageout_free_min = (2*MAXBSIZE)/PAGE_SIZE + - vmstats.v_interrupt_free_min; - vmstats.v_free_reserved = vm_pageout_page_count + - vmstats.v_pageout_free_min + (count / 768) + PQ_L2_SIZE; - vmstats.v_free_severe = vmstats.v_free_min / 2; - vmstats.v_free_min += vmstats.v_free_reserved; - vmstats.v_free_severe += vmstats.v_free_reserved; + vmstats.v_free_min = 64; + vmstats.v_free_reserved = vmstats.v_free_min * 4 / 8 + 7; + vmstats.v_free_severe = vmstats.v_free_min * 4 / 8 + 0; + vmstats.v_pageout_free_min = vmstats.v_free_min * 2 / 8 + 7; + vmstats.v_interrupt_free_min = vmstats.v_free_min * 1 / 8 + 7; + return 1; } @@ -1710,7 +1713,6 @@ vm_pageout_thread(void) */ curthread->td_flags |= TDF_SYSTHREAD; - vmstats.v_interrupt_free_min = 2; if (vmstats.v_page_count < 2000) vm_pageout_page_count = 8; diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index 081862ec41..9a589d4da1 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -709,8 +709,10 @@ vnode_pager_putpages(vm_object_t object, vm_page_t *m, int count, * daemon up. This should be probably be addressed XXX. */ - if ((vmstats.v_free_count + vmstats.v_cache_count) < vmstats.v_pageout_free_min) + if ((vmstats.v_free_count + vmstats.v_cache_count) < + vmstats.v_pageout_free_min) { sync |= OBJPC_SYNC; + } /* * Call device-specific putpages function -- 2.41.0