Make swap_pager_freespace() global

also make it return the count of the swap pages freed, which are not
simultaneously resident in the object.

Reviewed by:	markj
Tested by:	pho
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D37097
This commit is contained in:
Konstantin Belousov 2022-10-27 01:13:27 +03:00
parent 83aff0f08c
commit baa1ccceef
2 changed files with 45 additions and 13 deletions

View File

@ -436,7 +436,7 @@ static void swap_pager_update_writecount(vm_object_t object,
vm_offset_t start, vm_offset_t end);
static void swap_pager_release_writecount(vm_object_t object,
vm_offset_t start, vm_offset_t end);
static void swap_pager_freespace(vm_object_t object, vm_pindex_t start,
static void swap_pager_freespace_pgo(vm_object_t object, vm_pindex_t start,
vm_size_t size);
const struct pagerops swappagerops = {
@ -451,7 +451,7 @@ const struct pagerops swappagerops = {
.pgo_pageunswapped = swap_pager_unswapped, /* remove swap related to page */
.pgo_update_writecount = swap_pager_update_writecount,
.pgo_release_writecount = swap_pager_release_writecount,
.pgo_freespace = swap_pager_freespace,
.pgo_freespace = swap_pager_freespace_pgo,
};
/*
@ -483,9 +483,10 @@ static daddr_t swp_pager_getswapspace(int *npages);
* Metadata functions
*/
static daddr_t swp_pager_meta_build(vm_object_t, vm_pindex_t, daddr_t);
static void swp_pager_meta_free(vm_object_t, vm_pindex_t, vm_pindex_t);
static void swp_pager_meta_free(vm_object_t, vm_pindex_t, vm_size_t,
vm_size_t *);
static void swp_pager_meta_transfer(vm_object_t src, vm_object_t dst,
vm_pindex_t pindex, vm_pindex_t count);
vm_pindex_t pindex, vm_pindex_t count, vm_size_t *freed);
static void swp_pager_meta_free_all(vm_object_t);
static daddr_t swp_pager_meta_lookup(vm_object_t, vm_pindex_t);
@ -980,11 +981,21 @@ sysctl_swap_fragmentation(SYSCTL_HANDLER_ARGS)
*
* The object must be locked.
*/
static void
swap_pager_freespace(vm_object_t object, vm_pindex_t start, vm_size_t size)
void
swap_pager_freespace(vm_object_t object, vm_pindex_t start, vm_size_t size,
vm_size_t *freed)
{
MPASS((object->flags & OBJ_SWAP) != 0);
swp_pager_meta_free(object, start, size);
swp_pager_meta_free(object, start, size, freed);
}
static void
swap_pager_freespace_pgo(vm_object_t object, vm_pindex_t start, vm_size_t size)
{
MPASS((object->flags & OBJ_SWAP) != 0);
swp_pager_meta_free(object, start, size, NULL);
}
/*
@ -1008,7 +1019,7 @@ swap_pager_reserve(vm_object_t object, vm_pindex_t start, vm_pindex_t size)
n = MIN(size - i, INT_MAX);
blk = swp_pager_getswapspace(&n);
if (blk == SWAPBLK_NONE) {
swp_pager_meta_free(object, start, i);
swp_pager_meta_free(object, start, i, NULL);
VM_OBJECT_WUNLOCK(object);
return (-1);
}
@ -1096,7 +1107,8 @@ swap_pager_copy(vm_object_t srcobject, vm_object_t dstobject,
/*
* Transfer source to destination.
*/
swp_pager_meta_transfer(srcobject, dstobject, offset, dstobject->size);
swp_pager_meta_transfer(srcobject, dstobject, offset, dstobject->size,
NULL);
/*
* Free left over swap blocks in source.
@ -2119,16 +2131,22 @@ swp_pager_meta_build(vm_object_t object, vm_pindex_t pindex, daddr_t swapblk)
*/
static void
swp_pager_meta_transfer(vm_object_t srcobject, vm_object_t dstobject,
vm_pindex_t pindex, vm_pindex_t count)
vm_pindex_t pindex, vm_pindex_t count, vm_size_t *moved)
{
struct swblk *sb;
vm_page_t m;
daddr_t n_free, s_free;
vm_pindex_t offset, last;
vm_size_t mc;
int i, limit, start;
VM_OBJECT_ASSERT_WLOCKED(srcobject);
MPASS(moved == NULL || dstobject == NULL);
mc = 0;
m = NULL;
if (count == 0 || pctrie_is_empty(&srcobject->un_pager.swp.swp_blks))
return;
goto out;
swp_pager_init_freerange(&s_free, &n_free);
offset = pindex;
@ -2150,6 +2168,14 @@ swp_pager_meta_transfer(vm_object_t srcobject, vm_object_t dstobject,
swp_pager_update_freerange(&s_free, &n_free,
sb->d[i]);
}
if (moved != NULL) {
if (m != NULL && m->pindex != pindex + i - 1)
m = NULL;
m = m != NULL ? vm_page_next(m) :
vm_page_lookup(srcobject, pindex + i);
if (m == NULL || vm_page_none_valid(m))
mc++;
}
sb->d[i] = SWAPBLK_NONE;
}
pindex = sb->p + SWAP_META_PAGES;
@ -2161,6 +2187,9 @@ swp_pager_meta_transfer(vm_object_t srcobject, vm_object_t dstobject,
}
}
swp_pager_freeswapspace(s_free, n_free);
out:
if (moved != NULL)
*moved = mc;
}
/*
@ -2174,9 +2203,10 @@ swp_pager_meta_transfer(vm_object_t srcobject, vm_object_t dstobject,
* with resident pages.
*/
static void
swp_pager_meta_free(vm_object_t object, vm_pindex_t pindex, vm_pindex_t count)
swp_pager_meta_free(vm_object_t object, vm_pindex_t pindex, vm_pindex_t count,
vm_size_t *freed)
{
swp_pager_meta_transfer(object, NULL, pindex, count);
swp_pager_meta_transfer(object, NULL, pindex, count, freed);
}
/*

View File

@ -78,6 +78,8 @@ 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);
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);
int swap_pager_nswapdev(void);
int swap_pager_reserve(vm_object_t, vm_pindex_t, vm_pindex_t);