Changeset View
Changeset View
Standalone View
Standalone View
sys/vm/vm_fault.c
Show First 20 Lines • Show All 202 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
VM_OBJECT_WUNLOCK(fs->object); | VM_OBJECT_WUNLOCK(fs->object); | ||||
fault_deallocate(fs); | fault_deallocate(fs); | ||||
} | } | ||||
static void | static void | ||||
vm_fault_dirty(vm_map_entry_t entry, vm_page_t m, vm_prot_t prot, | vm_fault_dirty(vm_map_entry_t entry, vm_page_t m, vm_prot_t prot, | ||||
vm_prot_t fault_type, int fault_flags, bool set_wd) | vm_prot_t fault_type, int fault_flags, bool excl) | ||||
{ | { | ||||
bool need_dirty; | bool need_dirty; | ||||
if (((prot & VM_PROT_WRITE) == 0 && | if (((prot & VM_PROT_WRITE) == 0 && | ||||
(fault_flags & VM_FAULT_DIRTY) == 0) || | (fault_flags & VM_FAULT_DIRTY) == 0) || | ||||
(m->oflags & VPO_UNMANAGED) != 0) | (m->oflags & VPO_UNMANAGED) != 0) | ||||
return; | return; | ||||
VM_OBJECT_ASSERT_LOCKED(m->object); | VM_OBJECT_ASSERT_LOCKED(m->object); | ||||
VM_PAGE_OBJECT_BUSY_ASSERT(m); | VM_PAGE_OBJECT_BUSY_ASSERT(m); | ||||
need_dirty = ((fault_type & VM_PROT_WRITE) != 0 && | need_dirty = ((fault_type & VM_PROT_WRITE) != 0 && | ||||
(fault_flags & VM_FAULT_WIRE) == 0) || | (fault_flags & VM_FAULT_WIRE) == 0) || | ||||
(fault_flags & VM_FAULT_DIRTY) != 0; | (fault_flags & VM_FAULT_DIRTY) != 0; | ||||
if (set_wd) | |||||
vm_object_set_writeable_dirty(m->object); | vm_object_set_writeable_dirty(m->object); | ||||
else | |||||
if (!excl) | |||||
/* | /* | ||||
* If two callers of vm_fault_dirty() with set_wd == | * If two callers of vm_fault_dirty() with excl == | ||||
* FALSE, one for the map entry with MAP_ENTRY_NOSYNC | * FALSE, one for the map entry with MAP_ENTRY_NOSYNC | ||||
* flag set, other with flag clear, race, it is | * flag set, other with flag clear, race, it is | ||||
* possible for the no-NOSYNC thread to see m->dirty | * possible for the no-NOSYNC thread to see m->dirty | ||||
* != 0 and not clear PGA_NOSYNC. Take vm_page lock | * != 0 and not clear PGA_NOSYNC. Take vm_page lock | ||||
* around manipulation of PGA_NOSYNC and | * around manipulation of PGA_NOSYNC and | ||||
* vm_page_dirty() call to avoid the race. | * vm_page_dirty() call to avoid the race. | ||||
*/ | */ | ||||
vm_page_lock(m); | vm_page_lock(m); | ||||
Show All 20 Lines | vm_fault_dirty(vm_map_entry_t entry, vm_page_t m, vm_prot_t prot, | ||||
* pmap_is_modified() calls later. | * pmap_is_modified() calls later. | ||||
* | * | ||||
* Also, since the page is now dirty, we can possibly tell | * Also, since the page is now dirty, we can possibly tell | ||||
* the pager to release any swap backing the page. Calling | * the pager to release any swap backing the page. Calling | ||||
* the pager requires a write lock on the object. | * the pager requires a write lock on the object. | ||||
*/ | */ | ||||
if (need_dirty) | if (need_dirty) | ||||
vm_page_dirty(m); | vm_page_dirty(m); | ||||
if (!set_wd) | if (!excl) | ||||
vm_page_unlock(m); | vm_page_unlock(m); | ||||
else if (need_dirty) | else if (need_dirty) | ||||
vm_pager_page_unswapped(m); | vm_pager_page_unswapped(m); | ||||
} | } | ||||
/* | /* | ||||
* Unlocks fs.first_object and fs.map on success. | * Unlocks fs.first_object and fs.map on success. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 429 Lines • ▼ Show 20 Lines | if (wired) | ||||
fault_type = prot | (fault_type & VM_PROT_COPY); | fault_type = prot | (fault_type & VM_PROT_COPY); | ||||
else | else | ||||
KASSERT((fault_flags & VM_FAULT_WIRE) == 0, | KASSERT((fault_flags & VM_FAULT_WIRE) == 0, | ||||
("!wired && VM_FAULT_WIRE")); | ("!wired && VM_FAULT_WIRE")); | ||||
/* | /* | ||||
* Try to avoid lock contention on the top-level object through | * Try to avoid lock contention on the top-level object through | ||||
* special-case handling of some types of page faults, specifically, | * special-case handling of some types of page faults, specifically, | ||||
* those that are both (1) mapping an existing page from the top- | * those that are mapping an existing page from the top-level object. | ||||
* level object and (2) not having to mark that object as containing | * Under this condition, a read lock on the object suffices, allowing | ||||
* dirty pages. Under these conditions, a read lock on the top-level | * multiple page faults of a similar type to run in parallel. | ||||
* object suffices, allowing multiple page faults of a similar type to | |||||
* run in parallel on the same top-level object. | |||||
*/ | */ | ||||
if (fs.vp == NULL /* avoid locked vnode leak */ && | if (fs.vp == NULL /* avoid locked vnode leak */ && | ||||
(fault_flags & (VM_FAULT_WIRE | VM_FAULT_DIRTY)) == 0 && | (fault_flags & (VM_FAULT_WIRE | 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_TMPFS_NODE) == 0) || | |||||
(fs.first_object->flags & OBJ_MIGHTBEDIRTY) != 0)) { | |||||
VM_OBJECT_RLOCK(fs.first_object); | VM_OBJECT_RLOCK(fs.first_object); | ||||
if ((prot & VM_PROT_WRITE) == 0 || | |||||
(fs.first_object->type != OBJT_VNODE && | |||||
(fs.first_object->flags & OBJ_TMPFS_NODE) == 0) || | |||||
(fs.first_object->flags & OBJ_MIGHTBEDIRTY) != 0) { | |||||
rv = vm_fault_soft_fast(&fs, vaddr, prot, fault_type, | rv = vm_fault_soft_fast(&fs, vaddr, prot, fault_type, | ||||
fault_flags, wired, m_hold); | fault_flags, wired, m_hold); | ||||
if (rv == KERN_SUCCESS) | if (rv == KERN_SUCCESS) | ||||
return (rv); | return (rv); | ||||
} | |||||
if (!VM_OBJECT_TRYUPGRADE(fs.first_object)) { | if (!VM_OBJECT_TRYUPGRADE(fs.first_object)) { | ||||
VM_OBJECT_RUNLOCK(fs.first_object); | VM_OBJECT_RUNLOCK(fs.first_object); | ||||
VM_OBJECT_WLOCK(fs.first_object); | VM_OBJECT_WLOCK(fs.first_object); | ||||
} | } | ||||
} else { | } else { | ||||
VM_OBJECT_WLOCK(fs.first_object); | VM_OBJECT_WLOCK(fs.first_object); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,168 Lines • Show Last 20 Lines |