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:
yamt 2006-01-31 14:11:25 +00:00
parent 43ed84382c
commit acb669a7cf
3 changed files with 30 additions and 25 deletions

View File

@ -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;
}

View File

@ -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) {

View File

@ -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;