Previously, swap_pager_copy() freed swap blocks one at at time, via
swp_pager_meta_ctl(), with no opportunity to recognize freeing of consecutive blocks and free fewer block ranges. To open that opportunity, this change removes the SWM_FREE option from swp_pager_meta_ctl(), and compels the caller to do the freeing when a valid block address is returned. In swap_pager_copy(), these frees are aggregated, so that a sequence of them can be done at one time. The only other caller to swp_pager_meta_ctl() that passed SWM_FREE, swp_pager_unswapped(), is also modified to handle its single free explicitly. Submitted by: Doug Moore <dougm@rice.edu> Reviewed by: kib (an earlier version) MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D13290
This commit is contained in:
parent
0879ca728a
commit
4abca9bb05
@ -311,8 +311,7 @@ swap_release_by_cred(vm_ooffset_t decr, struct ucred *cred)
|
||||
racct_sub_cred(cred, RACCT_SWAP, decr);
|
||||
}
|
||||
|
||||
#define SWM_FREE 0x02 /* free, period */
|
||||
#define SWM_POP 0x04 /* pop out */
|
||||
#define SWM_POP 0x01 /* pop out */
|
||||
|
||||
static int swap_pager_full = 2; /* swap space exhaustion (task killing) */
|
||||
static int swap_pager_almost_full = 1; /* swap space exhaustion (w/hysteresis)*/
|
||||
@ -911,6 +910,7 @@ swap_pager_copy(vm_object_t srcobject, vm_object_t dstobject,
|
||||
vm_pindex_t offset, int destroysource)
|
||||
{
|
||||
vm_pindex_t i;
|
||||
daddr_t dstaddr, first_free, num_free, srcaddr;
|
||||
|
||||
VM_OBJECT_ASSERT_WLOCKED(srcobject);
|
||||
VM_OBJECT_ASSERT_WLOCKED(dstobject);
|
||||
@ -935,53 +935,44 @@ swap_pager_copy(vm_object_t srcobject, vm_object_t dstobject,
|
||||
}
|
||||
|
||||
/*
|
||||
* transfer source to destination.
|
||||
* Transfer source to destination.
|
||||
*/
|
||||
first_free = SWAPBLK_NONE;
|
||||
num_free = 0;
|
||||
for (i = 0; i < dstobject->size; ++i) {
|
||||
daddr_t dstaddr;
|
||||
|
||||
/*
|
||||
* Locate (without changing) the swapblk on the destination,
|
||||
* unless it is invalid in which case free it silently, or
|
||||
* if the destination is a resident page, in which case the
|
||||
* source is thrown away.
|
||||
*/
|
||||
srcaddr = swp_pager_meta_ctl(srcobject, i + offset, SWM_POP);
|
||||
if (srcaddr == SWAPBLK_NONE)
|
||||
continue;
|
||||
dstaddr = swp_pager_meta_ctl(dstobject, i, 0);
|
||||
|
||||
if (dstaddr == SWAPBLK_NONE) {
|
||||
/*
|
||||
* Destination has no swapblk and is not resident,
|
||||
* copy source.
|
||||
*
|
||||
* swp_pager_meta_build() can sleep.
|
||||
*/
|
||||
daddr_t srcaddr;
|
||||
|
||||
srcaddr = swp_pager_meta_ctl(
|
||||
srcobject,
|
||||
i + offset,
|
||||
SWM_POP
|
||||
);
|
||||
|
||||
if (srcaddr != SWAPBLK_NONE) {
|
||||
/*
|
||||
* swp_pager_meta_build() can sleep.
|
||||
*/
|
||||
vm_object_pip_add(srcobject, 1);
|
||||
VM_OBJECT_WUNLOCK(srcobject);
|
||||
vm_object_pip_add(dstobject, 1);
|
||||
swp_pager_meta_build(dstobject, i, srcaddr);
|
||||
vm_object_pip_wakeup(dstobject);
|
||||
VM_OBJECT_WLOCK(srcobject);
|
||||
vm_object_pip_wakeup(srcobject);
|
||||
}
|
||||
vm_object_pip_add(srcobject, 1);
|
||||
VM_OBJECT_WUNLOCK(srcobject);
|
||||
vm_object_pip_add(dstobject, 1);
|
||||
swp_pager_meta_build(dstobject, i, srcaddr);
|
||||
vm_object_pip_wakeup(dstobject);
|
||||
VM_OBJECT_WLOCK(srcobject);
|
||||
vm_object_pip_wakeup(srcobject);
|
||||
} else {
|
||||
/*
|
||||
* Destination has valid swapblk or it is represented
|
||||
* by a resident page. We destroy the sourceblock.
|
||||
*/
|
||||
|
||||
swp_pager_meta_ctl(srcobject, i + offset, SWM_FREE);
|
||||
if (first_free + num_free == srcaddr)
|
||||
num_free++;
|
||||
else {
|
||||
swp_pager_freeswapspace(first_free, num_free);
|
||||
first_free = srcaddr;
|
||||
num_free = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
swp_pager_freeswapspace(first_free, num_free);
|
||||
|
||||
/*
|
||||
* Free left over swap blocks in source.
|
||||
@ -1082,8 +1073,11 @@ swap_pager_haspage(vm_object_t object, vm_pindex_t pindex, int *before,
|
||||
static void
|
||||
swap_pager_unswapped(vm_page_t m)
|
||||
{
|
||||
daddr_t srcaddr;
|
||||
|
||||
swp_pager_meta_ctl(m->object, m->pindex, SWM_FREE);
|
||||
srcaddr = swp_pager_meta_ctl(m->object, m->pindex, SWM_POP);
|
||||
if (srcaddr != SWAPBLK_NONE)
|
||||
swp_pager_freeswapspace(srcaddr, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1999,21 +1993,17 @@ swp_pager_meta_free_all(vm_object_t object)
|
||||
}
|
||||
|
||||
/*
|
||||
* SWP_PAGER_METACTL() - misc control of swap and vm_page_t meta data.
|
||||
* SWP_PAGER_METACTL() - misc control of swap meta data.
|
||||
*
|
||||
* This routine is capable of looking up, popping, or freeing
|
||||
* swapblk assignments in the swap meta data or in the vm_page_t.
|
||||
* The routine typically returns the swapblk being looked-up, or popped,
|
||||
* or SWAPBLK_NONE if the block was freed, or SWAPBLK_NONE if the block
|
||||
* was invalid. This routine will automatically free any invalid
|
||||
* meta-data swapblks.
|
||||
* This routine is capable of looking up, or removing swapblk
|
||||
* assignments in the swap meta data. It returns the swapblk being
|
||||
* looked-up, popped, or SWAPBLK_NONE if the block was invalid.
|
||||
*
|
||||
* When acting on a busy resident page and paging is in progress, we
|
||||
* have to wait until paging is complete but otherwise can act on the
|
||||
* busy page.
|
||||
*
|
||||
* SWM_FREE remove and free swap block from metadata
|
||||
* SWM_POP remove from meta data but do not free.. pop it out
|
||||
* SWM_POP remove from meta data but do not free it
|
||||
*/
|
||||
static daddr_t
|
||||
swp_pager_meta_ctl(vm_object_t object, vm_pindex_t pindex, int flags)
|
||||
@ -2021,7 +2011,7 @@ swp_pager_meta_ctl(vm_object_t object, vm_pindex_t pindex, int flags)
|
||||
struct swblk *sb;
|
||||
daddr_t r1;
|
||||
|
||||
if ((flags & (SWM_FREE | SWM_POP)) != 0)
|
||||
if ((flags & SWM_POP) != 0)
|
||||
VM_OBJECT_ASSERT_WLOCKED(object);
|
||||
else
|
||||
VM_OBJECT_ASSERT_LOCKED(object);
|
||||
@ -2040,7 +2030,7 @@ swp_pager_meta_ctl(vm_object_t object, vm_pindex_t pindex, int flags)
|
||||
r1 = sb->d[pindex % SWAP_META_PAGES];
|
||||
if (r1 == SWAPBLK_NONE)
|
||||
return (SWAPBLK_NONE);
|
||||
if ((flags & (SWM_FREE | SWM_POP)) != 0) {
|
||||
if ((flags & SWM_POP) != 0) {
|
||||
sb->d[pindex % SWAP_META_PAGES] = SWAPBLK_NONE;
|
||||
if (swp_pager_swblk_empty(sb, 0, SWAP_META_PAGES)) {
|
||||
SWAP_PCTRIE_REMOVE(&object->un_pager.swp.swp_blks,
|
||||
@ -2048,10 +2038,6 @@ swp_pager_meta_ctl(vm_object_t object, vm_pindex_t pindex, int flags)
|
||||
uma_zfree(swblk_zone, sb);
|
||||
}
|
||||
}
|
||||
if ((flags & SWM_FREE) != 0) {
|
||||
swp_pager_freeswapspace(r1, 1);
|
||||
r1 = SWAPBLK_NONE;
|
||||
}
|
||||
return (r1);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user