git: db08b0b04dec - main - tmpfs_vnops: move swap work to swap_pager

From: Doug Moore <dougm_at_FreeBSD.org>
Date: Thu, 24 Oct 2024 19:26:05 UTC
The branch main has been updated by dougm:

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

commit db08b0b04deced766c3b5f07bcfb82333666226c
Author:     Doug Moore <dougm@FreeBSD.org>
AuthorDate: 2024-10-24 19:24:49 +0000
Commit:     Doug Moore <dougm@FreeBSD.org>
CommitDate: 2024-10-24 19:24:49 +0000

    tmpfs_vnops: move swap work to swap_pager
    
    Two functions in tmpfs_vnops.c use an interface provided by
    swap_pager.c. Move most of the implementation of those functions to
    swap_pager.c so that they can be implemented more effectively, with
    access to implementation details of the swap pager.
    
    Reviewed by:    kib
    Differential Revision:  https://reviews.freebsd.org/D47212
---
 sys/fs/tmpfs/tmpfs_vnops.c | 60 ++++------------------------------------------
 sys/vm/swap_pager.c        | 58 +++++++++++++++++++++++++++++++++++++++-----
 sys/vm/swap_pager.h        |  3 ++-
 3 files changed, 58 insertions(+), 63 deletions(-)

diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c
index c2559a61fe37..428c31f3c59a 100644
--- a/sys/fs/tmpfs/tmpfs_vnops.c
+++ b/sys/fs/tmpfs/tmpfs_vnops.c
@@ -2092,40 +2092,10 @@ tmpfs_setextattr(struct vop_setextattr_args *ap)
 static off_t
 tmpfs_seek_data_locked(vm_object_t obj, off_t noff)
 {
-	vm_page_t m;
-	vm_pindex_t p, p_swp;
+	vm_pindex_t p;
 
-	p = OFF_TO_IDX(noff);
-	m = vm_page_find_least(obj, p);
-
-	/*
-	 * Microoptimize the most common case for SEEK_DATA, where
-	 * there is no hole and the page is resident.
-	 */
-	if (m != NULL && m->pindex == p && vm_page_any_valid(m))
-		return (noff);
-
-	p_swp = swap_pager_find_least(obj, p);
-	if (p_swp == p)
-		return (noff);
-
-	/*
-	 * Find the first resident page after p, before p_swp.
-	 */
-	while (m != NULL && m->pindex < p_swp) {
-		if (vm_page_any_valid(m))
-			return (IDX_TO_OFF(m->pindex));
-		m = TAILQ_NEXT(m, listq);
-	}
-	if (p_swp == OBJ_MAX_SIZE)
-		p_swp = obj->size;
-	return (IDX_TO_OFF(p_swp));
-}
-
-static off_t
-tmpfs_seek_next(off_t noff)
-{
-	return (noff + PAGE_SIZE - (noff & PAGE_MASK));
+	p = swap_pager_seek_data(obj, OFF_TO_IDX(noff));
+	return (p == OFF_TO_IDX(noff) ? noff : IDX_TO_OFF(p));
 }
 
 static int
@@ -2142,30 +2112,8 @@ tmpfs_seek_clamp(struct tmpfs_node *tn, off_t *noff, bool seekdata)
 static off_t
 tmpfs_seek_hole_locked(vm_object_t obj, off_t noff)
 {
-	vm_page_t m;
-	vm_pindex_t p, p_swp;
-
-	for (;; noff = tmpfs_seek_next(noff)) {
-		/*
-		 * Walk over the largest sequential run of the valid pages.
-		 */
-		for (m = vm_page_lookup(obj, OFF_TO_IDX(noff));
-		    m != NULL && vm_page_any_valid(m);
-		    m = vm_page_next(m), noff = tmpfs_seek_next(noff))
-			;
 
-		/*
-		 * Found a hole in the object's page queue.  Check if
-		 * there is a hole in the swap at the same place.
-		 */
-		p = OFF_TO_IDX(noff);
-		p_swp = swap_pager_find_least(obj, p);
-		if (p_swp != p) {
-			noff = IDX_TO_OFF(p);
-			break;
-		}
-	}
-	return (noff);
+	return (IDX_TO_OFF(swap_pager_seek_hole(obj, OFF_TO_IDX(noff))));
 }
 
 static int
diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c
index 5eccc621bdae..90d44d3e7402 100644
--- a/sys/vm/swap_pager.c
+++ b/sys/vm/swap_pager.c
@@ -111,6 +111,7 @@
 #include <vm/vm_pager.h>
 #include <vm/vm_pageout.h>
 #include <vm/vm_param.h>
+#include <vm/vm_radix.h>
 #include <vm/swap_pager.h>
 #include <vm/vm_extern.h>
 #include <vm/uma.h>
@@ -2476,17 +2477,62 @@ swap_pager_iter_find_least(struct pctrie_iter *blks, vm_pindex_t pindex)
 }
 
 /*
- * Returns the least page index which is greater than or equal to the parameter
- * pindex and for which there is a swap block allocated.  Returns OBJ_MAX_SIZE
- * if are no allocated swap blocks for the object after the requested pindex.
+ * Find the first index >= pindex that has either a valid page or a swap
+ * block.
  */
 vm_pindex_t
-swap_pager_find_least(vm_object_t object, vm_pindex_t pindex)
+swap_pager_seek_data(vm_object_t object, vm_pindex_t pindex)
 {
-	struct pctrie_iter blks;
+	struct pctrie_iter blks, pages;
+	vm_page_t m;
+	vm_pindex_t swap_index;
+
+	VM_OBJECT_ASSERT_WLOCKED(object);
+	vm_page_iter_init(&pages, object);
+	m = vm_page_iter_lookup_ge(&pages, pindex);
+	if (m != NULL) {
+		if (!vm_page_any_valid(m))
+			m = NULL;
+		else if (pages.index == pindex)
+			return (pages.index);
+	}
+	swblk_iter_init_only(&blks, object);
+	swap_index = swap_pager_iter_find_least(&blks, pindex);
+	if (swap_index == pindex)
+		return (swap_index);
+	if (swap_index == OBJ_MAX_SIZE)
+		swap_index = object->size;
+	if (m == NULL)
+		return (swap_index);
+
+	while ((m = vm_radix_iter_step(&pages)) != NULL &&
+	    pages.index < swap_index) {
+		if (vm_page_any_valid(m))
+			return (pages.index);
+	}
+	return (swap_index);
+}
+
+/*
+ * Find the first index >= pindex that has neither a valid page nor a swap
+ * block.
+ */
+vm_pindex_t
+swap_pager_seek_hole(vm_object_t object, vm_pindex_t pindex)
+{
+	struct pctrie_iter blks, pages;
+	struct swblk *sb;
+	vm_page_t m;
 
+	VM_OBJECT_ASSERT_WLOCKED(object);
+	vm_page_iter_init(&pages, object);
 	swblk_iter_init_only(&blks, object);
-	return (swap_pager_iter_find_least(&blks, pindex));
+	while (((m = vm_page_iter_lookup(&pages, pindex)) != NULL &&
+	    vm_page_any_valid(m)) ||
+	    ((sb = swblk_iter_lookup(&blks, pindex)) != NULL &&
+	    sb->d[pindex % SWAP_META_PAGES] != SWAPBLK_NONE))
+		pindex++;
+	return (pindex);
 }
 
 /*
diff --git a/sys/vm/swap_pager.h b/sys/vm/swap_pager.h
index ade94802b963..3287886026f7 100644
--- a/sys/vm/swap_pager.h
+++ b/sys/vm/swap_pager.h
@@ -74,8 +74,9 @@ extern int nsw_cluster_max;
 struct xswdev;
 int swap_dev_info(int name, struct xswdev *xs, char *devname, size_t len);
 void swap_pager_copy(vm_object_t, vm_object_t, vm_pindex_t, int);
-vm_pindex_t swap_pager_find_least(vm_object_t object, vm_pindex_t pindex);
 bool swap_pager_scan_all_shadowed(vm_object_t object);
+vm_pindex_t swap_pager_seek_data(vm_object_t object, vm_pindex_t pindex);
+vm_pindex_t swap_pager_seek_hole(vm_object_t object, vm_pindex_t pindex);
 void swap_pager_freespace(vm_object_t object, vm_pindex_t start,
     vm_size_t size, vm_size_t *freed);
 void swap_pager_swap_init(void);