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
This commit is contained in:
Doug Moore 2024-10-24 14:24:49 -05:00
parent d021d3b3c6
commit db08b0b04d
3 changed files with 58 additions and 63 deletions

View file

@ -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

View file

@ -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);
return (swap_pager_iter_find_least(&blks, pindex));
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);
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);
}
/*

View file

@ -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);