[POWERPC] spufs: fix context destruction during psmap fault
We have a small window where a spu context may be destroyed while we're servicing a page fault (from another thread) to the context's problem state mapping. After we up_read() the mmap_sem, it's possible that the context is destroyed by its owning thread, and so the later references to ctx are invalid. This can maifest as a deadlock on the (now free()-ed) context state mutex. This change adds a reference to the context before we release the mmap_sem, so that the context cannot be destroyed. Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
This commit is contained in:
@@ -366,6 +366,13 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma,
|
|||||||
if (offset >= ps_size)
|
if (offset >= ps_size)
|
||||||
return NOPFN_SIGBUS;
|
return NOPFN_SIGBUS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Because we release the mmap_sem, the context may be destroyed while
|
||||||
|
* we're in spu_wait. Grab an extra reference so it isn't destroyed
|
||||||
|
* in the meantime.
|
||||||
|
*/
|
||||||
|
get_spu_context(ctx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have to wait for context to be loaded before we have
|
* We have to wait for context to be loaded before we have
|
||||||
* pages to hand out to the user, but we don't want to wait
|
* pages to hand out to the user, but we don't want to wait
|
||||||
@@ -375,7 +382,7 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma,
|
|||||||
* hanged.
|
* hanged.
|
||||||
*/
|
*/
|
||||||
if (spu_acquire(ctx))
|
if (spu_acquire(ctx))
|
||||||
return NOPFN_REFAULT;
|
goto refault;
|
||||||
|
|
||||||
if (ctx->state == SPU_STATE_SAVED) {
|
if (ctx->state == SPU_STATE_SAVED) {
|
||||||
up_read(¤t->mm->mmap_sem);
|
up_read(¤t->mm->mmap_sem);
|
||||||
@@ -391,6 +398,9 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma,
|
|||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
spu_release(ctx);
|
spu_release(ctx);
|
||||||
|
|
||||||
|
refault:
|
||||||
|
put_spu_context(ctx);
|
||||||
return NOPFN_REFAULT;
|
return NOPFN_REFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user