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)