summaryrefslogtreecommitdiffstats
path: root/sys/vm/vm_map.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2009-04-10 10:16:03 +0000
committerkib <kib@FreeBSD.org>2009-04-10 10:16:03 +0000
commit81638d98846e99a6bfcf7398057a650533aa1390 (patch)
treed2a9dfe34e82f1ea1ab3cbe791593b31fbee1dd2 /sys/vm/vm_map.c
parent5a12c5d70e83806a92145c478867d74073203a09 (diff)
downloadFreeBSD-src-81638d98846e99a6bfcf7398057a650533aa1390.zip
FreeBSD-src-81638d98846e99a6bfcf7398057a650533aa1390.tar.gz
When vm_map_wire(9) is allowed to skip holes in the wired region, skip
the mappings without any of read and execution rights, in particular, the PROT_NONE entries. This makes mlockall(2) work for the process address space that has such mappings. Since protection mode of the entry may change between setting MAP_ENTRY_IN_TRANSITION and final pass over the region that records the wire status of the entries, allocate new map entry flag MAP_ENTRY_WIRE_SKIPPED to mark the skipped PROT_NONE entries. Reported and tested by: Hans Ottevanger <fbsdhackers beasties demon nl> Reviewed by: alc MFC after: 3 weeks
Diffstat (limited to 'sys/vm/vm_map.c')
-rw-r--r--sys/vm/vm_map.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index f395be8..718c890 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -2217,6 +2217,16 @@ vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end,
*
*/
if (entry->wired_count == 0) {
+ if ((entry->protection & (VM_PROT_READ|VM_PROT_EXECUTE))
+ == 0) {
+ if ((flags & VM_MAP_WIRE_HOLESOK) == 0) {
+ end = entry->end;
+ rv = KERN_INVALID_ADDRESS;
+ goto done;
+ }
+ entry->eflags |= MAP_ENTRY_WIRE_SKIPPED;
+ goto next_entry;
+ }
entry->wired_count++;
saved_start = entry->start;
saved_end = entry->end;
@@ -2274,6 +2284,7 @@ vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end,
* Check the map for holes in the specified region.
* If VM_MAP_WIRE_HOLESOK was specified, skip this check.
*/
+ next_entry:
if (((flags & VM_MAP_WIRE_HOLESOK) == 0) &&
(entry->end < end && (entry->next == &map->header ||
entry->next->start > entry->end))) {
@@ -2295,6 +2306,8 @@ done:
}
entry = first_entry;
while (entry != &map->header && entry->start < end) {
+ if ((entry->eflags & MAP_ENTRY_WIRE_SKIPPED) != 0)
+ goto next_entry_done;
if (rv == KERN_SUCCESS) {
if (user_wire)
entry->eflags |= MAP_ENTRY_USER_WIRED;
@@ -2317,9 +2330,10 @@ done:
entry->object.vm_object->type == OBJT_DEVICE);
}
}
+ next_entry_done:
KASSERT(entry->eflags & MAP_ENTRY_IN_TRANSITION,
("vm_map_wire: in-transition flag missing"));
- entry->eflags &= ~MAP_ENTRY_IN_TRANSITION;
+ entry->eflags &= ~(MAP_ENTRY_IN_TRANSITION|MAP_ENTRY_WIRE_SKIPPED);
if (entry->eflags & MAP_ENTRY_NEEDS_WAKEUP) {
entry->eflags &= ~MAP_ENTRY_NEEDS_WAKEUP;
need_wakeup = TRUE;
OpenPOWER on IntegriCloud