summaryrefslogtreecommitdiffstats
path: root/sys/vm
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2014-05-23 16:46:50 +0000
committeralc <alc@FreeBSD.org>2014-05-23 16:46:50 +0000
commit80044281eb7ca569563950bc5c86bcd1a4d9c7c6 (patch)
treee2456d089d09839b341402bbe52c247751e5d82b /sys/vm
parent476a11c228e79a119aff97294782b703f76bcf2e (diff)
downloadFreeBSD-src-80044281eb7ca569563950bc5c86bcd1a4d9c7c6.zip
FreeBSD-src-80044281eb7ca569563950bc5c86bcd1a4d9c7c6.tar.gz
MFC r265886, r265948
With the new-and-improved vm_fault_copy_entry() (r265843), we can always avoid soft page faults when adding write access to user wired entries in vm_map_protect(). Previously, we only avoided the soft page fault when the underlying pages were copy-on-write. In other words, we avoided the pages faults that might sleep on page allocation, but not the trivial page faults to update the physical map. On a fork allow read-only wired pages to be copy-on-write shared between the parent and child processes. Previously, we copied these pages even though they are read only. However, the reason for copying them is historical and no longer exists. In recent times, vm_map_protect() has developed the ability to copy pages when write access is added to wired copy-on-write pages. So, in this case, copy-on-write sharing of wired pages is not to be feared. It is not going to lead to copy-on-write faults on wired memory.
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/vm_map.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index 3c0aabc..9093ea5 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -1978,10 +1978,17 @@ vm_map_protect(vm_map_t map, vm_offset_t start, vm_offset_t end,
else
current->protection = new_prot;
- if ((current->eflags & (MAP_ENTRY_COW | MAP_ENTRY_USER_WIRED))
- == (MAP_ENTRY_COW | MAP_ENTRY_USER_WIRED) &&
+ /*
+ * For user wired map entries, the normal lazy evaluation of
+ * write access upgrades through soft page faults is
+ * undesirable. Instead, immediately copy any pages that are
+ * copy-on-write and enable write access in the physical map.
+ */
+ if ((current->eflags & MAP_ENTRY_USER_WIRED) != 0 &&
(current->protection & VM_PROT_WRITE) != 0 &&
(old_prot & VM_PROT_WRITE) == 0) {
+ KASSERT(old_prot != VM_PROT_NONE,
+ ("vm_map_protect: inaccessible wired map entry"));
vm_fault_copy_entry(map, map, current, current, NULL);
}
@@ -3017,8 +3024,8 @@ vm_map_copy_entry(
if ((dst_entry->eflags|src_entry->eflags) & MAP_ENTRY_IS_SUB_MAP)
return;
- if (src_entry->wired_count == 0) {
-
+ if (src_entry->wired_count == 0 ||
+ (src_entry->protection & VM_PROT_WRITE) == 0) {
/*
* If the source entry is marked needs_copy, it is already
* write-protected.
@@ -3109,9 +3116,9 @@ vm_map_copy_entry(
dst_entry->end - dst_entry->start, src_entry->start);
} else {
/*
- * Of course, wired down pages can't be set copy-on-write.
- * Cause wired pages to be copied into the new map by
- * simulating faults (the new pages are pageable)
+ * We don't want to make writeable wired pages copy-on-write.
+ * Immediately copy these pages into the new map by simulating
+ * page faults. The new pages are pageable.
*/
vm_fault_copy_entry(dst_map, src_map, dst_entry, src_entry,
fork_charge);
OpenPOWER on IntegriCloud