git: 557dc337e6cb - main - vm_phys: check small blocks to finish allocation

From: Doug Moore <dougm_at_FreeBSD.org>
Date: Thu, 31 Mar 2022 21:23:01 UTC
The branch main has been updated by dougm:

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

commit 557dc337e6cb6664a322c3988632b5ca75ff33ed
Author:     Doug Moore <dougm@FreeBSD.org>
AuthorDate: 2022-03-31 21:19:55 +0000
Commit:     Doug Moore <dougm@FreeBSD.org>
CommitDate: 2022-03-31 21:19:55 +0000

    vm_phys: check small blocks to finish allocation
    
    In vm_phys_alloc_queues_contig, in the case that a sequence of
    max-order blocks are sought to fulfill an allocation, a sequence is
    ruled out if it does not have enough max-order blocks to satisfy the
    allocation. However, there may be smaller blocks of free memory that
    follow the last max-order block in the sequence, and they may be big
    enough to complete the allocation request, so check for that
    possibility before giving up on that block sequence.
    
    Reviewed by:    markj
    Tested by:      pho
    Differential Revision:  https://reviews.freebsd.org/D34724
---
 sys/vm/vm_phys.c | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/sys/vm/vm_phys.c b/sys/vm/vm_phys.c
index 1f4c228b1a84..33c46fe7c481 100644
--- a/sys/vm/vm_phys.c
+++ b/sys/vm/vm_phys.c
@@ -1405,9 +1405,9 @@ vm_phys_alloc_queues_contig(
 					continue;
 
 				/*
-				 * Determine if a sufficient number of
-				 * subsequent blocks to satisfy the
-				 * allocation request are free.
+				 * Determine if a series of free oind-blocks
+				 * starting here can satisfy the allocation
+				 * request.
 				 */
 				do {
 					pa += 1 <<
@@ -1416,6 +1416,23 @@ vm_phys_alloc_queues_contig(
 						goto done;
 				} while (VM_NFREEORDER - 1 == seg->first_page[
 				    atop(pa - seg->start)].order);
+
+				/*
+				 * Determine if an additional series of free
+				 * blocks of diminishing size can help to
+				 * satisfy the allocation request.
+				 */
+				for (;;) {
+					m = &seg->first_page[
+					    atop(pa - seg->start)];
+					if (m->order == VM_NFREEORDER ||
+					    pa + (2 << (PAGE_SHIFT + m->order))
+					    <= pa_end)
+						break;
+					pa += 1 << (PAGE_SHIFT + m->order);
+					if (pa >= pa_end)
+						goto done;
+				}
 			}
 		}
 	}
@@ -1423,6 +1440,7 @@ vm_phys_alloc_queues_contig(
 done:
 	for (m = m_ret; m < &m_ret[npages]; m = &m[1 << oind]) {
 		fl = (*queues)[m->pool];
+		oind = m->order;
 		vm_freelist_rem(fl, m, oind);
 		if (m->pool != VM_FREEPOOL_DEFAULT)
 			vm_phys_set_pool(VM_FREEPOOL_DEFAULT, m, oind);