diff options
author | kib <kib@FreeBSD.org> | 2013-09-08 17:51:22 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2013-09-08 17:51:22 +0000 |
commit | 56cc6860588a887bdad5d45e3e73e38a523b6c52 (patch) | |
tree | aa83ae142c669cae8ce8a5da7fe0736576976183 /sys/vm/vm_object.c | |
parent | a496157a2f1aae0a7a8510bcfe7ed2a0428968eb (diff) | |
download | FreeBSD-src-56cc6860588a887bdad5d45e3e73e38a523b6c52.zip FreeBSD-src-56cc6860588a887bdad5d45e3e73e38a523b6c52.tar.gz |
Drain for the xbusy state for two places which potentially do
pmap_remove_all(). Not doing the drain allows the pmap_enter() to
proceed in parallel, making the pmap_remove_all() effects void.
The race results in an invalidated page mapped wired by usermode.
Reported and tested by: pho
Reviewed by: alc
Sponsored by: The FreeBSD Foundation
Approved by: re (glebius)
Diffstat (limited to 'sys/vm/vm_object.c')
-rw-r--r-- | sys/vm/vm_object.c | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 1d7f321..9dea3a1 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -1910,6 +1910,12 @@ again: * not specified. */ vm_page_lock(p); + if (vm_page_xbusied(p)) { + VM_OBJECT_WUNLOCK(object); + vm_page_busy_sleep(p, "vmopax"); + VM_OBJECT_WLOCK(object); + goto again; + } if ((wirings = p->wire_count) != 0 && (wirings = pmap_page_wired_mappings(p)) != p->wire_count) { if ((options & (OBJPR_NOTWIRED | OBJPR_NOTMAPPED)) == |