f79fcaf038
vm_map_wire() increments entry->wire_count, after that it drops the map lock both for faulting in the entry' pages, and for marking next entry in the requested region as IN_TRANSITION. Only after all entries are faulted in, MAP_ENTRY_USER_WIRE flag is set. This makes it possible for vm_map_protect() to run while other entry' MAP_ENTRY_IN_TRANSITION flag is handled, and vm_map_busy() lock does not prevent it. In particular, if the call to vm_map_protect() adds VM_PROT_WRITE to CoW entry, it would fail to call vm_fault_copy_entry(). There are at least two consequences of the race: the top object in the shadow chain is not populated with writeable pages, and second, the entry eventually get contradictory flags MAP_ENTRY_NEEDS_COPY | MAP_ENTRY_USER_WIRED with VM_PROT_WRITE set. Handle it by waiting for all MAP_ENTRY_IN_TRANSITION flags to go away in vm_map_protect(), which does not drop map lock afterwards. Note that vm_map_busy_wait() is left as is. Reported and tested by: pho (previous version) Reviewed by: Doug Moore <dougm@rice.edu>, markj Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D20091 |
||
---|---|---|
.. | ||
_vm_radix.h | ||
default_pager.c | ||
device_pager.c | ||
memguard.c | ||
memguard.h | ||
phys_pager.c | ||
pmap.h | ||
redzone.c | ||
redzone.h | ||
sg_pager.c | ||
swap_pager.c | ||
swap_pager.h | ||
uma_core.c | ||
uma_dbg.c | ||
uma_dbg.h | ||
uma_int.h | ||
uma.h | ||
vm_domainset.c | ||
vm_domainset.h | ||
vm_extern.h | ||
vm_fault.c | ||
vm_glue.c | ||
vm_init.c | ||
vm_kern.c | ||
vm_kern.h | ||
vm_map.c | ||
vm_map.h | ||
vm_meter.c | ||
vm_mmap.c | ||
vm_object.c | ||
vm_object.h | ||
vm_page.c | ||
vm_page.h | ||
vm_pageout.c | ||
vm_pageout.h | ||
vm_pagequeue.h | ||
vm_pager.c | ||
vm_pager.h | ||
vm_param.h | ||
vm_phys.c | ||
vm_phys.h | ||
vm_radix.c | ||
vm_radix.h | ||
vm_reserv.c | ||
vm_reserv.h | ||
vm_swapout_dummy.c | ||
vm_swapout.c | ||
vm_unix.c | ||
vm.h | ||
vnode_pager.c | ||
vnode_pager.h |