diff options
-rw-r--r-- | contrib/netbsd-tests/lib/libc/sys/t_mlock.c | 2 | ||||
-rw-r--r-- | lib/libc/sys/mlock.2 | 28 | ||||
-rw-r--r-- | lib/libc/sys/mlockall.2 | 16 | ||||
-rw-r--r-- | lib/libc/tests/sys/mlock_helper.c | 22 | ||||
-rw-r--r-- | sys/amd64/vmm/vmm.c | 3 | ||||
-rw-r--r-- | sys/sys/vmmeter.h | 2 | ||||
-rw-r--r-- | sys/vm/vm_glue.c | 15 | ||||
-rw-r--r-- | sys/vm/vm_map.c | 99 | ||||
-rw-r--r-- | sys/vm/vm_map.h | 3 | ||||
-rw-r--r-- | sys/vm/vm_meter.c | 7 | ||||
-rw-r--r-- | sys/vm/vm_mmap.c | 25 | ||||
-rw-r--r-- | sys/vm/vm_pageout.c | 11 | ||||
-rw-r--r-- | sys/vm/vm_pageout.h | 2 | ||||
-rw-r--r-- | sys/vm/vm_unix.c | 26 | ||||
-rw-r--r-- | usr.bin/vmstat/vmstat.c | 4 |
15 files changed, 158 insertions, 107 deletions
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_mlock.c b/contrib/netbsd-tests/lib/libc/sys/t_mlock.c index e6c43943181b..61085f35cc21 100644 --- a/contrib/netbsd-tests/lib/libc/sys/t_mlock.c +++ b/contrib/netbsd-tests/lib/libc/sys/t_mlock.c @@ -51,7 +51,7 @@ __RCSID("$NetBSD: t_mlock.c,v 1.6 2016/08/09 12:02:44 kre Exp $"); #define _KMEMUSER #include <machine/vmparam.h> -void set_vm_max_wired(int); +void set_vm_max_wired(u_long); void restore_vm_max_wired(void); #endif diff --git a/lib/libc/sys/mlock.2 b/lib/libc/sys/mlock.2 index 4a4816615420..040a8f8eaf9e 100644 --- a/lib/libc/sys/mlock.2 +++ b/lib/libc/sys/mlock.2 @@ -28,7 +28,7 @@ .\" @(#)mlock.2 8.2 (Berkeley) 12/11/93 .\" $FreeBSD$ .\" -.Dd March 20, 2018 +.Dd May 13, 2019 .Dt MLOCK 2 .Os .Sh NAME @@ -97,13 +97,13 @@ resource limit and the system-wide .Dq wired pages limit -.Va vm.max_wired . -.Va vm.max_wired +.Va vm.max_user_wired . +.Va vm.max_user_wired applies to the system as a whole, so the amount available to a single process at any given time is the difference between -.Va vm.max_wired +.Va vm.max_user_wired and -.Va vm.stats.vm.v_wire_count . +.Va vm.stats.vm.v_user_wire_count . .Pp If .Va security.bsd.unprivileged_mlock @@ -124,13 +124,11 @@ will fail if: is set to 0 and the caller is not the super-user. .It Bq Er EINVAL The address range given wraps around zero. -.It Bq Er EAGAIN -Locking the indicated range would exceed the system limit for locked memory. .It Bq Er ENOMEM Some portion of the indicated address range is not allocated. There was an error faulting/mapping a page. -Locking the indicated range would exceed the per-process limit for locked -memory. +Locking the indicated range would exceed the per-process or system-wide limits +for locked memory. .El The .Fn munlock @@ -171,11 +169,11 @@ system calls first appeared in Allocating too much wired memory can lead to a memory-allocation deadlock which requires a reboot to recover from. .Pp -The per-process resource limit is a limit on the amount of virtual -memory locked, while the system-wide limit is for the number of locked -physical pages. -Hence a process with two distinct locked mappings of the same physical page -counts as 2 pages against the per-process limit and as only a single page -in the system limit. +The per-process and system-wide resource limits of locked memory apply +to the amount of virtual memory locked, not the amount of locked physical +pages. +Hence two distinct locked mappings of the same physical page counts as +2 pages aginst the system limit, and also against the per-process limit +if both mappings belong to the same physical map. .Pp The per-process resource limit is not currently supported. diff --git a/lib/libc/sys/mlockall.2 b/lib/libc/sys/mlockall.2 index 23c644a8493f..341099ee758f 100644 --- a/lib/libc/sys/mlockall.2 +++ b/lib/libc/sys/mlockall.2 @@ -30,7 +30,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 25, 2012 +.Dd May 13, 2019 .Dt MLOCKALL 2 .Os .Sh NAME @@ -69,7 +69,7 @@ limited in how much they can lock down. A single process can lock the minimum of a system-wide .Dq wired pages limit -.Va vm.max_wired +.Va vm.max_user_wired and the per-process .Dv RLIMIT_MEMLOCK resource limit. @@ -138,9 +138,9 @@ and functions first appeared in .Fx 5.1 . .Sh BUGS -The per-process resource limit is a limit on the amount of virtual -memory locked, while the system-wide limit is for the number of locked -physical pages. -Hence a process with two distinct locked mappings of the same physical page -counts as 2 pages against the per-process limit and as only a single page -in the system limit. +The per-process and system-wide resource limits of locked memory apply +to the amount of virtual memory locked, not the amount of locked physical +pages. +Hence two distinct locked mappings of the same physical page counts as +2 pages aginst the system limit, and also against the per-process limit +if both mappings belong to the same physical map. diff --git a/lib/libc/tests/sys/mlock_helper.c b/lib/libc/tests/sys/mlock_helper.c index 86bbf9ad4d5a..a483207aa5d6 100644 --- a/lib/libc/tests/sys/mlock_helper.c +++ b/lib/libc/tests/sys/mlock_helper.c @@ -39,16 +39,16 @@ __FBSDID("$FreeBSD$"); #include <limits.h> #include <stdio.h> -#define VM_MAX_WIRED "vm.max_wired" +#define VM_MAX_WIRED "vm.max_user_wired" static void -vm_max_wired_sysctl(int *old_value, int *new_value) +vm_max_wired_sysctl(u_long *old_value, u_long *new_value) { size_t old_len; - size_t new_len = (new_value == NULL ? 0 : sizeof(int)); + size_t new_len = (new_value == NULL ? 0 : sizeof(*new_value)); if (old_value == NULL) - printf("Setting the new value to %d\n", *new_value); + printf("Setting the new value to %lu\n", *new_value); else { ATF_REQUIRE_MSG(sysctlbyname(VM_MAX_WIRED, NULL, &old_len, new_value, new_len) == 0, @@ -60,14 +60,14 @@ vm_max_wired_sysctl(int *old_value, int *new_value) "sysctlbyname(%s) failed: %s", VM_MAX_WIRED, strerror(errno)); if (old_value != NULL) - printf("Saved the old value (%d)\n", *old_value); + printf("Saved the old value (%lu)\n", *old_value); } void -set_vm_max_wired(int new_value) +set_vm_max_wired(u_long new_value) { FILE *fp; - int old_value; + u_long old_value; fp = fopen(VM_MAX_WIRED, "w"); if (fp == NULL) { @@ -78,7 +78,7 @@ set_vm_max_wired(int new_value) vm_max_wired_sysctl(&old_value, NULL); - ATF_REQUIRE_MSG(fprintf(fp, "%d", old_value) > 0, + ATF_REQUIRE_MSG(fprintf(fp, "%lu", old_value) > 0, "saving %s failed", VM_MAX_WIRED); fclose(fp); @@ -90,7 +90,7 @@ void restore_vm_max_wired(void) { FILE *fp; - int saved_max_wired; + u_long saved_max_wired; fp = fopen(VM_MAX_WIRED, "r"); if (fp == NULL) { @@ -98,14 +98,14 @@ restore_vm_max_wired(void) return; } - if (fscanf(fp, "%d", &saved_max_wired) != 1) { + if (fscanf(fp, "%lu", &saved_max_wired) != 1) { perror("fscanf failed\n"); fclose(fp); return; } fclose(fp); - printf("old value in %s: %d\n", VM_MAX_WIRED, saved_max_wired); + printf("old value in %s: %lu\n", VM_MAX_WIRED, saved_max_wired); if (saved_max_wired == 0) /* This will cripple the test host */ return; diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c index c56b862fb1c1..2d3455321ffb 100644 --- a/sys/amd64/vmm/vmm.c +++ b/sys/amd64/vmm/vmm.c @@ -754,7 +754,8 @@ vm_mmap_memseg(struct vm *vm, vm_paddr_t gpa, int segid, vm_ooffset_t first, VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES); if (error != KERN_SUCCESS) { vm_map_remove(&vm->vmspace->vm_map, gpa, gpa + len); - return (EFAULT); + return (error == KERN_RESOURCE_SHORTAGE ? ENOMEM : + EFAULT); } } diff --git a/sys/sys/vmmeter.h b/sys/sys/vmmeter.h index 579d16756e99..3714a06983bf 100644 --- a/sys/sys/vmmeter.h +++ b/sys/sys/vmmeter.h @@ -153,6 +153,8 @@ extern domainset_t vm_severe_domains; #define VM_CNT_INC(var) VM_CNT_ADD(var, 1) #define VM_CNT_FETCH(var) counter_u64_fetch(vm_cnt.var) +extern u_long vm_user_wire_count; + static inline void vm_wire_add(int cnt) { diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c index fcffcd3bc34d..c8ad7ae7aae1 100644 --- a/sys/vm/vm_glue.c +++ b/sys/vm/vm_glue.c @@ -181,21 +181,8 @@ vslock(void *addr, size_t len) if (last < (vm_offset_t)addr || end < (vm_offset_t)addr) return (EINVAL); npages = atop(end - start); - if (npages > vm_page_max_wired) + if (npages > vm_page_max_user_wired) return (ENOMEM); -#if 0 - /* - * XXX - not yet - * - * The limit for transient usage of wired pages should be - * larger than for "permanent" wired pages (mlock()). - * - * Also, the sysctl code, which is the only present user - * of vslock(), does a hard loop on EAGAIN. - */ - if (npages + vm_wire_count() > vm_page_max_wired) - return (EAGAIN); -#endif error = vm_map_wire(&curproc->p_vmspace->vm_map, start, end, VM_MAP_WIRE_SYSTEM | VM_MAP_WIRE_NOHOLES); if (error == KERN_SUCCESS) { diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index 5371ed969c60..c77429f41554 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -90,6 +90,7 @@ __FBSDID("$FreeBSD$"); #include <vm/pmap.h> #include <vm/vm_map.h> #include <vm/vm_page.h> +#include <vm/vm_pageout.h> #include <vm/vm_object.h> #include <vm/vm_pager.h> #include <vm/vm_kern.h> @@ -2917,12 +2918,12 @@ done: if (rv == KERN_SUCCESS && (!user_unwire || (entry->eflags & MAP_ENTRY_USER_WIRED))) { - if (user_unwire) - entry->eflags &= ~MAP_ENTRY_USER_WIRED; if (entry->wired_count == 1) vm_map_entry_unwire(map, entry); else entry->wired_count--; + if (user_unwire) + entry->eflags &= ~MAP_ENTRY_USER_WIRED; } KASSERT((entry->eflags & MAP_ENTRY_IN_TRANSITION) != 0, ("vm_map_unwire: in-transition flag missing %p", entry)); @@ -2942,6 +2943,28 @@ done: return (rv); } +static void +vm_map_wire_user_count_sub(u_long npages) +{ + + atomic_subtract_long(&vm_user_wire_count, npages); +} + +static bool +vm_map_wire_user_count_add(u_long npages) +{ + u_long wired; + + wired = vm_user_wire_count; + do { + if (npages + wired > vm_page_max_user_wired) + return (false); + } while (!atomic_fcmpset_long(&vm_user_wire_count, &wired, + npages + wired)); + + return (true); +} + /* * vm_map_wire_entry_failure: * @@ -2978,37 +3001,49 @@ vm_map_wire_entry_failure(vm_map_t map, vm_map_entry_t entry, entry->wired_count = -1; } +int +vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end, int flags) +{ + int rv; + + vm_map_lock(map); + rv = vm_map_wire_locked(map, start, end, flags); + vm_map_unlock(map); + return (rv); +} + + /* - * vm_map_wire: + * vm_map_wire_locked: * - * Implements both kernel and user wiring. + * Implements both kernel and user wiring. Returns with the map locked, + * the map lock may be dropped. */ int -vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end, - int flags) +vm_map_wire_locked(vm_map_t map, vm_offset_t start, vm_offset_t end, int flags) { vm_map_entry_t entry, first_entry, tmp_entry; vm_offset_t faddr, saved_end, saved_start; - unsigned int last_timestamp; + u_long npages; + u_int last_timestamp; int rv; boolean_t need_wakeup, result, user_wire; vm_prot_t prot; + VM_MAP_ASSERT_LOCKED(map); + if (start == end) return (KERN_SUCCESS); prot = 0; if (flags & VM_MAP_WIRE_WRITE) prot |= VM_PROT_WRITE; user_wire = (flags & VM_MAP_WIRE_USER) ? TRUE : FALSE; - vm_map_lock(map); VM_MAP_RANGE_CHECK(map, start, end); if (!vm_map_lookup_entry(map, start, &first_entry)) { if (flags & VM_MAP_WIRE_HOLESOK) first_entry = first_entry->next; - else { - vm_map_unlock(map); + else return (KERN_INVALID_ADDRESS); - } } last_timestamp = map->timestamp; entry = first_entry; @@ -3042,7 +3077,6 @@ vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end, /* * first_entry has been deleted. */ - vm_map_unlock(map); return (KERN_INVALID_ADDRESS); } end = saved_start; @@ -3082,13 +3116,22 @@ vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end, } if (entry->wired_count == 0) { entry->wired_count++; - saved_start = entry->start; - saved_end = entry->end; + + npages = atop(entry->end - entry->start); + if (user_wire && !vm_map_wire_user_count_add(npages)) { + vm_map_wire_entry_failure(map, entry, + entry->start); + end = entry->end; + rv = KERN_RESOURCE_SHORTAGE; + goto done; + } /* * Release the map lock, relying on the in-transition * mark. Mark the map busy for fork. */ + saved_start = entry->start; + saved_end = entry->end; vm_map_busy(map); vm_map_unlock(map); @@ -3136,6 +3179,8 @@ vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end, last_timestamp = map->timestamp; if (rv != KERN_SUCCESS) { vm_map_wire_entry_failure(map, entry, faddr); + if (user_wire) + vm_map_wire_user_count_sub(npages); end = entry->end; goto done; } @@ -3201,9 +3246,12 @@ done: * Undo the wiring. Wiring succeeded on this entry * but failed on a later entry. */ - if (entry->wired_count == 1) + if (entry->wired_count == 1) { vm_map_entry_unwire(map, entry); - else + if (user_wire) + vm_map_wire_user_count_sub( + atop(entry->end - entry->start)); + } else entry->wired_count--; } next_entry_done: @@ -3220,7 +3268,6 @@ done: } vm_map_simplify_entry(map, entry); } - vm_map_unlock(map); if (need_wakeup) vm_map_wakeup(map); return (rv); @@ -3338,13 +3385,18 @@ vm_map_sync( static void vm_map_entry_unwire(vm_map_t map, vm_map_entry_t entry) { + vm_size_t size; VM_MAP_ASSERT_LOCKED(map); KASSERT(entry->wired_count > 0, ("vm_map_entry_unwire: entry %p isn't wired", entry)); + + size = entry->end - entry->start; + if ((entry->eflags & MAP_ENTRY_USER_WIRED) != 0) + vm_map_wire_user_count_sub(atop(size)); pmap_unwire(map->pmap, entry->start, entry->end); - vm_object_unwire(entry->object.vm_object, entry->offset, entry->end - - entry->start, PQ_ACTIVE); + vm_object_unwire(entry->object.vm_object, entry->offset, size, + PQ_ACTIVE); entry->wired_count = 0; } @@ -4311,12 +4363,11 @@ retry: * Heed the MAP_WIREFUTURE flag if it was set for this process. */ if (rv == KERN_SUCCESS && (map->flags & MAP_WIREFUTURE) != 0) { - vm_map_unlock(map); - vm_map_wire(map, grow_start, grow_start + grow_amount, + rv = vm_map_wire_locked(map, grow_start, + grow_start + grow_amount, VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES); - vm_map_lock_read(map); - } else - vm_map_lock_downgrade(map); + } + vm_map_lock_downgrade(map); out: #ifdef RACCT diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h index 8e3033b7fc40..fffda1394d71 100644 --- a/sys/vm/vm_map.h +++ b/sys/vm/vm_map.h @@ -422,7 +422,8 @@ int vm_map_madvise (vm_map_t, vm_offset_t, vm_offset_t, int); int vm_map_stack (vm_map_t, vm_offset_t, vm_size_t, vm_prot_t, vm_prot_t, int); int vm_map_unwire(vm_map_t map, vm_offset_t start, vm_offset_t end, int flags); -int vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end, +int vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end, int flags); +int vm_map_wire_locked(vm_map_t map, vm_offset_t start, vm_offset_t end, int flags); long vmspace_swap_count(struct vmspace *vmspace); void vm_map_entry_set_vnode_text(vm_map_entry_t entry, bool add); diff --git a/sys/vm/vm_meter.c b/sys/vm/vm_meter.c index dfd500814d25..a4d3b5307073 100644 --- a/sys/vm/vm_meter.c +++ b/sys/vm/vm_meter.c @@ -97,6 +97,8 @@ struct vmmeter __read_mostly vm_cnt = { .v_wire_count = EARLY_COUNTER, }; +u_long __exclusive_cache_line vm_user_wire_count; + static void vmcounter_startup(void) { @@ -394,6 +396,8 @@ sysctl_handle_vmstat_proc(SYSCTL_HANDLER_ARGS) #define VM_STATS_UINT(var, descr) \ SYSCTL_UINT(_vm_stats_vm, OID_AUTO, var, CTLFLAG_RD, &vm_cnt.var, 0, descr) +#define VM_STATS_ULONG(var, descr) \ + SYSCTL_ULONG(_vm_stats_vm, OID_AUTO, var, CTLFLAG_RD, &vm_cnt.var, 0, descr) VM_STATS_UINT(v_page_size, "Page size in bytes"); VM_STATS_UINT(v_page_count, "Total number of pages in system"); @@ -411,6 +415,9 @@ VM_STATS_UINT(v_pageout_free_min, "Min pages reserved for kernel"); VM_STATS_UINT(v_interrupt_free_min, "Reserved pages for interrupt code"); VM_STATS_UINT(v_free_severe, "Severe page depletion point"); +SYSCTL_ULONG(_vm_stats_vm, OID_AUTO, v_user_wire_count, CTLFLAG_RD, + &vm_user_wire_count, 0, "User-wired virtual memory"); + #ifdef COMPAT_FREEBSD11 /* * Provide compatibility sysctls for the benefit of old utilities which exit diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index 3e3de54a7924..cac6de681a65 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -1003,7 +1003,7 @@ kern_mlock(struct proc *proc, struct ucred *cred, uintptr_t addr0, size_t len) if (last < addr || end < addr) return (EINVAL); npages = atop(end - start); - if (npages > vm_page_max_wired) + if (npages > vm_page_max_user_wired) return (ENOMEM); map = &proc->p_vmspace->vm_map; PROC_LOCK(proc); @@ -1013,8 +1013,6 @@ kern_mlock(struct proc *proc, struct ucred *cred, uintptr_t addr0, size_t len) return (ENOMEM); } PROC_UNLOCK(proc); - if (npages + vm_wire_count() > vm_page_max_wired) - return (EAGAIN); #ifdef RACCT if (racct_enable) { PROC_LOCK(proc); @@ -1091,7 +1089,12 @@ sys_mlockall(struct thread *td, struct mlockall_args *uap) */ error = vm_map_wire(map, vm_map_min(map), vm_map_max(map), VM_MAP_WIRE_USER|VM_MAP_WIRE_HOLESOK); - error = (error == KERN_SUCCESS ? 0 : EAGAIN); + if (error == KERN_SUCCESS) + error = 0; + else if (error == KERN_RESOURCE_SHORTAGE) + error = ENOMEM; + else + error = EAGAIN; } #ifdef RACCT if (racct_enable && error != KERN_SUCCESS) { @@ -1558,10 +1561,16 @@ vm_mmap_object(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot, * If the process has requested that all future mappings * be wired, then heed this. */ - if (map->flags & MAP_WIREFUTURE) { - vm_map_wire(map, *addr, *addr + size, - VM_MAP_WIRE_USER | ((flags & MAP_STACK) ? - VM_MAP_WIRE_HOLESOK : VM_MAP_WIRE_NOHOLES)); + if ((map->flags & MAP_WIREFUTURE) != 0) { + vm_map_lock(map); + if ((map->flags & MAP_WIREFUTURE) != 0) + rv = vm_map_wire_locked(map, *addr, + *addr + size, VM_MAP_WIRE_USER | + ((flags & MAP_STACK) ? VM_MAP_WIRE_HOLESOK : + VM_MAP_WIRE_NOHOLES)); + if (rv != KERN_SUCCESS) + (void)vm_map_delete(map, *addr, *addr + size); + vm_map_unlock(map); } } return (vm_mmap_to_errno(rv)); diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index 923ba703b9ab..933d8c1e0718 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -194,9 +194,10 @@ SYSCTL_UINT(_vm, OID_AUTO, background_launder_max, CTLFLAG_RWTUN, int vm_pageout_page_count = 32; -int vm_page_max_wired; /* XXX max # of wired pages system-wide */ -SYSCTL_INT(_vm, OID_AUTO, max_wired, - CTLFLAG_RW, &vm_page_max_wired, 0, "System-wide limit to wired page count"); +u_long vm_page_max_user_wired; +SYSCTL_ULONG(_vm, OID_AUTO, max_user_wired, CTLFLAG_RW, + &vm_page_max_user_wired, 0, + "system-wide limit to user-wired page count"); static u_int isqrt(u_int num); static int vm_pageout_launder(struct vm_domain *vmd, int launder, @@ -2041,8 +2042,8 @@ vm_pageout_init(void) if (vm_pageout_update_period == 0) vm_pageout_update_period = 600; - if (vm_page_max_wired == 0) - vm_page_max_wired = freecount / 3; + if (vm_page_max_user_wired == 0) + vm_page_max_user_wired = freecount / 3; } /* diff --git a/sys/vm/vm_pageout.h b/sys/vm/vm_pageout.h index bae7e937f274..57402801f580 100644 --- a/sys/vm/vm_pageout.h +++ b/sys/vm/vm_pageout.h @@ -75,7 +75,7 @@ * Exported data structures. */ -extern int vm_page_max_wired; +extern u_long vm_page_max_user_wired; extern int vm_pageout_page_count; #define VM_OOM_MEM 1 diff --git a/sys/vm/vm_unix.c b/sys/vm/vm_unix.c index 58e14b16c93f..ff12c3008444 100644 --- a/sys/vm/vm_unix.c +++ b/sys/vm/vm_unix.c @@ -95,13 +95,11 @@ kern_break(struct thread *td, uintptr_t *addr) rlim_t datalim, lmemlim, vmemlim; int prot, rv; int error = 0; - boolean_t do_map_wirefuture; datalim = lim_cur(td, RLIMIT_DATA); lmemlim = lim_cur(td, RLIMIT_MEMLOCK); vmemlim = lim_cur(td, RLIMIT_VMEM); - do_map_wirefuture = FALSE; new = round_page(*addr); vm_map_lock(map); @@ -184,7 +182,14 @@ kern_break(struct thread *td, uintptr_t *addr) if (i386_read_exec && SV_PROC_FLAG(td->td_proc, SV_ILP32)) prot |= VM_PROT_EXECUTE; #endif - rv = vm_map_insert(map, NULL, 0, old, new, prot, VM_PROT_ALL, 0); + rv = vm_map_insert(map, NULL, 0, old, new, prot, VM_PROT_ALL, + 0); + if (rv == KERN_SUCCESS && (map->flags & MAP_WIREFUTURE) != 0) { + rv = vm_map_wire_locked(map, old, new, + VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES); + if (rv != KERN_SUCCESS) + vm_map_delete(map, old, new); + } if (rv != KERN_SUCCESS) { #ifdef RACCT if (racct_enable) { @@ -205,17 +210,6 @@ kern_break(struct thread *td, uintptr_t *addr) goto done; } vm->vm_dsize += btoc(new - old); - /* - * Handle the MAP_WIREFUTURE case for legacy applications, - * by marking the newly mapped range of pages as wired. - * We are not required to perform a corresponding - * vm_map_unwire() before vm_map_delete() below, as - * it will forcibly unwire the pages in the range. - * - * XXX If the pages cannot be wired, no error is returned. - */ - if ((map->flags & MAP_WIREFUTURE) == MAP_WIREFUTURE) - do_map_wirefuture = TRUE; } else if (new < old) { rv = vm_map_delete(map, new, old); if (rv != KERN_SUCCESS) { @@ -239,10 +233,6 @@ kern_break(struct thread *td, uintptr_t *addr) done: vm_map_unlock(map); - if (do_map_wirefuture) - (void) vm_map_wire(map, old, new, - VM_MAP_WIRE_USER|VM_MAP_WIRE_NOHOLES); - if (error == 0) *addr = new; diff --git a/usr.bin/vmstat/vmstat.c b/usr.bin/vmstat/vmstat.c index 01b258bf668e..e8cec07fd46b 100644 --- a/usr.bin/vmstat/vmstat.c +++ b/usr.bin/vmstat/vmstat.c @@ -156,6 +156,7 @@ static struct __vmmeter { u_int v_free_min; u_int v_free_count; u_int v_wire_count; + u_long v_user_wire_count; u_int v_active_count; u_int v_inactive_target; u_int v_inactive_count; @@ -566,6 +567,7 @@ fill_vmmeter(struct __vmmeter *vmmp) GET_VM_STATS(vm, v_free_min); GET_VM_STATS(vm, v_free_count); GET_VM_STATS(vm, v_wire_count); + GET_VM_STATS(vm, v_user_wire_count); GET_VM_STATS(vm, v_active_count); GET_VM_STATS(vm, v_inactive_target); GET_VM_STATS(vm, v_inactive_count); @@ -1057,6 +1059,8 @@ dosum(void) sum.v_laundry_count); xo_emit("{:wired-pages/%9u} {N:pages wired down}\n", sum.v_wire_count); + xo_emit("{:virtual-user-wired-pages/%9lu} {N:virtual user pages wired " + "down}\n", sum.v_user_wire_count); xo_emit("{:free-pages/%9u} {N:pages free}\n", sum.v_free_count); xo_emit("{:bytes-per-page/%9u} {N:bytes per page}\n", sum.v_page_size); |