vm_fault: Fix vm_fault_populate()'s handling of VM_FAULT_WIRE
vm_map_wire() works by calling vm_fault(VM_FAULT_WIRE) on each page in the rage. (For largepage mappings, it calls vm_fault() once per large page.) A pager's populate method may return more than one page to be mapped. If VM_FAULT_WIRE is also specified, we'd wire each page in the run, not just the fault page. Consider an object with two pages mapped in a vm_map_entry, and suppose vm_map_wire() is called on the entry. Then, the first vm_fault() would allocate and wire both pages, and the second would encounter a valid page upon lookup and wire it again in the regular fault handler. So the second page is wired twice and will be leaked when the object is destroyed. Fix the problem by modify vm_fault_populate() to wire only the fault page. Also modify the error handler for pmap_enter(psind=1) to not test fs->wired, since it must be false. PR: 260347 Reviewed by: alc, kib MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D33416
This commit is contained in:
parent
509f1a0f40
commit
88642d978a
@ -597,21 +597,23 @@ vm_fault_populate(struct faultstate *fs)
|
||||
(psind > 0 && rv == KERN_PROTECTION_FAILURE));
|
||||
if (__predict_false(psind > 0 &&
|
||||
rv == KERN_PROTECTION_FAILURE)) {
|
||||
MPASS(!fs->wired);
|
||||
for (i = 0; i < npages; i++) {
|
||||
rv = pmap_enter(fs->map->pmap, vaddr + ptoa(i),
|
||||
&m[i], fs->prot, fs->fault_type |
|
||||
(fs->wired ? PMAP_ENTER_WIRED : 0), 0);
|
||||
&m[i], fs->prot, fs->fault_type, 0);
|
||||
MPASS(rv == KERN_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
VM_OBJECT_WLOCK(fs->first_object);
|
||||
for (i = 0; i < npages; i++) {
|
||||
if ((fs->fault_flags & VM_FAULT_WIRE) != 0)
|
||||
if ((fs->fault_flags & VM_FAULT_WIRE) != 0 &&
|
||||
m[i].pindex == fs->first_pindex)
|
||||
vm_page_wire(&m[i]);
|
||||
else
|
||||
vm_page_activate(&m[i]);
|
||||
if (fs->m_hold != NULL && m[i].pindex == fs->first_pindex) {
|
||||
if (fs->m_hold != NULL &&
|
||||
m[i].pindex == fs->first_pindex) {
|
||||
(*fs->m_hold) = &m[i];
|
||||
vm_page_wire(&m[i]);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user