From 47934cef8f8eae0614799485658acebe190602f7 Mon Sep 17 00:00:00 2001 From: Don Lewis Date: Thu, 26 Feb 2004 00:27:04 +0000 Subject: Split the mlock() kernel code into two parts, mlock(), which unpacks the syscall arguments and does the suser() permission check, and kern_mlock(), which does the resource limit checking and calls vm_map_wire(). Split munlock() in a similar way. Enable the RLIMIT_MEMLOCK checking code in kern_mlock(). Replace calls to vslock() and vsunlock() in the sysctl code with calls to kern_mlock() and kern_munlock() so that the sysctl code will obey the wired memory limits. Nuke the vslock() and vsunlock() implementations, which are no longer used. Add a member to struct sysctl_req to track the amount of memory that is wired to handle the request. Modify sysctl_wire_old_buffer() to return an error if its call to kern_mlock() fails. Only wire the minimum of the length specified in the sysctl request and the length specified in its argument list. It is recommended that sysctl handlers that use sysctl_wire_old_buffer() should specify reasonable estimates for the amount of data they want to return so that only the minimum amount of memory is wired no matter what length has been specified by the request. Modify the callers of sysctl_wire_old_buffer() to look for the error return. Modify sysctl_old_user to obey the wired buffer length and clean up its implementation. Reviewed by: bms --- sys/vm/vm_extern.h | 4 ++-- sys/vm/vm_glue.c | 29 ------------------------ sys/vm/vm_mmap.c | 65 ++++++++++++++++++++++++++++++++++-------------------- 3 files changed, 43 insertions(+), 55 deletions(-) (limited to 'sys/vm') diff --git a/sys/vm/vm_extern.h b/sys/vm/vm_extern.h index 2d8c2327df899..d8581e6f5857b 100644 --- a/sys/vm/vm_extern.h +++ b/sys/vm/vm_extern.h @@ -59,6 +59,8 @@ int sstk(struct thread *, void *, int *); int swapon(struct thread *, void *, int *); #endif /* TYPEDEF_FOR_UAP */ +int kern_mlock(struct thread *, vm_offset_t, vm_size_t); +int kern_munlock(struct thread *, vm_offset_t, vm_size_t); int kernacc(void *, int, int); vm_offset_t kmem_alloc(vm_map_t, vm_size_t); vm_offset_t kmem_alloc_nofault(vm_map_t, vm_size_t); @@ -86,8 +88,6 @@ void vmspace_unshare(struct proc *); void vmspace_free(struct vmspace *); void vmspace_exitfree(struct proc *); void vnode_pager_setsize(struct vnode *, vm_ooffset_t); -void vslock(void *, u_int); -void vsunlock(void *, u_int); void vm_object_print(/* db_expr_t */ long, boolean_t, /* db_expr_t */ long, char *); int vm_fault_quick(caddr_t v, int prot); diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c index 15d0fd5f3e9c3..84cf879158208 100644 --- a/sys/vm/vm_glue.c +++ b/sys/vm/vm_glue.c @@ -183,35 +183,6 @@ useracc(addr, len, rw) return (rv == TRUE); } -/* - * MPSAFE - */ -void -vslock(addr, len) - void *addr; - u_int len; -{ - - vm_map_wire(&curproc->p_vmspace->vm_map, trunc_page((vm_offset_t)addr), - round_page((vm_offset_t)addr + len), - VM_MAP_WIRE_SYSTEM|VM_MAP_WIRE_NOHOLES); -} - -/* - * MPSAFE - */ -void -vsunlock(addr, len) - void *addr; - u_int len; -{ - - vm_map_unwire(&curproc->p_vmspace->vm_map, - trunc_page((vm_offset_t)addr), - round_page((vm_offset_t)addr + len), - VM_MAP_WIRE_SYSTEM|VM_MAP_WIRE_NOHOLES); -} - /* * Create the U area for a new process. * This routine directly affects the fork perf for a process. diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index 2cad29b42253a..6f438706a4c08 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -984,12 +984,26 @@ mlock(td, uap) struct thread *td; struct mlock_args *uap; { - vm_offset_t addr; - vm_size_t size, pageoff; int error; - addr = (vm_offset_t) uap->addr; - size = uap->len; + error = suser(td); + if (error) + return (error); + return (kern_mlock(td, (vm_offset_t)uap->addr, (vm_size_t)uap->len)); +} + +/* + * MPSAFE + */ +int +kern_mlock(td, addr, size) + struct thread *td; + vm_offset_t addr; + vm_size_t size; +{ + vm_size_t pageoff; + struct proc *proc = td->td_proc; + int error; pageoff = (addr & PAGE_MASK); addr -= pageoff; @@ -1003,21 +1017,15 @@ mlock(td, uap) if (atop(size) + cnt.v_wire_count > vm_page_max_wired) return (EAGAIN); -#if 0 - PROC_LOCK(td->td_proc); - if (size + ptoa(pmap_wired_count(vm_map_pmap(&td->td_proc->p_vmspace->vm_map))) > - lim_cur(td->td_proc, RLIMIT_MEMLOCK)) { - PROC_UNLOCK(td->td_proc); + PROC_LOCK(proc); + if (size + ptoa(pmap_wired_count(vm_map_pmap(&proc->p_vmspace->vm_map))) > + lim_cur(proc, RLIMIT_MEMLOCK)) { + PROC_UNLOCK(proc); return (ENOMEM); } - PROC_UNLOCK(td->td_proc); -#else - error = suser(td); - if (error) - return (error); -#endif + PROC_UNLOCK(proc); - error = vm_map_wire(&td->td_proc->p_vmspace->vm_map, addr, + error = vm_map_wire(&proc->p_vmspace->vm_map, addr, addr + size, VM_MAP_WIRE_USER|VM_MAP_WIRE_NOHOLES); return (error == KERN_SUCCESS ? 0 : ENOMEM); } @@ -1133,12 +1141,25 @@ munlock(td, uap) struct thread *td; struct munlock_args *uap; { - vm_offset_t addr; - vm_size_t size, pageoff; int error; - addr = (vm_offset_t) uap->addr; - size = uap->len; + error = suser(td); + if (error) + return (error); + return (kern_munlock(td, (vm_offset_t)uap->addr, (vm_size_t)uap->len)); +} + +/* + * MPSAFE + */ +int +kern_munlock(td, addr, size) + struct thread *td; + vm_offset_t addr; + vm_size_t size; +{ + vm_size_t pageoff; + int error; pageoff = (addr & PAGE_MASK); addr -= pageoff; @@ -1149,10 +1170,6 @@ munlock(td, uap) if (addr + size < addr) return (EINVAL); - error = suser(td); - if (error) - return (error); - error = vm_map_unwire(&td->td_proc->p_vmspace->vm_map, addr, addr + size, VM_MAP_WIRE_USER|VM_MAP_WIRE_NOHOLES); return (error == KERN_SUCCESS ? 0 : ENOMEM); -- cgit v1.3