tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: vmpage race and deadlock
Juergen Hannken-Illjes <hannken%eis.cs.tu-bs.de@localhost> wrote:
> Some weeks ago I started my fs stress test (5 x fsstress+fsx+dbench)
> on a log enabled ffs1 file system backed by md(4).
>
> Usually within hours I get a deadlock where a thread is waiting on
> "genput" but the page in question is neither BUSY nor WANTED. I suppose
> I tracked (*1) it down to three places, where we change page flags
> without holding the object lock. With this diff (*2) in place the test
> runs for > 48 hours.
Cool!
> Using atomic ops here is not possible as flags is a 16bit value.
>
You cannot use them at one place; in such case all uses i.e. protocol
would need to be converted to atomic ops.
> @@ -637,8 +639,9 @@ loopdone:
> npages << PAGE_SHIFT, 0, cred);
> UVMHIST_LOG(ubchist, "gop_alloc off 0x%x/0x%x -> %d",
> startoffset, npages << PAGE_SHIFT, error,0);
> if (!error) {
> + mutex_enter(&uobj->vmobjlock);
> for (i = 0; i < npages; i++) {
> struct vm_page *pg = pgs[i];
>
> if (pg == NULL) {
> @@ -647,8 +650,9 @@ loopdone:
> pg->flags &= ~(PG_CLEAN|PG_RDONLY);
> UVMHIST_LOG(ubchist, "mark dirty pg %p",
> pg,0,0,0);
> }
> + mutex_exit(&uobj->vmobjlock);
> }
> }
> if (!glocked) {
> genfs_node_unlock(vp);
I think this loop can actually be moved after mutex_enter(&uobj->vmobjlock)
at line 660 (with condition check, of course).
> Index: sys/uvm/uvm_bio.c
> ===================================================================
> RCS file: /cvsroot/src/sys/uvm/uvm_bio.c,v
> retrieving revision 1.70
> diff -p -u -4 -r1.70 uvm_bio.c
> --- sys/uvm/uvm_bio.c 22 Jun 2010 18:34:50 -0000 1.70
> +++ sys/uvm/uvm_bio.c 22 Nov 2010 09:11:18 -0000
> @@ -644,8 +644,9 @@ ubc_release(void *va, int flags)
> if (zerolen) {
> memset((char *)umapva + endoff, 0, zerolen);
> }
> umap->flags &= ~UMAP_PAGES_LOCKED;
> + mutex_enter(&uobj->vmobjlock);
> mutex_enter(&uvm_pageqlock);
> for (i = 0; i < npages; i++) {
> rv = pmap_extract(pmap_kernel(),
> umapva + slot_offset + (i << PAGE_SHIFT), &pa);
> @@ -657,9 +658,8 @@ ubc_release(void *va, int flags)
> }
> mutex_exit(&uvm_pageqlock);
> pmap_kremove(umapva, ubc_winsize);
> pmap_update(pmap_kernel());
> - mutex_enter(&uobj->vmobjlock);
> uvm_page_unbusy(pgs, npages);
> mutex_exit(&uobj->vmobjlock);
> unmapped = true;
> } else {
This one is already made in rmind-uvplock branch.
Thanks for catching these!
--
Mindaugas
Home |
Main Index |
Thread Index |
Old Index