git: 514c2930292e - main - vm_object: use iterators in page_collect_flush()

From: Doug Moore <dougm_at_FreeBSD.org>
Date: Thu, 17 Apr 2025 22:07:24 UTC
The branch main has been updated by dougm:

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

commit 514c2930292ec4e275ea0417ede98b8c78ea8930
Author:     Doug Moore <dougm@FreeBSD.org>
AuthorDate: 2025-04-17 22:05:30 +0000
Commit:     Doug Moore <dougm@FreeBSD.org>
CommitDate: 2025-04-17 22:05:30 +0000

    vm_object: use iterators in page_collect_flush()
    
    Implement vm_object_page_collect_flush() using iterators instead of
    vm_page_next() and vm_page_prev().
    
    Reviewed by:    kib
    Differential Revision:  https://reviews.freebsd.org/D49874
---
 sys/vm/vm_object.c | 59 ++++++++++++++++++++++++++++++------------------------
 1 file changed, 33 insertions(+), 26 deletions(-)

diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index 19e585745a80..c696408def20 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -110,8 +110,8 @@ static int old_msync;
 SYSCTL_INT(_vm, OID_AUTO, old_msync, CTLFLAG_RW, &old_msync, 0,
     "Use old (insecure) msync behavior");
 
-static int	vm_object_page_collect_flush(vm_object_t object, vm_page_t p,
-		    int pagerflags, int flags, boolean_t *allclean,
+static int	vm_object_page_collect_flush(struct pctrie_iter *pages,
+		    vm_page_t p, int pagerflags, int flags, boolean_t *allclean,
 		    boolean_t *eio);
 static boolean_t vm_object_page_remove_write(vm_page_t p, int flags,
 		    boolean_t *allclean);
@@ -1032,6 +1032,7 @@ boolean_t
 vm_object_page_clean(vm_object_t object, vm_ooffset_t start, vm_ooffset_t end,
     int flags)
 {
+	struct pctrie_iter pages;
 	vm_page_t np, p;
 	vm_pindex_t pi, tend, tstart;
 	int curgeneration, n, pagerflags;
@@ -1050,31 +1051,37 @@ vm_object_page_clean(vm_object_t object, vm_ooffset_t start, vm_ooffset_t end,
 	tend = (end == 0) ? object->size : OFF_TO_IDX(end + PAGE_MASK);
 	allclean = tstart == 0 && tend >= object->size;
 	res = TRUE;
+	vm_page_iter_init(&pages, object);
 
 rescan:
 	curgeneration = object->generation;
 
-	for (p = vm_page_find_least(object, tstart); p != NULL; p = np) {
+	for (p = vm_radix_iter_lookup_ge(&pages, tstart); p != NULL; p = np) {
 		pi = p->pindex;
 		if (pi >= tend)
 			break;
-		np = TAILQ_NEXT(p, listq);
-		if (vm_page_none_valid(p))
+		if (vm_page_none_valid(p)) {
+			np = vm_radix_iter_step(&pages);
 			continue;
-		if (vm_page_busy_acquire(p, VM_ALLOC_WAITFAIL) == 0) {
+		}
+		if (!vm_page_busy_acquire(p, VM_ALLOC_WAITFAIL)) {
 			if (object->generation != curgeneration &&
-			    (flags & OBJPC_SYNC) != 0)
+			    (flags & OBJPC_SYNC) != 0) {
+				pctrie_iter_reset(&pages);
 				goto rescan;
-			np = vm_page_find_least(object, pi);
+			}
+			np = vm_radix_iter_lookup_ge(&pages, pi);
 			continue;
 		}
 		if (!vm_object_page_remove_write(p, flags, &allclean)) {
+			np = vm_radix_iter_step(&pages);
 			vm_page_xunbusy(p);
 			continue;
 		}
 		if (object->type == OBJT_VNODE) {
-			n = vm_object_page_collect_flush(object, p, pagerflags,
+			n = vm_object_page_collect_flush(&pages, p, pagerflags,
 			    flags, &allclean, &eio);
+			pctrie_iter_reset(&pages);
 			if (eio) {
 				res = FALSE;
 				allclean = FALSE;
@@ -1103,7 +1110,7 @@ rescan:
 			n = 1;
 			vm_page_xunbusy(p);
 		}
-		np = vm_page_find_least(object, pi + n);
+		np = vm_radix_iter_lookup_ge(&pages, pi + n);
 	}
 #if 0
 	VOP_FSYNC(vp, (pagerflags & VM_PAGER_PUT_SYNC) ? MNT_WAIT : 0);
@@ -1120,37 +1127,37 @@ rescan:
 }
 
 static int
-vm_object_page_collect_flush(vm_object_t object, vm_page_t p, int pagerflags,
-    int flags, boolean_t *allclean, boolean_t *eio)
+vm_object_page_collect_flush(struct pctrie_iter *pages, vm_page_t p,
+    int pagerflags, int flags, boolean_t *allclean, boolean_t *eio)
 {
-	vm_page_t ma[2 * vm_pageout_page_count - 1], tp;
+	vm_page_t ma[2 * vm_pageout_page_count - 1];
 	int base, count, runlen;
 
 	vm_page_lock_assert(p, MA_NOTOWNED);
 	vm_page_assert_xbusied(p);
-	VM_OBJECT_ASSERT_WLOCKED(object);
 	base = nitems(ma) / 2;
 	ma[base] = p;
-	for (count = 1, tp = p; count < vm_pageout_page_count; count++) {
-		tp = vm_page_next(tp);
-		if (tp == NULL || vm_page_tryxbusy(tp) == 0)
+	for (count = 1; count < vm_pageout_page_count; count++) {
+		p = vm_radix_iter_next(pages);
+		if (p == NULL || vm_page_tryxbusy(p) == 0)
 			break;
-		if (!vm_object_page_remove_write(tp, flags, allclean)) {
-			vm_page_xunbusy(tp);
+		if (!vm_object_page_remove_write(p, flags, allclean)) {
+			vm_page_xunbusy(p);
 			break;
 		}
-		ma[base + count] = tp;
+		ma[base + count] = p;
 	}
 
-	for (tp = p; count < vm_pageout_page_count; count++) {
-		tp = vm_page_prev(tp);
-		if (tp == NULL || vm_page_tryxbusy(tp) == 0)
+	pages->index = ma[base]->pindex;
+	for (; count < vm_pageout_page_count; count++) {
+		p = vm_radix_iter_prev(pages);
+		if (p == NULL || vm_page_tryxbusy(p) == 0)
 			break;
-		if (!vm_object_page_remove_write(tp, flags, allclean)) {
-			vm_page_xunbusy(tp);
+		if (!vm_object_page_remove_write(p, flags, allclean)) {
+			vm_page_xunbusy(p);
 			break;
 		}
-		ma[--base] = tp;
+		ma[--base] = p;
 	}
 
 	vm_pageout_flush(&ma[base], count, pagerflags, nitems(ma) / 2 - base,