More pipe changes:
From alc: Move pageable pipe memory to a seperate kernel submap to avoid awkward vm map interlocking issues. (Bad explanation provided by me.) From me: Rework pipespace accounting code to handle this new layout, and adjust our default values to account for the fact that we now have a solid limit on allocations. Also, remove the "maxpipes" limit, as it no longer has a purpose. (The limit on kva usage solves the problem of having two many pipes.)
This commit is contained in:
parent
1bb319c248
commit
bd71f7b671
@ -77,7 +77,6 @@ int nbuf;
|
||||
int nswbuf;
|
||||
int maxswzone; /* max swmeta KVA storage */
|
||||
int maxbcache; /* max buffer cache KVA storage */
|
||||
int maxpipes; /* Limit on # of pipes */
|
||||
int maxpipekva; /* Limit on pipe KVA */
|
||||
int maxpipekvawired; /* Limit on wired pipe KVA */
|
||||
u_quad_t maxtsiz; /* max text size */
|
||||
@ -180,19 +179,18 @@ void
|
||||
init_param3(long kmempages)
|
||||
{
|
||||
/*
|
||||
* Limit number of pipes to a reasonable fraction of kmap entries,
|
||||
* pageable pipe memory usage to 2.5% of the kernel map, and wired
|
||||
* pipe memory usage to 1% of the same. Ensure that all have
|
||||
* reasonable floors. (See sys_pipe.c for more info.)
|
||||
* Limit pageable pipe memory usage to 5% of the kernel map
|
||||
* (via pipe_map), and nonpageable pipe memory usage to 2.5%
|
||||
* of the same. Ensure that all have reasonable floors.
|
||||
* (See sys_pipe.c for more info.)
|
||||
*/
|
||||
maxpipes = kmempages / 5;
|
||||
maxpipekva = (kmempages / 40) * PAGE_SIZE;
|
||||
maxpipekvawired = (kmempages / 100) * PAGE_SIZE;
|
||||
maxpipekva = (kmempages / 20) * PAGE_SIZE;
|
||||
maxpipekvawired = (kmempages / 40) * PAGE_SIZE;
|
||||
|
||||
if (maxpipes < 128)
|
||||
maxpipes = 128;
|
||||
if (maxpipekva < 512 * 1024)
|
||||
maxpipekva = 512 * 1024;
|
||||
if (maxpipekvawired < 512 * 1024)
|
||||
maxpipekvawired = 512 * 1024;
|
||||
|
||||
TUNABLE_INT_FETCH("kern.ipc.maxpipekva", &maxpipekva);
|
||||
}
|
||||
|
@ -43,24 +43,20 @@
|
||||
*
|
||||
* The constant PIPE_MINDIRECT is chosen to make sure that buffering will
|
||||
* happen for small transfers so that the system will not spend all of
|
||||
* its time context switching. PIPE_SIZE is constrained by the
|
||||
* amount of kernel virtual memory.
|
||||
* its time context switching.
|
||||
*
|
||||
* In order to limit the resource use of pipes, three sysctls exist:
|
||||
* In order to limit the resource use of pipes, two sysctls exist:
|
||||
*
|
||||
* kern.ipc.maxpipes - A limit on the total number of pipes in the system.
|
||||
* Note that since pipes are bidirectional, the effective value is this
|
||||
* number divided by two.
|
||||
*
|
||||
* kern.ipc.maxpipekva - This value limits the amount of pageable memory that
|
||||
* can be used by pipes. Whenever the amount in use exceeds this value,
|
||||
* all new pipes will be SMALL_PIPE_SIZE in size, rather than PIPE_SIZE.
|
||||
* Big pipe creation will be limited as well.
|
||||
* kern.ipc.maxpipekva - This is a hard limit on the amount of pageable
|
||||
* address space available to us in pipe_map. Whenever the amount in use
|
||||
* exceeds half of this value, all new pipes will be created with size
|
||||
* SMALL_PIPE_SIZE, rather than PIPE_SIZE. Big pipe creation will be limited
|
||||
* as well. This value is loader tunable only.
|
||||
*
|
||||
* kern.ipc.maxpipekvawired - This value limits the amount of memory that may
|
||||
* be wired in order to facilitate direct copies using page flipping.
|
||||
* Whenever this value is exceeded, pipes will fall back to using regular
|
||||
* copies.
|
||||
* copies. This value is sysctl controllable at all times.
|
||||
*
|
||||
* These values are autotuned in subr_param.c.
|
||||
*
|
||||
@ -182,9 +178,7 @@ static int amountpipekvawired;
|
||||
|
||||
SYSCTL_DECL(_kern_ipc);
|
||||
|
||||
SYSCTL_INT(_kern_ipc, OID_AUTO, maxpipes, CTLFLAG_RW,
|
||||
&maxpipes, 0, "Max # of pipes");
|
||||
SYSCTL_INT(_kern_ipc, OID_AUTO, maxpipekva, CTLFLAG_RW,
|
||||
SYSCTL_INT(_kern_ipc, OID_AUTO, maxpipekva, CTLFLAG_RD,
|
||||
&maxpipekva, 0, "Pipe KVA limit");
|
||||
SYSCTL_INT(_kern_ipc, OID_AUTO, maxpipekvawired, CTLFLAG_RW,
|
||||
&maxpipekvawired, 0, "Pipe KVA wired limit");
|
||||
@ -339,32 +333,29 @@ pipespace(cpipe, size)
|
||||
KASSERT(cpipe->pipe_mtxp == NULL || !mtx_owned(PIPE_MTX(cpipe)),
|
||||
("pipespace: pipe mutex locked"));
|
||||
|
||||
if (amountpipes > maxpipes) {
|
||||
if (ppsratecheck(&lastfail, &curfail, 1))
|
||||
printf("kern.maxpipes exceeded, please see tuning(7).\n");
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
npages = round_page(size)/PAGE_SIZE;
|
||||
size = round_page(size);
|
||||
npages = size / PAGE_SIZE;
|
||||
/*
|
||||
* Create an object, I don't like the idea of paging to/from
|
||||
* kernel_object.
|
||||
* XXX -- minor change needed here for NetBSD/OpenBSD VM systems.
|
||||
*/
|
||||
object = vm_object_allocate(OBJT_DEFAULT, npages);
|
||||
buffer = (caddr_t) vm_map_min(kernel_map);
|
||||
buffer = (caddr_t) vm_map_min(pipe_map);
|
||||
|
||||
/*
|
||||
* Insert the object into the kernel map, and allocate kva for it.
|
||||
* The map entry is, by default, pageable.
|
||||
* XXX -- minor change needed here for NetBSD/OpenBSD VM systems.
|
||||
*/
|
||||
error = vm_map_find(kernel_map, object, 0,
|
||||
error = vm_map_find(pipe_map, object, 0,
|
||||
(vm_offset_t *) &buffer, size, 1,
|
||||
VM_PROT_ALL, VM_PROT_ALL, 0);
|
||||
|
||||
if (error != KERN_SUCCESS) {
|
||||
vm_object_deallocate(object);
|
||||
if (ppsratecheck(&lastfail, &curfail, 1))
|
||||
printf("kern.maxpipekva exceeded, please see tuning(7).\n");
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
@ -423,7 +414,7 @@ pipe_create(cpipep)
|
||||
/*
|
||||
* Reduce to 1/4th pipe size if we're over our global max.
|
||||
*/
|
||||
if (amountpipekva > maxpipekva)
|
||||
if (amountpipekva > maxpipekva / 2)
|
||||
error = pipespace(cpipe, SMALL_PIPE_SIZE);
|
||||
else
|
||||
error = pipespace(cpipe, PIPE_SIZE);
|
||||
@ -697,8 +688,6 @@ pipe_build_write_buffer(wpipe, uio)
|
||||
vm_page_lock_queues();
|
||||
for (j = 0; j < i; j++) {
|
||||
vm_page_unhold(wpipe->pipe_map.ms[j]);
|
||||
atomic_subtract_int(&amountpipekvawired,
|
||||
PAGE_SIZE);
|
||||
}
|
||||
vm_page_unlock_queues();
|
||||
return (EFAULT);
|
||||
@ -707,7 +696,6 @@ pipe_build_write_buffer(wpipe, uio)
|
||||
m = PHYS_TO_VM_PAGE(paddr);
|
||||
vm_page_lock_queues();
|
||||
vm_page_hold(m);
|
||||
atomic_add_int(&amountpipekvawired, PAGE_SIZE);
|
||||
vm_page_unlock_queues();
|
||||
wpipe->pipe_map.ms[i] = m;
|
||||
}
|
||||
@ -730,7 +718,7 @@ pipe_build_write_buffer(wpipe, uio)
|
||||
*/
|
||||
wpipe->pipe_map.kva = kmem_alloc_nofault(kernel_map,
|
||||
wpipe->pipe_buffer.size + PAGE_SIZE);
|
||||
atomic_add_int(&amountpipekva,
|
||||
atomic_add_int(&amountpipekvawired,
|
||||
wpipe->pipe_buffer.size + PAGE_SIZE);
|
||||
}
|
||||
pmap_qenter(wpipe->pipe_map.kva, wpipe->pipe_map.ms,
|
||||
@ -764,19 +752,19 @@ pipe_destroy_write_buffer(wpipe)
|
||||
if (wpipe->pipe_map.kva) {
|
||||
pmap_qremove(wpipe->pipe_map.kva, wpipe->pipe_map.npages);
|
||||
|
||||
if (amountpipekva > maxpipekva) {
|
||||
if (amountpipekvawired > maxpipekvawired / 2) {
|
||||
/* Conserve address space */
|
||||
vm_offset_t kva = wpipe->pipe_map.kva;
|
||||
wpipe->pipe_map.kva = 0;
|
||||
kmem_free(kernel_map, kva,
|
||||
wpipe->pipe_buffer.size + PAGE_SIZE);
|
||||
atomic_subtract_int(&amountpipekva,
|
||||
atomic_subtract_int(&amountpipekvawired,
|
||||
wpipe->pipe_buffer.size + PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
vm_page_lock_queues();
|
||||
for (i = 0; i < wpipe->pipe_map.npages; i++) {
|
||||
vm_page_unhold(wpipe->pipe_map.ms[i]);
|
||||
atomic_subtract_int(&amountpipekvawired, PAGE_SIZE);
|
||||
}
|
||||
vm_page_unlock_queues();
|
||||
wpipe->pipe_map.npages = 0;
|
||||
@ -951,7 +939,7 @@ pipe_write(fp, uio, active_cred, flags, td)
|
||||
* so.
|
||||
*/
|
||||
if ((uio->uio_resid > PIPE_SIZE) &&
|
||||
(amountpipekva < maxpipekva) &&
|
||||
(amountpipekva < maxpipekva / 2) &&
|
||||
(nbigpipe < LIMITBIGPIPES) &&
|
||||
(wpipe->pipe_state & PIPE_DIRECTW) == 0 &&
|
||||
(wpipe->pipe_buffer.size <= PIPE_SIZE) &&
|
||||
@ -998,7 +986,7 @@ pipe_write(fp, uio, active_cred, flags, td)
|
||||
*/
|
||||
if ((uio->uio_iov->iov_len >= PIPE_MINDIRECT) &&
|
||||
(fp->f_flag & FNONBLOCK) == 0 &&
|
||||
amountpipekvawired < maxpipekvawired) {
|
||||
amountpipekvawired + uio->uio_resid < maxpipekvawired) {
|
||||
error = pipe_direct_write(wpipe, uio);
|
||||
if (error)
|
||||
break;
|
||||
@ -1404,14 +1392,14 @@ pipe_free_kmem(cpipe)
|
||||
atomic_subtract_int(&nbigpipe, 1);
|
||||
atomic_subtract_int(&amountpipekva, cpipe->pipe_buffer.size);
|
||||
atomic_subtract_int(&amountpipes, 1);
|
||||
kmem_free(kernel_map,
|
||||
(vm_offset_t)cpipe->pipe_buffer.buffer,
|
||||
cpipe->pipe_buffer.size);
|
||||
vm_map_remove(pipe_map,
|
||||
(vm_offset_t)cpipe->pipe_buffer.buffer,
|
||||
(vm_offset_t)cpipe->pipe_buffer.buffer + cpipe->pipe_buffer.size);
|
||||
cpipe->pipe_buffer.buffer = NULL;
|
||||
}
|
||||
#ifndef PIPE_NODIRECT
|
||||
if (cpipe->pipe_map.kva != 0) {
|
||||
atomic_subtract_int(&amountpipekva,
|
||||
atomic_subtract_int(&amountpipekvawired,
|
||||
cpipe->pipe_buffer.size + PAGE_SIZE);
|
||||
kmem_free(kernel_map,
|
||||
cpipe->pipe_map.kva,
|
||||
|
@ -60,7 +60,6 @@
|
||||
/*
|
||||
* See sys_pipe.c for info on what these limits mean.
|
||||
*/
|
||||
extern int maxpipes;
|
||||
extern int maxpipekva;
|
||||
extern int maxpipekvawired;
|
||||
|
||||
|
@ -75,6 +75,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/selinfo.h>
|
||||
#include <sys/pipe.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/buf.h>
|
||||
|
||||
@ -195,6 +197,7 @@ again:
|
||||
pager_map->system_map = 1;
|
||||
exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
|
||||
(16*(ARG_MAX+(PAGE_SIZE*3))));
|
||||
pipe_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, maxpipekva);
|
||||
|
||||
/*
|
||||
* XXX: Mbuf system machine-specific initializations should
|
||||
|
@ -89,6 +89,7 @@ __FBSDID("$FreeBSD$");
|
||||
vm_map_t kernel_map=0;
|
||||
vm_map_t kmem_map=0;
|
||||
vm_map_t exec_map=0;
|
||||
vm_map_t pipe_map;
|
||||
vm_map_t clean_map=0;
|
||||
vm_map_t buffer_map=0;
|
||||
|
||||
|
@ -73,6 +73,7 @@ extern vm_map_t kernel_map;
|
||||
extern vm_map_t kmem_map;
|
||||
extern vm_map_t clean_map;
|
||||
extern vm_map_t exec_map;
|
||||
extern vm_map_t pipe_map;
|
||||
extern u_int vm_kmem_size;
|
||||
|
||||
#endif /* _VM_VM_KERN_H_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user