aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDoug Moore <dougm@FreeBSD.org>2024-06-12 03:51:40 +0000
committerDoug Moore <dougm@FreeBSD.org>2024-06-12 03:54:39 +0000
commita880104a21bf41ebbb4ead26e6d4adda32bad76c (patch)
tree07c83468d7cca91683a5bfbb1ee265ccc7aeb2d6
parente77ad954bb825983b4346b9cc646c9c910b1be24 (diff)
downloadsrc-a880104a21bf41ebbb4ead26e6d4adda32bad76c.tar.gz
src-a880104a21bf41ebbb4ead26e6d4adda32bad76c.zip
swap_pager: add new page range struct
Define a page_range struct to pair up the two values passed to freerange functions. Have swp_pager_freeswapspace also take a page_range argument rather than a pair of arguments. In swp_pager_meta_free_all, drop a needless test and use a new helper function to do the cleanup for each swap block. Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D45562
-rw-r--r--sys/vm/swap_pager.c99
1 files changed, 56 insertions, 43 deletions
diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c
index 15f227457bba..3bfda3eea169 100644
--- a/sys/vm/swap_pager.c
+++ b/sys/vm/swap_pager.c
@@ -142,6 +142,15 @@ struct swblk {
daddr_t d[SWAP_META_PAGES];
};
+/*
+ * A page_range structure records the start address and length of a sequence of
+ * mapped page addresses.
+ */
+struct page_range {
+ daddr_t start;
+ daddr_t num;
+};
+
static MALLOC_DEFINE(M_VMPGDATA, "vm_pgdata", "swap pager private data");
static struct mtx sw_dev_mtx;
static TAILQ_HEAD(, swdevt) swtailq = TAILQ_HEAD_INITIALIZER(swtailq);
@@ -471,7 +480,7 @@ static int swapoff_one(struct swdevt *sp, struct ucred *cred,
/*
* Swap bitmap functions
*/
-static void swp_pager_freeswapspace(daddr_t blk, daddr_t npages);
+static void swp_pager_freeswapspace(const struct page_range *range);
static daddr_t swp_pager_getswapspace(int *npages);
/*
@@ -486,23 +495,21 @@ static void swp_pager_meta_free_all(vm_object_t);
static daddr_t swp_pager_meta_lookup(vm_object_t, vm_pindex_t);
static void
-swp_pager_init_freerange(daddr_t *start, daddr_t *num)
+swp_pager_init_freerange(struct page_range *range)
{
-
- *start = SWAPBLK_NONE;
- *num = 0;
+ range->start = SWAPBLK_NONE;
+ range->num = 0;
}
static void
-swp_pager_update_freerange(daddr_t *start, daddr_t *num, daddr_t addr)
+swp_pager_update_freerange(struct page_range *range, daddr_t addr)
{
-
- if (*start + *num == addr) {
- (*num)++;
+ if (range->start + range->num == addr) {
+ range->num++;
} else {
- swp_pager_freeswapspace(*start, *num);
- *start = addr;
- *num = 1;
+ swp_pager_freeswapspace(range);
+ range->start = addr;
+ range->num = 1;
}
}
@@ -906,10 +913,13 @@ swp_pager_strategy(struct buf *bp)
* This routine may not sleep.
*/
static void
-swp_pager_freeswapspace(daddr_t blk, daddr_t npages)
+swp_pager_freeswapspace(const struct page_range *range)
{
+ daddr_t blk, npages;
struct swdevt *sp;
+ blk = range->start;
+ npages = range->num;
if (npages == 0)
return;
mtx_lock(&sw_dev_mtx);
@@ -1004,11 +1014,12 @@ swap_pager_freespace_pgo(vm_object_t object, vm_pindex_t start, vm_size_t size)
int
swap_pager_reserve(vm_object_t object, vm_pindex_t start, vm_pindex_t size)
{
- daddr_t addr, blk, n_free, s_free;
+ struct page_range range;
+ daddr_t addr, blk;
vm_pindex_t i, j;
int n;
- swp_pager_init_freerange(&s_free, &n_free);
+ swp_pager_init_freerange(&range);
VM_OBJECT_WLOCK(object);
for (i = 0; i < size; i += n) {
n = MIN(size - i, INT_MAX);
@@ -1022,11 +1033,10 @@ swap_pager_reserve(vm_object_t object, vm_pindex_t start, vm_pindex_t size)
addr = swp_pager_meta_build(object,
start + i + j, blk + j);
if (addr != SWAPBLK_NONE)
- swp_pager_update_freerange(&s_free, &n_free,
- addr);
+ swp_pager_update_freerange(&range, addr);
}
}
- swp_pager_freeswapspace(s_free, n_free);
+ swp_pager_freeswapspace(&range);
VM_OBJECT_WUNLOCK(object);
return (0);
}
@@ -1195,6 +1205,7 @@ swap_pager_haspage(vm_object_t object, vm_pindex_t pindex, int *before,
static void
swap_pager_unswapped(vm_page_t m)
{
+ struct page_range range;
struct swblk *sb;
vm_object_t obj;
@@ -1233,9 +1244,11 @@ swap_pager_unswapped(vm_page_t m)
rounddown(m->pindex, SWAP_META_PAGES));
if (sb == NULL)
return;
- if (sb->d[m->pindex % SWAP_META_PAGES] == SWAPBLK_NONE)
+ range.start = sb->d[m->pindex % SWAP_META_PAGES];
+ if (range.start == SWAPBLK_NONE)
return;
- swp_pager_freeswapspace(sb->d[m->pindex % SWAP_META_PAGES], 1);
+ range.num = 1;
+ swp_pager_freeswapspace(&range);
sb->d[m->pindex % SWAP_META_PAGES] = SWAPBLK_NONE;
swp_pager_free_empty_swblk(m->object, sb);
}
@@ -1480,8 +1493,9 @@ static void
swap_pager_putpages(vm_object_t object, vm_page_t *ma, int count,
int flags, int *rtvals)
{
+ struct page_range range;
struct buf *bp;
- daddr_t addr, blk, n_free, s_free;
+ daddr_t addr, blk;
vm_page_t mreq;
int i, j, n;
bool async;
@@ -1492,7 +1506,7 @@ swap_pager_putpages(vm_object_t object, vm_page_t *ma, int count,
VM_OBJECT_WUNLOCK(object);
async = curproc == pageproc && (flags & VM_PAGER_PUT_SYNC) == 0;
- swp_pager_init_freerange(&s_free, &n_free);
+ swp_pager_init_freerange(&range);
/*
* Assign swap blocks and issue I/O. We reallocate swap on the fly.
@@ -1530,8 +1544,7 @@ swap_pager_putpages(vm_object_t object, vm_page_t *ma, int count,
addr = swp_pager_meta_build(mreq->object, mreq->pindex,
blk + j);
if (addr != SWAPBLK_NONE)
- swp_pager_update_freerange(&s_free, &n_free,
- addr);
+ swp_pager_update_freerange(&range, addr);
MPASS(mreq->dirty == VM_PAGE_BITS_ALL);
mreq->oflags |= VPO_SWAPINPROG;
}
@@ -1603,7 +1616,7 @@ swap_pager_putpages(vm_object_t object, vm_page_t *ma, int count,
*/
swp_pager_async_iodone(bp);
}
- swp_pager_freeswapspace(s_free, n_free);
+ swp_pager_freeswapspace(&range);
VM_OBJECT_WLOCK(object);
}
@@ -2131,9 +2144,9 @@ static void
swp_pager_meta_transfer(vm_object_t srcobject, vm_object_t dstobject,
vm_pindex_t pindex, vm_pindex_t count, vm_size_t *moved)
{
+ struct page_range range;
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;
@@ -2146,7 +2159,7 @@ swp_pager_meta_transfer(vm_object_t srcobject, vm_object_t dstobject,
if (count == 0 || pctrie_is_empty(&srcobject->un_pager.swp.swp_blks))
goto out;
- swp_pager_init_freerange(&s_free, &n_free);
+ swp_pager_init_freerange(&range);
offset = pindex;
last = pindex + count;
for (;;) {
@@ -2163,8 +2176,7 @@ swp_pager_meta_transfer(vm_object_t srcobject, vm_object_t dstobject,
if (dstobject == NULL ||
!swp_pager_xfer_source(srcobject, dstobject,
sb->p + i - offset, sb->d[i])) {
- swp_pager_update_freerange(&s_free, &n_free,
- sb->d[i]);
+ swp_pager_update_freerange(&range, sb->d[i]);
}
if (moved != NULL) {
if (m != NULL && m->pindex != pindex + i - 1)
@@ -2184,7 +2196,7 @@ swp_pager_meta_transfer(vm_object_t srcobject, vm_object_t dstobject,
uma_zfree(swblk_zone, sb);
}
}
- swp_pager_freeswapspace(s_free, n_free);
+ swp_pager_freeswapspace(&range);
out:
if (moved != NULL)
*moved = mc;
@@ -2207,6 +2219,16 @@ swp_pager_meta_free(vm_object_t object, vm_pindex_t pindex, vm_pindex_t count,
swp_pager_meta_transfer(object, NULL, pindex, count, freed);
}
+static void
+swp_pager_meta_free_block(struct swblk *sb, struct page_range *range)
+{
+ for (int i = 0; i < SWAP_META_PAGES; i++) {
+ if (sb->d[i] != SWAPBLK_NONE)
+ swp_pager_update_freerange(range, sb->d[i]);
+ }
+ uma_zfree(swblk_zone, sb);
+}
+
/*
* SWP_PAGER_META_FREE_ALL() - destroy all swap metadata associated with object
*
@@ -2217,28 +2239,19 @@ static void
swp_pager_meta_free_all(vm_object_t object)
{
struct swblk *sb;
- daddr_t n_free, s_free;
+ struct page_range range;
vm_pindex_t pindex;
- int i;
VM_OBJECT_ASSERT_WLOCKED(object);
- if (pctrie_is_empty(&object->un_pager.swp.swp_blks))
- return;
-
- swp_pager_init_freerange(&s_free, &n_free);
+ swp_pager_init_freerange(&range);
for (pindex = 0; (sb = SWAP_PCTRIE_LOOKUP_GE(
&object->un_pager.swp.swp_blks, pindex)) != NULL;) {
pindex = sb->p + SWAP_META_PAGES;
- for (i = 0; i < SWAP_META_PAGES; i++) {
- if (sb->d[i] == SWAPBLK_NONE)
- continue;
- swp_pager_update_freerange(&s_free, &n_free, sb->d[i]);
- }
SWAP_PCTRIE_REMOVE(&object->un_pager.swp.swp_blks, sb->p);
- uma_zfree(swblk_zone, sb);
+ swp_pager_meta_free_block(sb, &range);
}
- swp_pager_freeswapspace(s_free, n_free);
+ swp_pager_freeswapspace(&range);
}
/*