| From 8bdafa39a47265bc029838b35cc6585f69224afa Mon Sep 17 00:00:00 2001 |
| From: Anton Blanchard <anton@samba.org> |
| Date: Wed, 14 Sep 2011 09:43:15 +0000 |
| Subject: powerpc: Fix deadlock in icswx code |
| |
| From: Anton Blanchard <anton@samba.org> |
| |
| commit 8bdafa39a47265bc029838b35cc6585f69224afa upstream. |
| |
| The icswx code introduced an A-B B-A deadlock: |
| |
| CPU0 CPU1 |
| ---- ---- |
| lock(&anon_vma->mutex); |
| lock(&mm->mmap_sem); |
| lock(&anon_vma->mutex); |
| lock(&mm->mmap_sem); |
| |
| Instead of using the mmap_sem to keep mm_users constant, take the |
| page table spinlock. |
| |
| Signed-off-by: Anton Blanchard <anton@samba.org> |
| Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| arch/powerpc/mm/mmu_context_hash64.c | 12 ++++++------ |
| 1 file changed, 6 insertions(+), 6 deletions(-) |
| |
| --- a/arch/powerpc/mm/mmu_context_hash64.c |
| +++ b/arch/powerpc/mm/mmu_context_hash64.c |
| @@ -136,8 +136,8 @@ int use_cop(unsigned long acop, struct m |
| if (!mm || !acop) |
| return -EINVAL; |
| |
| - /* We need to make sure mm_users doesn't change */ |
| - down_read(&mm->mmap_sem); |
| + /* The page_table_lock ensures mm_users won't change under us */ |
| + spin_lock(&mm->page_table_lock); |
| spin_lock(mm->context.cop_lockp); |
| |
| if (mm->context.cop_pid == COP_PID_NONE) { |
| @@ -164,7 +164,7 @@ int use_cop(unsigned long acop, struct m |
| |
| out: |
| spin_unlock(mm->context.cop_lockp); |
| - up_read(&mm->mmap_sem); |
| + spin_unlock(&mm->page_table_lock); |
| |
| return ret; |
| } |
| @@ -185,8 +185,8 @@ void drop_cop(unsigned long acop, struct |
| if (WARN_ON_ONCE(!mm)) |
| return; |
| |
| - /* We need to make sure mm_users doesn't change */ |
| - down_read(&mm->mmap_sem); |
| + /* The page_table_lock ensures mm_users won't change under us */ |
| + spin_lock(&mm->page_table_lock); |
| spin_lock(mm->context.cop_lockp); |
| |
| mm->context.acop &= ~acop; |
| @@ -213,7 +213,7 @@ void drop_cop(unsigned long acop, struct |
| } |
| |
| spin_unlock(mm->context.cop_lockp); |
| - up_read(&mm->mmap_sem); |
| + spin_unlock(&mm->page_table_lock); |
| } |
| EXPORT_SYMBOL_GPL(drop_cop); |
| |