handle "strange" filesystems like layered filesystems and tmpfs,
where pgo_get returns pages which don't belong to the uobj. also fix an XXX in uvm_loananon and lock-unlock mismatch in uvm_loanuobj. PR/28372, PR/32665 (Alan Barrett).
This commit is contained in:
parent
43ed84382c
commit
acb669a7cf
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: uvm_bio.c,v 1.42 2005/11/29 22:52:03 yamt Exp $ */
|
||||
/* $NetBSD: uvm_bio.c,v 1.43 2006/01/31 14:11:25 yamt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Chuck Silvers.
|
||||
@ -34,7 +34,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: uvm_bio.c,v 1.42 2005/11/29 22:52:03 yamt Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: uvm_bio.c,v 1.43 2006/01/31 14:11:25 yamt Exp $");
|
||||
|
||||
#include "opt_uvmhist.h"
|
||||
|
||||
@ -294,8 +294,6 @@ again:
|
||||
eva = ufi->orig_rvaddr + (npages << PAGE_SHIFT);
|
||||
|
||||
UVMHIST_LOG(ubchist, "va 0x%lx eva 0x%lx", va, eva, 0, 0);
|
||||
simple_lock(&uobj->vmobjlock);
|
||||
uvm_lock_pageq();
|
||||
for (i = 0; va < eva; i++, va += PAGE_SIZE) {
|
||||
boolean_t rdonly;
|
||||
vm_prot_t mask;
|
||||
@ -319,12 +317,18 @@ again:
|
||||
if (pg == NULL || pg == PGO_DONTCARE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uobj = pg->uobject;
|
||||
simple_lock(&uobj->vmobjlock);
|
||||
if (pg->flags & PG_WANTED) {
|
||||
wakeup(pg);
|
||||
}
|
||||
KASSERT((pg->flags & PG_FAKE) == 0);
|
||||
if (pg->flags & PG_RELEASED) {
|
||||
uvm_lock_pageq();
|
||||
uvm_pagefree(pg);
|
||||
uvm_unlock_pageq();
|
||||
simple_unlock(&uobj->vmobjlock);
|
||||
continue;
|
||||
}
|
||||
if (pg->loan_count != 0) {
|
||||
@ -337,9 +341,7 @@ again:
|
||||
prot &= ~VM_PROT_WRITE;
|
||||
|
||||
if (prot & VM_PROT_WRITE) {
|
||||
uvm_unlock_pageq();
|
||||
pg = uvm_loanbreak(pg);
|
||||
uvm_lock_pageq();
|
||||
if (pg == NULL)
|
||||
continue; /* will re-fault */
|
||||
}
|
||||
@ -359,12 +361,13 @@ again:
|
||||
mask = rdonly ? ~VM_PROT_WRITE : VM_PROT_ALL;
|
||||
pmap_enter(ufi->orig_map->pmap, va, VM_PAGE_TO_PHYS(pg),
|
||||
prot & mask, access_type & mask);
|
||||
uvm_lock_pageq();
|
||||
uvm_pageactivate(pg);
|
||||
uvm_unlock_pageq();
|
||||
pg->flags &= ~(PG_BUSY);
|
||||
UVM_PAGE_OWN(pg, NULL);
|
||||
simple_unlock(&uobj->vmobjlock);
|
||||
}
|
||||
uvm_unlock_pageq();
|
||||
simple_unlock(&uobj->vmobjlock);
|
||||
pmap_update(ufi->orig_map->pmap);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: uvm_fault.c,v 1.106 2006/01/31 14:05:47 yamt Exp $ */
|
||||
/* $NetBSD: uvm_fault.c,v 1.107 2006/01/31 14:11:25 yamt Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
@ -39,7 +39,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: uvm_fault.c,v 1.106 2006/01/31 14:05:47 yamt Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: uvm_fault.c,v 1.107 2006/01/31 14:11:25 yamt Exp $");
|
||||
|
||||
#include "opt_uvmhist.h"
|
||||
|
||||
@ -570,7 +570,6 @@ uvmfault_promote(struct uvm_faultinfo *ufi,
|
||||
} else if (uobjpage != PGO_DONTCARE) {
|
||||
/* object-backed COW */
|
||||
opg = uobjpage;
|
||||
KASSERT(opg->uobject == ufi->entry->object.uvm_obj);
|
||||
} else {
|
||||
/* ZFOD */
|
||||
opg = NULL;
|
||||
@ -1071,6 +1070,7 @@ ReFault:
|
||||
if (curpg == NULL || curpg == PGO_DONTCARE) {
|
||||
continue;
|
||||
}
|
||||
KASSERT(curpg->uobject == uobj);
|
||||
|
||||
/*
|
||||
* if center page is resident and not
|
||||
@ -1513,6 +1513,7 @@ Case2:
|
||||
locked = uvmfault_relock(&ufi);
|
||||
if (locked && amap)
|
||||
amap_lock(amap);
|
||||
uobj = uobjpage->uobject;
|
||||
simple_lock(&uobj->vmobjlock);
|
||||
|
||||
/* locked(locked): maps(read), amap(if !null), uobj, uobjpage */
|
||||
@ -1576,6 +1577,7 @@ Case2:
|
||||
* - at this point uobjpage could be PG_WANTED (handle later)
|
||||
*/
|
||||
|
||||
KASSERT(uobj == NULL || uobj == uobjpage->uobject);
|
||||
KASSERT(uobj == NULL || !UVM_OBJ_IS_CLEAN(uobjpage->uobject) ||
|
||||
(uobjpage->flags & PG_CLEAN) != 0);
|
||||
if (promote == FALSE) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: uvm_loan.c,v 1.57 2005/12/24 20:45:10 perry Exp $ */
|
||||
/* $NetBSD: uvm_loan.c,v 1.58 2006/01/31 14:11:25 yamt Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
@ -39,7 +39,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: uvm_loan.c,v 1.57 2005/12/24 20:45:10 perry Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: uvm_loan.c,v 1.58 2006/01/31 14:11:25 yamt Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -155,8 +155,6 @@ uvm_loanentry(struct uvm_faultinfo *ufi, void ***output, int flags)
|
||||
*/
|
||||
if (aref->ar_amap)
|
||||
amap_lock(aref->ar_amap);
|
||||
if (uobj)
|
||||
simple_lock(&uobj->vmobjlock);
|
||||
|
||||
/*
|
||||
* loop until done
|
||||
@ -218,8 +216,6 @@ uvm_loanentry(struct uvm_faultinfo *ufi, void ***output, int flags)
|
||||
|
||||
if (aref->ar_amap)
|
||||
amap_unlock(aref->ar_amap);
|
||||
if (uobj)
|
||||
simple_unlock(&uobj->vmobjlock);
|
||||
uvmfault_unlockmaps(ufi, FALSE);
|
||||
UVMHIST_LOG(loanhist, "done %d", result, 0,0,0);
|
||||
return (result);
|
||||
@ -426,7 +422,7 @@ uvm_loananon(struct uvm_faultinfo *ufi, void ***output, int flags,
|
||||
UVMHIST_LOG(loanhist, "->K wired %p", pg,0,0,0);
|
||||
KASSERT(pg->uobject == NULL);
|
||||
uvmfault_unlockall(ufi, ufi->entry->aref.ar_amap,
|
||||
ufi->entry->object.uvm_obj, anon);
|
||||
NULL, anon);
|
||||
return (-1);
|
||||
}
|
||||
if (pg->loan_count == 0) {
|
||||
@ -439,7 +435,7 @@ uvm_loananon(struct uvm_faultinfo *ufi, void ***output, int flags,
|
||||
(*output)++;
|
||||
|
||||
/* unlock anon and return success */
|
||||
if (pg->uobject) /* XXXCDC: what if this is our uobj? bad */
|
||||
if (pg->uobject)
|
||||
simple_unlock(&pg->uobject->vmobjlock);
|
||||
simple_unlock(&anon->an_lock);
|
||||
UVMHIST_LOG(loanhist, "->K done", 0,0,0,0);
|
||||
@ -642,6 +638,7 @@ uvm_loanuobj(struct uvm_faultinfo *ufi, void ***output, int flags, vaddr_t va)
|
||||
* XXXCDC: duplicate code with uvm_fault().
|
||||
*/
|
||||
|
||||
simple_lock(&uobj->vmobjlock);
|
||||
if (uobj->pgops->pgo_get) { /* try locked pgo_get */
|
||||
npages = 1;
|
||||
pg = NULL;
|
||||
@ -691,6 +688,7 @@ uvm_loanuobj(struct uvm_faultinfo *ufi, void ***output, int flags, vaddr_t va)
|
||||
locked = uvmfault_relock(ufi);
|
||||
if (locked && amap)
|
||||
amap_lock(amap);
|
||||
uobj = pg->uobject;
|
||||
simple_lock(&uobj->vmobjlock);
|
||||
|
||||
/*
|
||||
@ -719,6 +717,7 @@ uvm_loanuobj(struct uvm_faultinfo *ufi, void ***output, int flags, vaddr_t va)
|
||||
uvm_lock_pageq();
|
||||
uvm_pagefree(pg);
|
||||
uvm_unlock_pageq();
|
||||
simple_unlock(&uobj->vmobjlock);
|
||||
return (0);
|
||||
}
|
||||
uvm_lock_pageq();
|
||||
@ -731,6 +730,8 @@ uvm_loanuobj(struct uvm_faultinfo *ufi, void ***output, int flags, vaddr_t va)
|
||||
}
|
||||
}
|
||||
|
||||
KASSERT(uobj == pg->uobject);
|
||||
|
||||
/*
|
||||
* at this point we have the page we want ("pg") marked PG_BUSY for us
|
||||
* and we have all data structures locked. do the loanout. page can
|
||||
@ -742,6 +743,7 @@ uvm_loanuobj(struct uvm_faultinfo *ufi, void ***output, int flags, vaddr_t va)
|
||||
uvmfault_unlockall(ufi, amap, uobj, NULL);
|
||||
return (-1);
|
||||
}
|
||||
simple_unlock(&uobj->vmobjlock);
|
||||
**output = pg;
|
||||
(*output)++;
|
||||
return (1);
|
||||
@ -764,6 +766,7 @@ uvm_loanuobj(struct uvm_faultinfo *ufi, void ***output, int flags, vaddr_t va)
|
||||
}
|
||||
pg->flags &= ~(PG_WANTED|PG_BUSY);
|
||||
UVM_PAGE_OWN(pg, NULL);
|
||||
simple_unlock(&uobj->vmobjlock);
|
||||
**output = anon;
|
||||
(*output)++;
|
||||
return (1);
|
||||
@ -801,6 +804,7 @@ uvm_loanuobj(struct uvm_faultinfo *ufi, void ***output, int flags, vaddr_t va)
|
||||
}
|
||||
pg->flags &= ~(PG_WANTED|PG_BUSY);
|
||||
UVM_PAGE_OWN(pg, NULL);
|
||||
simple_unlock(&uobj->vmobjlock);
|
||||
simple_unlock(&anon->an_lock);
|
||||
**output = anon;
|
||||
(*output)++;
|
||||
@ -838,7 +842,6 @@ uvm_loanzero(struct uvm_faultinfo *ufi, void ***output, int flags)
|
||||
{
|
||||
struct vm_anon *anon;
|
||||
struct vm_page *pg;
|
||||
struct uvm_object *uobj = ufi->entry->object.uvm_obj;
|
||||
struct vm_amap *amap = ufi->entry->aref.ar_amap;
|
||||
|
||||
UVMHIST_FUNC(__func__); UVMHIST_CALLED(loanhist);
|
||||
@ -854,7 +857,7 @@ again:
|
||||
while ((pg = uvm_pagealloc(&uvm_loanzero_object, 0, NULL,
|
||||
UVM_PGA_ZERO)) == NULL) {
|
||||
simple_unlock(&uvm_loanzero_object.vmobjlock);
|
||||
uvmfault_unlockall(ufi, amap, uobj, NULL);
|
||||
uvmfault_unlockall(ufi, amap, NULL, NULL);
|
||||
uvm_wait("loanzero");
|
||||
if (!uvmfault_relock(ufi)) {
|
||||
return (0);
|
||||
@ -862,9 +865,6 @@ again:
|
||||
if (amap) {
|
||||
amap_lock(amap);
|
||||
}
|
||||
if (uobj) {
|
||||
simple_lock(&uobj->vmobjlock);
|
||||
}
|
||||
goto again;
|
||||
}
|
||||
|
||||
@ -913,7 +913,7 @@ again:
|
||||
if (anon == NULL) {
|
||||
/* out of swap causes us to fail */
|
||||
simple_unlock(&uvm_loanzero_object.vmobjlock);
|
||||
uvmfault_unlockall(ufi, amap, uobj, NULL);
|
||||
uvmfault_unlockall(ufi, amap, NULL, NULL);
|
||||
return (-1);
|
||||
}
|
||||
anon->an_page = pg;
|
||||
|
Loading…
Reference in New Issue
Block a user