git: 1b13e36fcc00 - main - vm_page_insert: use pctrie combined insert/lookup
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 06 Jun 2024 17:35:47 UTC
The branch main has been updated by rlibby:
URL: https://cgit.FreeBSD.org/src/commit/?id=1b13e36fcc000186045186451ab2a2fec5654fac
commit 1b13e36fcc000186045186451ab2a2fec5654fac
Author: Ryan Libby <rlibby@FreeBSD.org>
AuthorDate: 2024-06-06 17:26:50 +0000
Commit: Ryan Libby <rlibby@FreeBSD.org>
CommitDate: 2024-06-06 17:26:50 +0000
vm_page_insert: use pctrie combined insert/lookup
This reduces work done under vm_page_insert for large objects.
Reviewed by: alc, dougm, markj
Sponsored by: Dell EMC Isilon
Differential Revision: https://reviews.freebsd.org/D45486
---
sys/vm/vm_page.c | 100 ++++++++++++++++++++++++++++++++-----------------------
1 file changed, 59 insertions(+), 41 deletions(-)
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index b41439045205..4b97637668b4 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -1416,6 +1416,56 @@ vm_page_dirty_KBI(vm_page_t m)
m->dirty = VM_PAGE_BITS_ALL;
}
+/*
+ * Insert the given page into the given object at the given pindex. mpred is
+ * used for memq linkage. From vm_page_insert, lookup is true, mpred is
+ * initially NULL, and this procedure looks it up. From vm_page_insert_after,
+ * lookup is false and mpred is known to the caller to be valid, and may be
+ * NULL if this will be the page with the lowest pindex.
+ *
+ * The procedure is marked __always_inline to suggest to the compiler to
+ * eliminate the lookup parameter and the associated alternate branch.
+ */
+static __always_inline int
+vm_page_insert_lookup(vm_page_t m, vm_object_t object, vm_pindex_t pindex,
+ vm_page_t mpred, bool lookup)
+{
+ int error;
+
+ VM_OBJECT_ASSERT_WLOCKED(object);
+ KASSERT(m->object == NULL,
+ ("vm_page_insert: page %p already inserted", m));
+
+ /*
+ * Record the object/offset pair in this page.
+ */
+ m->object = object;
+ m->pindex = pindex;
+ m->ref_count |= VPRC_OBJREF;
+
+ /*
+ * Add this page to the object's radix tree, and look up mpred if
+ * needed.
+ */
+ if (lookup)
+ error = vm_radix_insert_lookup_lt(&object->rtree, m, &mpred);
+ else
+ error = vm_radix_insert(&object->rtree, m);
+ if (__predict_false(error != 0)) {
+ m->object = NULL;
+ m->pindex = 0;
+ m->ref_count &= ~VPRC_OBJREF;
+ return (1);
+ }
+
+ /*
+ * Now link into the object's ordered list of backed pages.
+ */
+ vm_page_insert_radixdone(m, object, mpred);
+ vm_pager_page_inserted(object, m);
+ return (0);
+}
+
/*
* vm_page_insert: [ internal use only ]
*
@@ -1426,11 +1476,7 @@ vm_page_dirty_KBI(vm_page_t m)
int
vm_page_insert(vm_page_t m, vm_object_t object, vm_pindex_t pindex)
{
- vm_page_t mpred;
-
- VM_OBJECT_ASSERT_WLOCKED(object);
- mpred = vm_radix_lookup_le(&object->rtree, pindex);
- return (vm_page_insert_after(m, object, pindex, mpred));
+ return (vm_page_insert_lookup(m, object, pindex, NULL, true));
}
/*
@@ -1447,42 +1493,7 @@ static int
vm_page_insert_after(vm_page_t m, vm_object_t object, vm_pindex_t pindex,
vm_page_t mpred)
{
- vm_page_t msucc;
-
- VM_OBJECT_ASSERT_WLOCKED(object);
- KASSERT(m->object == NULL,
- ("vm_page_insert_after: page already inserted"));
- if (mpred != NULL) {
- KASSERT(mpred->object == object,
- ("vm_page_insert_after: object doesn't contain mpred"));
- KASSERT(mpred->pindex < pindex,
- ("vm_page_insert_after: mpred doesn't precede pindex"));
- msucc = TAILQ_NEXT(mpred, listq);
- } else
- msucc = TAILQ_FIRST(&object->memq);
- if (msucc != NULL)
- KASSERT(msucc->pindex > pindex,
- ("vm_page_insert_after: msucc doesn't succeed pindex"));
-
- /*
- * Record the object/offset pair in this page.
- */
- m->object = object;
- m->pindex = pindex;
- m->ref_count |= VPRC_OBJREF;
-
- /*
- * Now link into the object's ordered list of backed pages.
- */
- if (vm_radix_insert(&object->rtree, m)) {
- m->object = NULL;
- m->pindex = 0;
- m->ref_count &= ~VPRC_OBJREF;
- return (1);
- }
- vm_page_insert_radixdone(m, object, mpred);
- vm_pager_page_inserted(object, m);
- return (0);
+ return (vm_page_insert_lookup(m, object, pindex, mpred, false));
}
/*
@@ -1510,6 +1521,13 @@ vm_page_insert_radixdone(vm_page_t m, vm_object_t object, vm_page_t mpred)
("vm_page_insert_radixdone: object doesn't contain mpred"));
KASSERT(mpred->pindex < m->pindex,
("vm_page_insert_radixdone: mpred doesn't precede pindex"));
+ KASSERT(TAILQ_NEXT(mpred, listq) == NULL ||
+ m->pindex < TAILQ_NEXT(mpred, listq)->pindex,
+ ("vm_page_insert_radixdone: pindex doesn't precede msucc"));
+ } else {
+ KASSERT(TAILQ_EMPTY(&object->memq) ||
+ m->pindex < TAILQ_FIRST(&object->memq)->pindex,
+ ("vm_page_insert_radixdone: no mpred but not first page"));
}
if (mpred != NULL)