Update the checks in vm_page_zone_import().
- Remove the cnt == 1 check. UMA passes cnt == 1 when it has disabled per-CPU caching. In this case we might as well just allocate a single page and return it to the caller, since the caller is going to do exactly that anyway if the UMA cache allocation attempt fails. - Don't replenish caches if the domain is severely short on free pages. With large buckets we may otherwise quickly exacerbate a situation where the page daemon is failing to keep up. - Don't replenish caches if the calling thread belongs to the page daemon, which should avoid creating extra memory pressure when it is trying to free memory. Virtually all such allocations while occur in the context of laundering, where the laundry thread must allocate slabs for various swap and I/O-related UMA zones. Reviewed by: kib Discussed with: alc, jeff MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D22394
This commit is contained in:
parent
58afbd3942
commit
e25228e838
@ -1829,21 +1829,14 @@ vm_page_alloc_after(vm_object_t object, vm_pindex_t pindex,
|
|||||||
* Returns true if the number of free pages exceeds the minimum
|
* Returns true if the number of free pages exceeds the minimum
|
||||||
* for the request class and false otherwise.
|
* for the request class and false otherwise.
|
||||||
*/
|
*/
|
||||||
int
|
static int
|
||||||
vm_domain_allocate(struct vm_domain *vmd, int req, int npages)
|
_vm_domain_allocate(struct vm_domain *vmd, int req_class, int npages)
|
||||||
{
|
{
|
||||||
u_int limit, old, new;
|
u_int limit, old, new;
|
||||||
|
|
||||||
req = req & VM_ALLOC_CLASS_MASK;
|
if (req_class == VM_ALLOC_INTERRUPT)
|
||||||
|
|
||||||
/*
|
|
||||||
* The page daemon is allowed to dig deeper into the free page list.
|
|
||||||
*/
|
|
||||||
if (curproc == pageproc && req != VM_ALLOC_INTERRUPT)
|
|
||||||
req = VM_ALLOC_SYSTEM;
|
|
||||||
if (req == VM_ALLOC_INTERRUPT)
|
|
||||||
limit = 0;
|
limit = 0;
|
||||||
else if (req == VM_ALLOC_SYSTEM)
|
else if (req_class == VM_ALLOC_SYSTEM)
|
||||||
limit = vmd->vmd_interrupt_free_min;
|
limit = vmd->vmd_interrupt_free_min;
|
||||||
else
|
else
|
||||||
limit = vmd->vmd_free_reserved;
|
limit = vmd->vmd_free_reserved;
|
||||||
@ -1871,6 +1864,20 @@ vm_domain_allocate(struct vm_domain *vmd, int req, int npages)
|
|||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
vm_domain_allocate(struct vm_domain *vmd, int req, int npages)
|
||||||
|
{
|
||||||
|
int req_class;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The page daemon is allowed to dig deeper into the free page list.
|
||||||
|
*/
|
||||||
|
req_class = req & VM_ALLOC_CLASS_MASK;
|
||||||
|
if (curproc == pageproc && req_class != VM_ALLOC_INTERRUPT)
|
||||||
|
req_class = VM_ALLOC_SYSTEM;
|
||||||
|
return (_vm_domain_allocate(vmd, req_class, npages));
|
||||||
|
}
|
||||||
|
|
||||||
vm_page_t
|
vm_page_t
|
||||||
vm_page_alloc_domain_after(vm_object_t object, vm_pindex_t pindex, int domain,
|
vm_page_alloc_domain_after(vm_object_t object, vm_pindex_t pindex, int domain,
|
||||||
int req, vm_page_t mpred)
|
int req, vm_page_t mpred)
|
||||||
@ -2316,8 +2323,13 @@ vm_page_zone_import(void *arg, void **store, int cnt, int domain, int flags)
|
|||||||
|
|
||||||
pgcache = arg;
|
pgcache = arg;
|
||||||
vmd = VM_DOMAIN(pgcache->domain);
|
vmd = VM_DOMAIN(pgcache->domain);
|
||||||
/* Only import if we can bring in a full bucket. */
|
|
||||||
if (cnt == 1 || !vm_domain_allocate(vmd, VM_ALLOC_NORMAL, cnt))
|
/*
|
||||||
|
* The page daemon should avoid creating extra memory pressure since its
|
||||||
|
* main purpose is to replenish the store of free pages.
|
||||||
|
*/
|
||||||
|
if (vmd->vmd_severeset || curproc == pageproc ||
|
||||||
|
!_vm_domain_allocate(vmd, VM_ALLOC_NORMAL, cnt))
|
||||||
return (0);
|
return (0);
|
||||||
domain = vmd->vmd_domain;
|
domain = vmd->vmd_domain;
|
||||||
vm_domain_free_lock(vmd);
|
vm_domain_free_lock(vmd);
|
||||||
|
Loading…
Reference in New Issue
Block a user