diff options
author | Anton Blanchard <anton@samba.org> | 2011-09-14 05:43:15 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2011-09-20 01:53:23 -0400 |
commit | 8bdafa39a47265bc029838b35cc6585f69224afa (patch) | |
tree | cade05d9d67d3c6c421f46012961a46dacae5d70 /arch/powerpc/mm/mmu_context_hash64.c | |
parent | a11940978bd598e65996b4f807cf4904793f7025 (diff) |
powerpc: Fix deadlock in icswx code
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>
Cc: <stable@kernel.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/mm/mmu_context_hash64.c')
-rw-r--r-- | arch/powerpc/mm/mmu_context_hash64.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/arch/powerpc/mm/mmu_context_hash64.c b/arch/powerpc/mm/mmu_context_hash64.c index 3bafc3deca6d..4ff587e38250 100644 --- 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 mm_struct *mm) | |||
136 | if (!mm || !acop) | 136 | if (!mm || !acop) |
137 | return -EINVAL; | 137 | return -EINVAL; |
138 | 138 | ||
139 | /* We need to make sure mm_users doesn't change */ | 139 | /* The page_table_lock ensures mm_users won't change under us */ |
140 | down_read(&mm->mmap_sem); | 140 | spin_lock(&mm->page_table_lock); |
141 | spin_lock(mm->context.cop_lockp); | 141 | spin_lock(mm->context.cop_lockp); |
142 | 142 | ||
143 | if (mm->context.cop_pid == COP_PID_NONE) { | 143 | if (mm->context.cop_pid == COP_PID_NONE) { |
@@ -164,7 +164,7 @@ int use_cop(unsigned long acop, struct mm_struct *mm) | |||
164 | 164 | ||
165 | out: | 165 | out: |
166 | spin_unlock(mm->context.cop_lockp); | 166 | spin_unlock(mm->context.cop_lockp); |
167 | up_read(&mm->mmap_sem); | 167 | spin_unlock(&mm->page_table_lock); |
168 | 168 | ||
169 | return ret; | 169 | return ret; |
170 | } | 170 | } |
@@ -185,8 +185,8 @@ void drop_cop(unsigned long acop, struct mm_struct *mm) | |||
185 | if (WARN_ON_ONCE(!mm)) | 185 | if (WARN_ON_ONCE(!mm)) |
186 | return; | 186 | return; |
187 | 187 | ||
188 | /* We need to make sure mm_users doesn't change */ | 188 | /* The page_table_lock ensures mm_users won't change under us */ |
189 | down_read(&mm->mmap_sem); | 189 | spin_lock(&mm->page_table_lock); |
190 | spin_lock(mm->context.cop_lockp); | 190 | spin_lock(mm->context.cop_lockp); |
191 | 191 | ||
192 | mm->context.acop &= ~acop; | 192 | mm->context.acop &= ~acop; |
@@ -213,7 +213,7 @@ void drop_cop(unsigned long acop, struct mm_struct *mm) | |||
213 | } | 213 | } |
214 | 214 | ||
215 | spin_unlock(mm->context.cop_lockp); | 215 | spin_unlock(mm->context.cop_lockp); |
216 | up_read(&mm->mmap_sem); | 216 | spin_unlock(&mm->page_table_lock); |
217 | } | 217 | } |
218 | EXPORT_SYMBOL_GPL(drop_cop); | 218 | EXPORT_SYMBOL_GPL(drop_cop); |
219 | 219 | ||