git: db08b0b04dec - main - tmpfs_vnops: move swap work to swap_pager
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
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);