diff options
author | 2011-07-07 20:52:50 +0000 | |
---|---|---|
committer | 2011-07-07 20:52:50 +0000 | |
commit | 0bec8dbe4017410cf1ddf990002aabeccd653f82 (patch) | |
tree | 5aec429a62d78dac765f4a08a89e26bb14b7cab9 | |
parent | There were two loops in pf_setup_pdesc() and pf_normalize_ip6() (diff) | |
download | wireguard-openbsd-0bec8dbe4017410cf1ddf990002aabeccd653f82.tar.xz wireguard-openbsd-0bec8dbe4017410cf1ddf990002aabeccd653f82.zip |
Move the uvm reserve enforcement from uvm_pagealloc to pmemrange.
More and more things are allocating outside of uvm_pagealloc these days making
it easy for something like the buffer cache to eat your last page with no
repercussions (other than a hung machine, of course).
ok ariane@ also ok ariane@ again after I spotted and fixed a possible underflow
problem in the calculation.
-rw-r--r-- | sys/uvm/uvm_extern.h | 3 | ||||
-rw-r--r-- | sys/uvm/uvm_page.c | 40 | ||||
-rw-r--r-- | sys/uvm/uvm_pmemrange.c | 38 |
3 files changed, 45 insertions, 36 deletions
diff --git a/sys/uvm/uvm_extern.h b/sys/uvm/uvm_extern.h index 72abe2a2540..72a9125340d 100644 --- a/sys/uvm/uvm_extern.h +++ b/sys/uvm/uvm_extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_extern.h,v 1.101 2011/07/06 19:50:38 beck Exp $ */ +/* $OpenBSD: uvm_extern.h,v 1.102 2011/07/07 20:52:50 oga Exp $ */ /* $NetBSD: uvm_extern.h,v 1.57 2001/03/09 01:02:12 chs Exp $ */ /* @@ -222,6 +222,7 @@ typedef int vm_prot_t; #define UVM_PLA_ZERO 0x0004 /* zero all pages before returning */ #define UVM_PLA_TRYCONTIG 0x0008 /* try to allocate contig physmem */ #define UVM_PLA_FAILOK 0x0010 /* caller can handle failure */ +#define UVM_PLA_USERESERVE 0x0020 /* ok to use reserve pages */ /* * lockflags that control the locking behavior of various functions. diff --git a/sys/uvm/uvm_page.c b/sys/uvm/uvm_page.c index 48a62736256..318a0e52734 100644 --- a/sys/uvm/uvm_page.c +++ b/sys/uvm/uvm_page.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_page.c,v 1.112 2011/07/06 19:50:38 beck Exp $ */ +/* $OpenBSD: uvm_page.c,v 1.113 2011/07/07 20:52:50 oga Exp $ */ /* $NetBSD: uvm_page.c,v 1.44 2000/11/27 08:40:04 chs Exp $ */ /* @@ -76,7 +76,6 @@ #include <sys/sched.h> #include <sys/kernel.h> #include <sys/vnode.h> -#include <sys/mount.h> #include <sys/proc.h> #include <uvm/uvm.h> @@ -920,43 +919,19 @@ uvm_pagealloc(struct uvm_object *obj, voff_t off, struct vm_anon *anon, struct vm_page *pg; struct pglist pgl; int pmr_flags; - boolean_t use_reserve; KASSERT(obj == NULL || anon == NULL); KASSERT(off == trunc_page(off)); - /* - * check to see if we need to generate some free pages waking - * the pagedaemon. - */ - if ((uvmexp.free - BUFPAGES_DEFICIT) < uvmexp.freemin || - ((uvmexp.free - BUFPAGES_DEFICIT) < uvmexp.freetarg && - (uvmexp.inactive + BUFPAGES_INACT) < uvmexp.inactarg)) - wakeup(&uvm.pagedaemon); - - /* - * fail if any of these conditions is true: - * [1] there really are no free pages, or - * [2] only kernel "reserved" pages remain and - * the page isn't being allocated to a kernel object. - * [3] only pagedaemon "reserved" pages remain and - * the requestor isn't the pagedaemon. - */ - - use_reserve = (flags & UVM_PGA_USERESERVE) || - (obj && UVM_OBJ_IS_KERN_OBJECT(obj)); - if ((uvmexp.free <= uvmexp.reserve_kernel && !use_reserve) || - (uvmexp.free <= uvmexp.reserve_pagedaemon && - !((curproc == uvm.pagedaemon_proc) || - (curproc == syncerproc)))) - goto fail; - + /* XXX these functions should share flags */ pmr_flags = UVM_PLA_NOWAIT; if (flags & UVM_PGA_ZERO) pmr_flags |= UVM_PLA_ZERO; + if (flags & UVM_PGA_USERESERVE) + pmr_flags |= UVM_PLA_USERESERVE; TAILQ_INIT(&pgl); if (uvm_pmr_getpages(1, 0, 0, 1, 0, 1, pmr_flags, &pgl) != 0) - goto fail; + return (NULL); pg = TAILQ_FIRST(&pgl); KASSERT(pg != NULL && TAILQ_NEXT(pg, pageq) == NULL); @@ -967,10 +942,7 @@ uvm_pagealloc(struct uvm_object *obj, voff_t off, struct vm_anon *anon, if (flags & UVM_PGA_ZERO) atomic_clearbits_int(&pg->pg_flags, PG_CLEAN); - return(pg); - - fail: - return (NULL); + return (pg); } /* diff --git a/sys/uvm/uvm_pmemrange.c b/sys/uvm/uvm_pmemrange.c index 114709b6ac4..20b68bd8152 100644 --- a/sys/uvm/uvm_pmemrange.c +++ b/sys/uvm/uvm_pmemrange.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_pmemrange.c,v 1.27 2011/07/06 19:50:38 beck Exp $ */ +/* $OpenBSD: uvm_pmemrange.c,v 1.28 2011/07/07 20:52:50 oga Exp $ */ /* * Copyright (c) 2009, 2010 Ariane van der Steldt <ariane@stack.nl> @@ -20,6 +20,7 @@ #include <sys/systm.h> #include <uvm/uvm.h> #include <sys/malloc.h> +#include <sys/mount.h> /* for BUFPAGES defines */ #include <sys/proc.h> /* XXX for atomic */ #include <sys/kernel.h> @@ -747,6 +748,7 @@ uvm_pmr_getpages(psize_t count, paddr_t start, paddr_t end, paddr_t align, int memtype; /* Requested memtype. */ int memtype_init; /* Best memtype. */ int desperate; /* True if allocation failed. */ + int is_pdaemon; #ifdef DIAGNOSTIC struct vm_page *diag_prev; /* Used during validation. */ #endif /* DIAGNOSTIC */ @@ -762,6 +764,26 @@ uvm_pmr_getpages(psize_t count, paddr_t start, paddr_t end, paddr_t align, (boundary == 0 || maxseg * boundary >= count) && TAILQ_EMPTY(result)); + is_pdaemon = ((curproc == uvm.pagedaemon_proc) || + (curproc == syncerproc)); + + /* + * All allocations by the pagedaemon automatically get access to + * the kernel reserve of pages so swapping can catch up with memory + * exhaustion + */ + if (is_pdaemon) + flags |= UVM_PLA_USERESERVE; + + /* + * check to see if we need to generate some free pages waking + * the pagedaemon. + */ + if ((uvmexp.free - BUFPAGES_DEFICIT) < uvmexp.freemin || + ((uvmexp.free - BUFPAGES_DEFICIT) < uvmexp.freetarg && + (uvmexp.inactive + BUFPAGES_INACT) < uvmexp.inactarg)) + wakeup(&uvm.pagedaemon); + /* * TRYCONTIG is a noop if you only want a single segment. * Remove it if that's the case: otherwise it'll deny the fast @@ -836,6 +858,20 @@ retry: /* Return point after sleeping. */ fcount = 0; fnsegs = 0; + /* + * fail if any of these conditions are true: + * [1] there really are no free pages, or + * [2] only kernel "reserved" pages remain and + * the we are not allowed to use them. + * [3] only pagedaemon "reserved" pages remain and + * the requestor isn't the pagedaemon. + */ + if (((uvmexp.free < uvmexp.reserve_kernel + ptoa(count)) && + (flags & UVM_PLA_USERESERVE) == 0) || + ((uvmexp.free < uvmexp.reserve_pagedaemon + ptoa(count)) && + !is_pdaemon)) + goto fail; + retry_desperate: /* * If we just want any page(s), go for the really fast option. |