summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbeck <beck@openbsd.org>2019-05-09 20:36:44 +0000
committerbeck <beck@openbsd.org>2019-05-09 20:36:44 +0000
commitd4c6c9b57a2886f149c0c3fc366ab553f5c7721a (patch)
treea2900691486856d802afbe1fcee40c1f314fc924
parentUnlock adjfreq(2), adjtime(2), clock_settime(2), and settimeofday(2). (diff)
downloadwireguard-openbsd-d4c6c9b57a2886f149c0c3fc366ab553f5c7721a.tar.xz
wireguard-openbsd-d4c6c9b57a2886f149c0c3fc366ab553f5c7721a.zip
Ensure that pagedaemon wakeups as a result of failed UVM_PLA_NOWAIT
allocations will recover some memory from the dma_constraint range. The allocation still fails, the intent is to ensure that the pagedaemon will free some memory to possibly allow a subsequent allocation to succeed. This also adds a UVM_PLA_NOWAKE flag to allow special cases in the buffer cache to not wake up the pagedaemon until they want to. ok kettenis@
-rw-r--r--sys/kern/vfs_biomem.c6
-rw-r--r--sys/uvm/uvm_extern.h3
-rw-r--r--sys/uvm/uvm_pdaemon.c30
-rw-r--r--sys/uvm/uvm_pmemrange.c17
4 files changed, 45 insertions, 11 deletions
diff --git a/sys/kern/vfs_biomem.c b/sys/kern/vfs_biomem.c
index 0f761c976c2..8bdd583fe58 100644
--- a/sys/kern/vfs_biomem.c
+++ b/sys/kern/vfs_biomem.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_biomem.c,v 1.40 2019/05/08 12:40:57 beck Exp $ */
+/* $OpenBSD: vfs_biomem.c,v 1.41 2019/05/09 20:36:44 beck Exp $ */
/*
* Copyright (c) 2007 Artur Grabowski <art@openbsd.org>
@@ -288,7 +288,7 @@ buf_alloc_pages(struct buf *bp, vsize_t size)
*/
do {
i = uvm_pagealloc_multi(buf_object, offs, size,
- UVM_PLA_NOWAIT);
+ UVM_PLA_NOWAIT | UVM_PLA_NOWAKE);
if (i == 0)
break;
} while (bufbackoff(&dma_constraint, size) == 0);
@@ -359,7 +359,7 @@ buf_realloc_pages(struct buf *bp, struct uvm_constraint_range *where,
do {
r = uvm_pagerealloc_multi(bp->b_pobj, bp->b_poffs,
- bp->b_bufsize, UVM_PLA_NOWAIT, where);
+ bp->b_bufsize, UVM_PLA_NOWAIT | UVM_PLA_NOWAKE, where);
if (r == 0)
break;
} while ((bufbackoff(where, atop(bp->b_bufsize)) == 0));
diff --git a/sys/uvm/uvm_extern.h b/sys/uvm/uvm_extern.h
index 24ddcd98ccd..12dc1f7b32f 100644
--- a/sys/uvm/uvm_extern.h
+++ b/sys/uvm/uvm_extern.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_extern.h,v 1.145 2019/03/01 01:46:18 cheloha Exp $ */
+/* $OpenBSD: uvm_extern.h,v 1.146 2019/05/09 20:36:44 beck Exp $ */
/* $NetBSD: uvm_extern.h,v 1.57 2001/03/09 01:02:12 chs Exp $ */
/*
@@ -151,6 +151,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_NOWAKE 0x0020 /* don't wake the page daemon on failure */
/*
* lockflags that control the locking behavior of various functions.
diff --git a/sys/uvm/uvm_pdaemon.c b/sys/uvm/uvm_pdaemon.c
index c0368f66815..1c3c38fd5ea 100644
--- a/sys/uvm/uvm_pdaemon.c
+++ b/sys/uvm/uvm_pdaemon.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_pdaemon.c,v 1.79 2018/01/18 18:08:51 bluhm Exp $ */
+/* $OpenBSD: uvm_pdaemon.c,v 1.80 2019/05/09 20:36:44 beck Exp $ */
/* $NetBSD: uvm_pdaemon.c,v 1.23 2000/08/20 10:24:14 bjh21 Exp $ */
/*
@@ -186,6 +186,13 @@ uvmpd_tune(void)
}
/*
+ * Indicate to the page daemon that a nowait call failed and it should
+ * recover at least some memory in the most restricted region (assumed
+ * to be dma_constraint).
+ */
+volatile int uvm_nowait_failed;
+
+/*
* uvm_pageout: the main loop for the pagedaemon
*/
void
@@ -205,12 +212,17 @@ uvm_pageout(void *arg)
uvm_unlock_pageq();
for (;;) {
+ int nowaitfailed = 0;
long size;
work_done = 0; /* No work done this iteration. */
uvm_lock_fpageq();
+ if (uvm_nowait_failed) {
+ nowaitfailed = 1;
+ uvm_nowait_failed = 0;
+ }
- if (TAILQ_EMPTY(&uvm.pmr_control.allocs)) {
+ if (!nowaitfailed && TAILQ_EMPTY(&uvm.pmr_control.allocs)) {
msleep(&uvm.pagedaemon, &uvm.fpageqlock, PVM,
"pgdaemon", 0);
uvmexp.pdwoke++;
@@ -219,8 +231,16 @@ uvm_pageout(void *arg)
if ((pma = TAILQ_FIRST(&uvm.pmr_control.allocs)) != NULL) {
pma->pm_flags |= UVM_PMA_BUSY;
constraint = pma->pm_constraint;
- } else
- constraint = no_constraint;
+ } else {
+ if (nowaitfailed) {
+ /*
+ * XXX realisticly, this is what our
+ * nowait callers probably care about
+ */
+ constraint = dma_constraint;
+ } else
+ constraint = no_constraint;
+ }
uvm_unlock_fpageq();
@@ -243,6 +263,8 @@ uvm_pageout(void *arg)
if (uvmexp.free - BUFPAGES_DEFICIT < uvmexp.freetarg)
size += uvmexp.freetarg - (uvmexp.free -
BUFPAGES_DEFICIT);
+ if (size == 0)
+ size = 16; /* XXX */
uvm_unlock_pageq();
(void) bufbackoff(&constraint, size * 2);
uvm_lock_pageq();
diff --git a/sys/uvm/uvm_pmemrange.c b/sys/uvm/uvm_pmemrange.c
index dcddfe35a14..cd92c319650 100644
--- a/sys/uvm/uvm_pmemrange.c
+++ b/sys/uvm/uvm_pmemrange.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_pmemrange.c,v 1.53 2016/09/16 02:52:24 dlg Exp $ */
+/* $OpenBSD: uvm_pmemrange.c,v 1.54 2019/05/09 20:36:44 beck Exp $ */
/*
* Copyright (c) 2009, 2010 Ariane van der Steldt <ariane@stack.nl>
@@ -702,6 +702,13 @@ uvm_pmr_extract_range(struct uvm_pmemrange *pmr, struct vm_page *pg,
}
/*
+ * Indicate to the page daemon that a nowait call failed and it should
+ * recover at least some memory in the most restricted region (assumed
+ * to be dma_constraint).
+ */
+extern volatile int uvm_nowait_failed;
+
+/*
* Acquire a number of pages.
*
* count: the number of pages returned
@@ -1014,8 +1021,12 @@ fail:
flags & UVM_PLA_FAILOK) == 0)
goto retry;
KASSERT(flags & UVM_PLA_FAILOK);
- } else
- wakeup(&uvm.pagedaemon);
+ } else {
+ if (!(flags & UVM_PLA_NOWAKE)) {
+ uvm_nowait_failed = 1;
+ wakeup(&uvm.pagedaemon);
+ }
+ }
uvm_unlock_fpageq();
return ENOMEM;