Callers of swp_pager_getswapspace get either as many blocks as they
requested, or none, and in the latter case it is up to them to pick a smaller request to make - which they always do by halving the failed request. This change to swp_pager_getswapspace leaves the task of downsizing the request to the function and not its caller. It still does so by halving the original request. Approved by: kib (mentor) Differential Revision: https://reviews.freebsd.org/D20228
This commit is contained in:
parent
535192530c
commit
48e98a2afc
@ -407,7 +407,7 @@ static int swapoff_one(struct swdevt *sp, struct ucred *cred);
|
|||||||
* Swap bitmap functions
|
* Swap bitmap functions
|
||||||
*/
|
*/
|
||||||
static void swp_pager_freeswapspace(daddr_t blk, daddr_t npages);
|
static void swp_pager_freeswapspace(daddr_t blk, daddr_t npages);
|
||||||
static daddr_t swp_pager_getswapspace(int npages);
|
static daddr_t swp_pager_getswapspace(int *npages, int limit);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Metadata functions
|
* Metadata functions
|
||||||
@ -708,9 +708,10 @@ swap_pager_dealloc(vm_object_t object)
|
|||||||
/*
|
/*
|
||||||
* SWP_PAGER_GETSWAPSPACE() - allocate raw swap space
|
* SWP_PAGER_GETSWAPSPACE() - allocate raw swap space
|
||||||
*
|
*
|
||||||
* Allocate swap for the requested number of pages. The starting
|
* Allocate swap for up to the requested number of pages, and at
|
||||||
* swap block number (a page index) is returned or SWAPBLK_NONE
|
* least a minimum number of pages. The starting swap block number
|
||||||
* if the allocation failed.
|
* (a page index) is returned or SWAPBLK_NONE if the allocation
|
||||||
|
* failed.
|
||||||
*
|
*
|
||||||
* Also has the side effect of advising that somebody made a mistake
|
* Also has the side effect of advising that somebody made a mistake
|
||||||
* when they configured swap and didn't configure enough.
|
* when they configured swap and didn't configure enough.
|
||||||
@ -720,38 +721,46 @@ swap_pager_dealloc(vm_object_t object)
|
|||||||
* We allocate in round-robin fashion from the configured devices.
|
* We allocate in round-robin fashion from the configured devices.
|
||||||
*/
|
*/
|
||||||
static daddr_t
|
static daddr_t
|
||||||
swp_pager_getswapspace(int npages)
|
swp_pager_getswapspace(int *io_npages, int limit)
|
||||||
{
|
{
|
||||||
daddr_t blk;
|
daddr_t blk;
|
||||||
struct swdevt *sp;
|
struct swdevt *sp;
|
||||||
int i;
|
int npages;
|
||||||
|
|
||||||
blk = SWAPBLK_NONE;
|
blk = SWAPBLK_NONE;
|
||||||
|
npages = *io_npages;
|
||||||
mtx_lock(&sw_dev_mtx);
|
mtx_lock(&sw_dev_mtx);
|
||||||
sp = swdevhd;
|
sp = swdevhd;
|
||||||
for (i = 0; i < nswapdev; i++) {
|
while (!TAILQ_EMPTY(&swtailq)) {
|
||||||
if (sp == NULL)
|
if (sp == NULL)
|
||||||
sp = TAILQ_FIRST(&swtailq);
|
sp = TAILQ_FIRST(&swtailq);
|
||||||
if (!(sp->sw_flags & SW_CLOSING)) {
|
if ((sp->sw_flags & SW_CLOSING) == 0)
|
||||||
blk = blist_alloc(sp->sw_blist, npages);
|
blk = blist_alloc(sp->sw_blist, npages);
|
||||||
if (blk != SWAPBLK_NONE) {
|
if (blk != SWAPBLK_NONE)
|
||||||
blk += sp->sw_first;
|
break;
|
||||||
sp->sw_used += npages;
|
|
||||||
swap_pager_avail -= npages;
|
|
||||||
swp_sizecheck();
|
|
||||||
swdevhd = TAILQ_NEXT(sp, sw_list);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sp = TAILQ_NEXT(sp, sw_list);
|
sp = TAILQ_NEXT(sp, sw_list);
|
||||||
|
if (swdevhd == sp) {
|
||||||
|
if (npages <= limit)
|
||||||
|
break;
|
||||||
|
npages >>= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (swap_pager_full != 2) {
|
if (blk != SWAPBLK_NONE) {
|
||||||
printf("swap_pager_getswapspace(%d): failed\n", npages);
|
*io_npages = npages;
|
||||||
swap_pager_full = 2;
|
blk += sp->sw_first;
|
||||||
swap_pager_almost_full = 1;
|
sp->sw_used += npages;
|
||||||
|
swap_pager_avail -= npages;
|
||||||
|
swp_sizecheck();
|
||||||
|
swdevhd = TAILQ_NEXT(sp, sw_list);
|
||||||
|
} else {
|
||||||
|
if (swap_pager_full != 2) {
|
||||||
|
printf("swp_pager_getswapspace(%d): failed\n",
|
||||||
|
*io_npages);
|
||||||
|
swap_pager_full = 2;
|
||||||
|
swap_pager_almost_full = 1;
|
||||||
|
}
|
||||||
|
swdevhd = NULL;
|
||||||
}
|
}
|
||||||
swdevhd = NULL;
|
|
||||||
done:
|
|
||||||
mtx_unlock(&sw_dev_mtx);
|
mtx_unlock(&sw_dev_mtx);
|
||||||
return (blk);
|
return (blk);
|
||||||
}
|
}
|
||||||
@ -886,35 +895,28 @@ swap_pager_freespace(vm_object_t object, vm_pindex_t start, vm_size_t size)
|
|||||||
int
|
int
|
||||||
swap_pager_reserve(vm_object_t object, vm_pindex_t start, vm_size_t size)
|
swap_pager_reserve(vm_object_t object, vm_pindex_t start, vm_size_t size)
|
||||||
{
|
{
|
||||||
int n = 0;
|
daddr_t addr, blk, n_free, s_free;
|
||||||
daddr_t blk = SWAPBLK_NONE;
|
int i, j, n;
|
||||||
vm_pindex_t beg = start; /* save start index */
|
|
||||||
daddr_t addr, n_free, s_free;
|
|
||||||
|
|
||||||
swp_pager_init_freerange(&s_free, &n_free);
|
swp_pager_init_freerange(&s_free, &n_free);
|
||||||
VM_OBJECT_WLOCK(object);
|
VM_OBJECT_WLOCK(object);
|
||||||
while (size) {
|
for (i = 0; i < size; i += n) {
|
||||||
if (n == 0) {
|
n = min(BLIST_MAX_ALLOC, size - i);
|
||||||
n = BLIST_MAX_ALLOC;
|
blk = swp_pager_getswapspace(&n, 1);
|
||||||
while ((blk = swp_pager_getswapspace(n)) == SWAPBLK_NONE) {
|
if (blk == SWAPBLK_NONE) {
|
||||||
n >>= 1;
|
swp_pager_meta_free(object, start, i);
|
||||||
if (n == 0) {
|
VM_OBJECT_WUNLOCK(object);
|
||||||
swp_pager_meta_free(object, beg, start - beg);
|
return (-1);
|
||||||
VM_OBJECT_WUNLOCK(object);
|
}
|
||||||
return (-1);
|
for (j = 0; j < n; ++j) {
|
||||||
}
|
addr = swp_pager_meta_build(object,
|
||||||
}
|
start + i + j, blk + j);
|
||||||
|
if (addr != SWAPBLK_NONE)
|
||||||
|
swp_pager_update_freerange(&s_free, &n_free,
|
||||||
|
addr);
|
||||||
}
|
}
|
||||||
addr = swp_pager_meta_build(object, start, blk);
|
|
||||||
if (addr != SWAPBLK_NONE)
|
|
||||||
swp_pager_update_freerange(&s_free, &n_free, addr);
|
|
||||||
--size;
|
|
||||||
++start;
|
|
||||||
++blk;
|
|
||||||
--n;
|
|
||||||
}
|
}
|
||||||
swp_pager_freeswapspace(s_free, n_free);
|
swp_pager_freeswapspace(s_free, n_free);
|
||||||
swp_pager_meta_free(object, start, n);
|
|
||||||
VM_OBJECT_WUNLOCK(object);
|
VM_OBJECT_WUNLOCK(object);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@ -1384,18 +1386,8 @@ swap_pager_putpages(vm_object_t object, vm_page_t *ma, int count,
|
|||||||
n = min(BLIST_MAX_ALLOC, count - i);
|
n = min(BLIST_MAX_ALLOC, count - i);
|
||||||
n = min(n, nsw_cluster_max);
|
n = min(n, nsw_cluster_max);
|
||||||
|
|
||||||
/*
|
/* Get a block of swap of size up to size n. */
|
||||||
* Get biggest block of swap we can. If we fail, fall
|
blk = swp_pager_getswapspace(&n, 4);
|
||||||
* back and try to allocate a smaller block. Don't go
|
|
||||||
* overboard trying to allocate space if it would overly
|
|
||||||
* fragment swap.
|
|
||||||
*/
|
|
||||||
while (
|
|
||||||
(blk = swp_pager_getswapspace(n)) == SWAPBLK_NONE &&
|
|
||||||
n > 4
|
|
||||||
) {
|
|
||||||
n >>= 1;
|
|
||||||
}
|
|
||||||
if (blk == SWAPBLK_NONE) {
|
if (blk == SWAPBLK_NONE) {
|
||||||
for (j = 0; j < n; ++j)
|
for (j = 0; j < n; ++j)
|
||||||
rtvals[i+j] = VM_PAGER_FAIL;
|
rtvals[i+j] = VM_PAGER_FAIL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user