The branch main has been updated by dougm:

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

commit b68c7ebf5e633549dfda1cfa25991b097dfbcdce
Author:     Doug Moore <do...@freebsd.org>
AuthorDate: 2025-03-31 04:00:53 +0000
Commit:     Doug Moore <do...@freebsd.org>
CommitDate: 2025-03-31 04:00:53 +0000

    vm_reserv: extract common gap-checking code
    
    vm_reserv_alloc_contig and vm_reserv_alloc_page both have code to
    determine whether a new reservation will fit between the predecessor
    and successor. Extract this code into a separate function rather than
    having it appear twice. Optimize slightly to avoid checking object
    size limit when there is a successor, and to avoid checking the upper
    bound at all when the size to be allocated is a multiple of
    reservation size.
    
    Reviewed by:    markj
    Differential Revision:  https://reviews.freebsd.org/D49460
---
 sys/vm/vm_reserv.c | 175 ++++++++++++++++++++++++-----------------------------
 1 file changed, 80 insertions(+), 95 deletions(-)

diff --git a/sys/vm/vm_reserv.c b/sys/vm/vm_reserv.c
index 3dc278851cc9..e553d115a6d4 100644
--- a/sys/vm/vm_reserv.c
+++ b/sys/vm/vm_reserv.c
@@ -549,6 +549,73 @@ vm_reserv_has_pindex(vm_reserv_t rv, vm_pindex_t pindex)
        return (((pindex - rv->pindex) & ~(VM_LEVEL_0_NPAGES - 1)) == 0);
 }
 
+/*
+ * How many pages should be in a new allocation that starts at the first page 
of
+ * the reservation superpage that contains 'first', fits between the 
allocations
+ * that include 'mpred' and 'msucc', fits within 'object', includes at least
+ * 'minpages' pages, and tries to include every allocated page in a superpage?
+ *
+ * We must synchronize with the reserv object lock to protect the pindex/object
+ * of the resulting reservations against rename while we are inspecting.
+ */
+static u_long
+vm_reserv_num_alloc_pages(vm_object_t object, vm_pindex_t first,
+    u_long minpages, vm_page_t mpred, vm_page_t msucc)
+{
+       vm_pindex_t leftcap, rightcap;
+       vm_reserv_t rv;
+       u_int allocpages;
+
+       allocpages = roundup2(minpages, VM_LEVEL_0_NPAGES);
+
+       vm_reserv_object_lock(object);
+       if (mpred != NULL) {
+               if ((rv = vm_reserv_from_page(mpred))->object != object)
+                       leftcap = mpred->pindex + 1;
+               else
+                       leftcap = rv->pindex + VM_LEVEL_0_NPAGES;
+               if (leftcap > first)
+                       allocpages = 0;
+       }
+       if (minpages < allocpages) {
+               if (msucc == NULL) {
+                       /*
+                        * Would the last new reservation extend past the end of
+                        * the object?
+                        *
+                        * If the object is unlikely to grow don't allocate a
+                        * reservation for the tail.
+                        */
+                       if ((object->flags & OBJ_ANON) == 0)
+                               rightcap = object->size;
+                       else
+                               rightcap = OBJ_MAX_SIZE;
+               } else {
+                       /*
+                        * Would the last new reservation extend past the start
+                        * of another page or reservation?
+                        *
+                        * If the object would, don't allocate a reservation for
+                        * the tail.
+                        */
+                       if ((rv = vm_reserv_from_page(msucc))->object != object)
+                               rightcap = msucc->pindex;
+                       else
+                               rightcap = rv->pindex;
+               }
+               if (first + allocpages > rightcap) {
+                       /*
+                        * A reservation for the last of the requested pages
+                        * will not fit.  Reduce the size of the upcoming
+                        * allocation accordingly.
+                        */
+                       allocpages = minpages;
+               }
+       }
+       vm_reserv_object_unlock(object);
+       return (allocpages);
+}
+
 /*
  * Increases the given reservation's population count.  Moves the reservation
  * to the tail of the partially populated reservation queue.
@@ -623,9 +690,9 @@ vm_reserv_alloc_contig(vm_object_t object, vm_pindex_t 
pindex, int domain,
        struct vm_domain *vmd;
        vm_paddr_t pa, size;
        vm_page_t m, m_ret, msucc;
-       vm_pindex_t first, leftcap, rightcap;
+       vm_pindex_t first;
        vm_reserv_t rv;
-       u_long allocpages, maxpages, minpages;
+       u_long allocpages;
        int i, index, n;
 
        VM_OBJECT_ASSERT_WLOCKED(object);
@@ -690,63 +757,14 @@ out:
        }
 
        /*
-        * Could at least one reservation fit between the first index to the
-        * left that can be used ("leftcap") and the first index to the right
-        * that cannot be used ("rightcap")?
-        *
-        * We must synchronize with the reserv object lock to protect the
-        * pindex/object of the resulting reservations against rename while
-        * we are inspecting.
+        * Check whether an allocation including at least one reservation can
+        * fit between mpred and msucc.
         */
        first = pindex - VM_RESERV_INDEX(object, pindex);
-       minpages = VM_RESERV_INDEX(object, pindex) + npages;
-       maxpages = roundup2(minpages, VM_LEVEL_0_NPAGES);
-       allocpages = maxpages;
-       vm_reserv_object_lock(object);
-       if (mpred != NULL) {
-               if ((rv = vm_reserv_from_page(mpred))->object != object)
-                       leftcap = mpred->pindex + 1;
-               else
-                       leftcap = rv->pindex + VM_LEVEL_0_NPAGES;
-               if (leftcap > first) {
-                       vm_reserv_object_unlock(object);
-                       return (NULL);
-               }
-       }
-       if (msucc != NULL) {
-               if ((rv = vm_reserv_from_page(msucc))->object != object)
-                       rightcap = msucc->pindex;
-               else
-                       rightcap = rv->pindex;
-               if (first + maxpages > rightcap) {
-                       if (maxpages == VM_LEVEL_0_NPAGES) {
-                               vm_reserv_object_unlock(object);
-                               return (NULL);
-                       }
-
-                       /*
-                        * At least one reservation will fit between "leftcap"
-                        * and "rightcap".  However, a reservation for the
-                        * last of the requested pages will not fit.  Reduce
-                        * the size of the upcoming allocation accordingly.
-                        */
-                       allocpages = minpages;
-               }
-       }
-       vm_reserv_object_unlock(object);
-
-       /*
-        * Would the last new reservation extend past the end of the object?
-        *
-        * If the object is unlikely to grow don't allocate a reservation for
-        * the tail.
-        */
-       if ((object->flags & OBJ_ANON) == 0 &&
-           first + maxpages > object->size) {
-               if (maxpages == VM_LEVEL_0_NPAGES)
-                       return (NULL);
-               allocpages = minpages;
-       }
+       allocpages = vm_reserv_num_alloc_pages(object, first,
+           VM_RESERV_INDEX(object, pindex) + npages, mpred, msucc);
+       if (allocpages < VM_LEVEL_0_NPAGES)
+               return (NULL);
 
        /*
         * Allocate the physical pages.  The alignment and boundary specified
@@ -817,7 +835,7 @@ vm_reserv_alloc_page(vm_object_t object, vm_pindex_t 
pindex, int domain,
 {
        struct vm_domain *vmd;
        vm_page_t m, msucc;
-       vm_pindex_t first, leftcap, rightcap;
+       vm_pindex_t first;
        vm_reserv_t rv;
        int index;
 
@@ -859,45 +877,12 @@ out:
        }
 
        /*
-        * Could a reservation fit between the first index to the left that
-        * can be used and the first index to the right that cannot be used?
-        *
-        * We must synchronize with the reserv object lock to protect the
-        * pindex/object of the resulting reservations against rename while
-        * we are inspecting.
+        * Check whether an allocation including reservations can fit
+        * between mpred and msucc.
         */
        first = pindex - VM_RESERV_INDEX(object, pindex);
-       vm_reserv_object_lock(object);
-       if (mpred != NULL) {
-               if ((rv = vm_reserv_from_page(mpred))->object != object)
-                       leftcap = mpred->pindex + 1;
-               else
-                       leftcap = rv->pindex + VM_LEVEL_0_NPAGES;
-               if (leftcap > first) {
-                       vm_reserv_object_unlock(object);
-                       return (NULL);
-               }
-       }
-       if (msucc != NULL) {
-               if ((rv = vm_reserv_from_page(msucc))->object != object)
-                       rightcap = msucc->pindex;
-               else
-                       rightcap = rv->pindex;
-               if (first + VM_LEVEL_0_NPAGES > rightcap) {
-                       vm_reserv_object_unlock(object);
-                       return (NULL);
-               }
-       }
-       vm_reserv_object_unlock(object);
-
-       /*
-        * Would the last new reservation extend past the end of the object?
-        *
-        * If the object is unlikely to grow don't allocate a reservation for
-        * the tail.
-        */
-       if ((object->flags & OBJ_ANON) == 0 &&
-           first + VM_LEVEL_0_NPAGES > object->size)
+       if (vm_reserv_num_alloc_pages(object, first, 1, mpred, msucc) < 
+           VM_LEVEL_0_NPAGES)
                return (NULL);
 
        /*

Reply via email to