Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 8 Oct 2021 09:25:27 GMT
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 174aad047e12 - main - vm_fault: do not trigger OOM too early
Message-ID:  <202110080925.1989PRgf066947@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=174aad047e12e8f30f9a5919ca1c08919441a217

commit 174aad047e12e8f30f9a5919ca1c08919441a217
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2021-10-04 06:36:02 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2021-10-08 09:24:46 +0000

    vm_fault: do not trigger OOM too early
    
    Wakeup in vm_waitpfault() does not mean that the thread would get the
    page on the next vm_page_alloc() call, other thread might steal the free
    page we were waiting for. On the other hand, this wakeup might come much
    earlier than just vm_pfault_oom_wait seconds, if the rate of the page
    reclamation is high enough.
    
    If wakeups come fast and we loose the allocation race enough times, OOM
    could be undeservably triggered much earlier than vm_pfault_oom_attempts
    x vm_pfault_oom_wait seconds.  Fix it by not counting the number of sleeps,
    but measuring the time to th first allocation failure, and triggering OOM
    when it was older than oom_attempts x oom_wait seconds.
    
    Reviewed by:    markj
    Tested by:      pho
    Sponsored by:   The FreeBSD Foundation
    MFC after:      2 weeks
    Differential revision:  https://reviews.freebsd.org/D32287
---
 sys/vm/vm_fault.c | 52 +++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 37 insertions(+), 15 deletions(-)

diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index 5cfe7d1ae315..8a4b5a543dd6 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -125,7 +125,8 @@ struct faultstate {
 	vm_prot_t	fault_type;
 	vm_prot_t	prot;
 	int		fault_flags;
-	int		oom;
+	struct timeval	oom_start_time;
+	bool		oom_started;
 	boolean_t	wired;
 
 	/* Page reference for cow. */
@@ -1073,6 +1074,38 @@ vm_fault_zerofill(struct faultstate *fs)
 	vm_page_valid(fs->m);
 }
 
+/*
+ * Initiate page fault after timeout.  Returns true if caller should
+ * do vm_waitpfault() after the call.
+ */
+static bool
+vm_fault_allocate_oom(struct faultstate *fs)
+{
+	struct timeval now;
+
+	unlock_and_deallocate(fs);
+	if (vm_pfault_oom_attempts < 0)
+		return (true);
+	if (!fs->oom_started) {
+		fs->oom_started = true;
+		getmicrotime(&fs->oom_start_time);
+		return (true);
+	}
+
+	getmicrotime(&now);
+	timevalsub(&now, &fs->oom_start_time);
+	if (now.tv_sec < vm_pfault_oom_attempts * vm_pfault_oom_wait)
+		return (true);
+
+	if (bootverbose)
+		printf(
+	    "proc %d (%s) failed to alloc page on fault, starting OOM\n",
+		    curproc->p_pid, curproc->p_comm);
+	vm_pageout_oom(VM_OOM_MEM_PF);
+	fs->oom_started = false;
+	return (false);
+}
+
 /*
  * Allocate a page directly or via the object populate method.
  */
@@ -1136,22 +1169,11 @@ vm_fault_allocate(struct faultstate *fs)
 		fs->m = vm_page_alloc(fs->object, fs->pindex, alloc_req);
 	}
 	if (fs->m == NULL) {
-		unlock_and_deallocate(fs);
-		if (vm_pfault_oom_attempts < 0 ||
-		    fs->oom < vm_pfault_oom_attempts) {
-			fs->oom++;
+		if (vm_fault_allocate_oom(fs))
 			vm_waitpfault(dset, vm_pfault_oom_wait * hz);
-		} else 	{
-			if (bootverbose)
-				printf(
-		"proc %d (%s) failed to alloc page on fault, starting OOM\n",
-				    curproc->p_pid, curproc->p_comm);
-			vm_pageout_oom(VM_OOM_MEM_PF);
-			fs->oom = 0;
-		}
 		return (KERN_RESOURCE_SHORTAGE);
 	}
-	fs->oom = 0;
+	fs->oom_started = false;
 
 	return (KERN_NOT_RECEIVER);
 }
@@ -1300,7 +1322,7 @@ vm_fault(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type,
 	fs.fault_flags = fault_flags;
 	fs.map = map;
 	fs.lookup_still_valid = false;
-	fs.oom = 0;
+	fs.oom_started = false;
 	faultcount = 0;
 	nera = -1;
 	hardfault = false;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202110080925.1989PRgf066947>