Date: Fri, 10 Apr 2009 10:16:03 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r190886 - head/sys/vm Message-ID: <200904101016.n3AAG3Ow039018@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Fri Apr 10 10:16:03 2009 New Revision: 190886 URL: http://svn.freebsd.org/changeset/base/190886 Log: 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 Modified: head/sys/vm/vm_map.c head/sys/vm/vm_map.h Modified: head/sys/vm/vm_map.c ============================================================================== --- head/sys/vm/vm_map.c Fri Apr 10 10:14:04 2009 (r190885) +++ head/sys/vm/vm_map.c Fri Apr 10 10:16:03 2009 (r190886) @@ -2217,6 +2217,16 @@ vm_map_wire(vm_map_t map, vm_offset_t st * */ 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 st * 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; Modified: head/sys/vm/vm_map.h ============================================================================== --- head/sys/vm/vm_map.h Fri Apr 10 10:14:04 2009 (r190885) +++ head/sys/vm/vm_map.h Fri Apr 10 10:16:03 2009 (r190886) @@ -137,6 +137,8 @@ struct vm_map_entry { #define MAP_ENTRY_GROWS_DOWN 0x1000 /* Top-down stacks */ #define MAP_ENTRY_GROWS_UP 0x2000 /* Bottom-up stacks */ +#define MAP_ENTRY_WIRE_SKIPPED 0x4000 + #ifdef _KERNEL static __inline u_char vm_map_entry_behavior(vm_map_entry_t entry)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200904101016.n3AAG3Ow039018>