mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-06 16:40:47 +00:00
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
This commit is contained in:
parent
e77ad954bb
commit
a880104a21
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue