MFC r270011:

Implement 'fast path' for the vm page fault handler.

MFC r270387 (by alc):
Relax one of the conditions for mapping a page on the fast path.

Approved by:	re (gjb)
This commit is contained in:
kib 2014-08-25 21:21:29 +00:00
parent 35c4352f4c
commit 4e198665c5

View File

@ -237,6 +237,7 @@ vm_fault_hold(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type,
int hardfault;
struct faultstate fs;
struct vnode *vp;
vm_page_t m;
int locked, error;
hardfault = 0;
@ -290,6 +291,56 @@ RetryFault:;
goto RetryFault;
}
if (wired)
fault_type = prot | (fault_type & VM_PROT_COPY);
if (fs.vp == NULL /* avoid locked vnode leak */ &&
(fault_flags & (VM_FAULT_CHANGE_WIRING | VM_FAULT_DIRTY)) == 0 &&
/* avoid calling vm_object_set_writeable_dirty() */
((prot & VM_PROT_WRITE) == 0 ||
fs.first_object->type != OBJT_VNODE ||
(fs.first_object->flags & OBJ_MIGHTBEDIRTY) != 0)) {
VM_OBJECT_RLOCK(fs.first_object);
if ((prot & VM_PROT_WRITE) != 0 &&
fs.first_object->type == OBJT_VNODE &&
(fs.first_object->flags & OBJ_MIGHTBEDIRTY) == 0)
goto fast_failed;
m = vm_page_lookup(fs.first_object, fs.first_pindex);
/* A busy page can be mapped for read|execute access. */
if (m == NULL || ((prot & VM_PROT_WRITE) != 0 &&
vm_page_busied(m)) || m->valid != VM_PAGE_BITS_ALL)
goto fast_failed;
result = pmap_enter(fs.map->pmap, vaddr, m, prot,
fault_type | PMAP_ENTER_NOSLEEP | (wired ? PMAP_ENTER_WIRED :
0), 0);
if (result != KERN_SUCCESS)
goto fast_failed;
if (m_hold != NULL) {
*m_hold = m;
vm_page_lock(m);
vm_page_hold(m);
vm_page_unlock(m);
}
if ((fault_type & VM_PROT_WRITE) != 0 &&
(m->oflags & VPO_UNMANAGED) == 0) {
vm_page_dirty(m);
vm_pager_page_unswapped(m);
}
VM_OBJECT_RUNLOCK(fs.first_object);
if (!wired)
vm_fault_prefault(&fs, vaddr, 0, 0);
vm_map_lookup_done(fs.map, fs.entry);
curthread->td_ru.ru_minflt++;
return (KERN_SUCCESS);
fast_failed:
if (!VM_OBJECT_TRYUPGRADE(fs.first_object)) {
VM_OBJECT_RUNLOCK(fs.first_object);
VM_OBJECT_WLOCK(fs.first_object);
}
} else {
VM_OBJECT_WLOCK(fs.first_object);
}
/*
* Make a reference to this object to prevent its disposal while we
* are messing with it. Once we have the reference, the map is free
@ -300,15 +351,11 @@ RetryFault:;
* truncation operations) during I/O. This must be done after
* obtaining the vnode lock in order to avoid possible deadlocks.
*/
VM_OBJECT_WLOCK(fs.first_object);
vm_object_reference_locked(fs.first_object);
vm_object_pip_add(fs.first_object, 1);
fs.lookup_still_valid = TRUE;
if (wired)
fault_type = prot | (fault_type & VM_PROT_COPY);
fs.first_m = NULL;
/*