diff options
author | alc <alc@FreeBSD.org> | 2014-05-23 16:46:50 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 2014-05-23 16:46:50 +0000 |
commit | 80044281eb7ca569563950bc5c86bcd1a4d9c7c6 (patch) | |
tree | e2456d089d09839b341402bbe52c247751e5d82b /sys/vm/vm_map.c | |
parent | 476a11c228e79a119aff97294782b703f76bcf2e (diff) | |
download | FreeBSD-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/vm_map.c')
-rw-r--r-- | sys/vm/vm_map.c | 21 |
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); |