git: a8d3ef5bc6de - stable/13 - vm_page: Remove extra test from page alloc

From: Doug Moore <dougm_at_FreeBSD.org>
Date: Mon, 11 Jul 2022 05:41:24 UTC
The branch stable/13 has been updated by dougm:

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

commit a8d3ef5bc6de9efb56132797558795d7918d4be9
Author:     Doug Moore <dougm@FreeBSD.org>
AuthorDate: 2021-12-24 04:45:47 +0000
Commit:     Doug Moore <dougm@FreeBSD.org>
CommitDate: 2022-07-11 05:41:05 +0000

    vm_page: Remove extra test from page alloc
    
    Extract code from vm_page_alloc_contig_domain into a new function.  Do
    so in a way that eliminates a bound-to-fail reservation test after a
    reservation is broken by a call from vm_page_alloc_contig_domain.
    
    Reviewed by:    kib
    Differential Revision:  https://reviews.freebsd.org/D33551
    
    (cherry picked from commit fb38b29b5609b0c0769b2b2e1d6c917c0799f2a0)
---
 sys/vm/vm_page.c | 81 ++++++++++++++++++++++++++++++++------------------------
 1 file changed, 47 insertions(+), 34 deletions(-)

diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index 685a5338969b..2b9e46674bdf 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -2187,12 +2187,46 @@ vm_page_alloc_contig(vm_object_t object, vm_pindex_t pindex, int req,
 	return (m);
 }
 
+static vm_page_t
+vm_page_find_contig_domain(int domain, int req, u_long npages, vm_paddr_t low,
+    vm_paddr_t high, u_long alignment, vm_paddr_t boundary)
+{
+	struct vm_domain *vmd;
+	vm_page_t m_ret;
+
+	vmd = VM_DOMAIN(domain);
+	if (!vm_domain_allocate(vmd, req, npages))
+		return (NULL);
+#if VM_NRESERVLEVEL > 0
+again:
+#endif
+	/*
+	 * Try to allocate the pages from the free page queues.
+	 */
+	vm_domain_free_lock(vmd);
+	m_ret = vm_phys_alloc_contig(domain, npages, low, high,
+	    alignment, boundary);
+	vm_domain_free_unlock(vmd);
+	if (m_ret != NULL)
+		return (m_ret);
+	vm_domain_freecnt_inc(vmd, npages);
+#if VM_NRESERVLEVEL > 0
+	/*
+	 * Try to break a reservation to replenish free page queues
+	 * in a way that allows the allocation to succeed.
+	 */
+	if (vm_reserv_reclaim_contig(domain, npages, low,
+	    high, alignment, boundary))
+		goto again;
+#endif
+	return (m_ret);
+}
+
 vm_page_t
 vm_page_alloc_contig_domain(vm_object_t object, vm_pindex_t pindex, int domain,
     int req, u_long npages, vm_paddr_t low, vm_paddr_t high, u_long alignment,
     vm_paddr_t boundary, vm_memattr_t memattr)
 {
-	struct vm_domain *vmd;
 	vm_page_t m, m_ret, mpred;
 	u_int busy_lock, flags, oflags;
 
@@ -2223,44 +2257,23 @@ vm_page_alloc_contig_domain(vm_object_t object, vm_pindex_t pindex, int domain,
 	 * Can we allocate the pages without the number of free pages falling
 	 * below the lower bound for the allocation class?
 	 */
-	m_ret = NULL;
-again:
+	for (;;) {
 #if VM_NRESERVLEVEL > 0
-	/*
-	 * Can we allocate the pages from a reservation?
-	 */
-	if (vm_object_reserv(object) &&
-	    (m_ret = vm_reserv_alloc_contig(object, pindex, domain, req,
-	    mpred, npages, low, high, alignment, boundary)) != NULL) {
-		goto found;
-	}
-#endif
-	vmd = VM_DOMAIN(domain);
-	if (vm_domain_allocate(vmd, req, npages)) {
 		/*
-		 * allocate them from the free page queues.
+		 * Can we allocate the pages from a reservation?
 		 */
-		vm_domain_free_lock(vmd);
-		m_ret = vm_phys_alloc_contig(domain, npages, low, high,
-		    alignment, boundary);
-		vm_domain_free_unlock(vmd);
-		if (m_ret == NULL) {
-			vm_domain_freecnt_inc(vmd, npages);
-#if VM_NRESERVLEVEL > 0
-			if (vm_reserv_reclaim_contig(domain, npages, low,
-			    high, alignment, boundary))
-				goto again;
-#endif
+		if (vm_object_reserv(object) &&
+		    (m_ret = vm_reserv_alloc_contig(object, pindex, domain, req,
+		    mpred, npages, low, high, alignment, boundary)) != NULL) {
+			break;
 		}
-	}
-	if (m_ret == NULL) {
-		if (vm_domain_alloc_fail(vmd, object, req))
-			goto again;
-		return (NULL);
-	}
-#if VM_NRESERVLEVEL > 0
-found:
 #endif
+		if ((m_ret = vm_page_find_contig_domain(domain, req, npages,
+		    low, high, alignment, boundary)) != NULL)
+			break;
+		if (!vm_domain_alloc_fail(VM_DOMAIN(domain), object, req))
+			return (NULL);
+	}
 	for (m = m_ret; m < &m_ret[npages]; m++) {
 		vm_page_dequeue(m);
 		vm_page_alloc_check(m);