diff options
| author | Andrea Arcangeli <aarcange@redhat.com> | 2011-02-16 18:45:22 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2011-03-10 03:41:57 -0500 |
| commit | a79e53d85683c6dd9f99c90511028adc2043031f (patch) | |
| tree | 191f423331b608a5f7f134f484ce62a9ee7fb4a6 /arch/x86/mm/fault.c | |
| parent | f86268549f424f83b9eb0963989270e14fbfc3de (diff) | |
x86/mm: Fix pgd_lock deadlock
It's forbidden to take the page_table_lock with the irq disabled
or if there's contention the IPIs (for tlb flushes) sent with
the page_table_lock held will never run leading to a deadlock.
Nobody takes the pgd_lock from irq context so the _irqsave can be
removed.
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Acked-by: Rik van Riel <riel@redhat.com>
Tested-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: <stable@kernel.org>
LKML-Reference: <201102162345.p1GNjMjm021738@imap1.linux-foundation.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/mm/fault.c')
| -rw-r--r-- | arch/x86/mm/fault.c | 7 |
1 files changed, 3 insertions, 4 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index ffc7be104fc2..20e3f8702d1e 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
| @@ -229,15 +229,14 @@ void vmalloc_sync_all(void) | |||
| 229 | for (address = VMALLOC_START & PMD_MASK; | 229 | for (address = VMALLOC_START & PMD_MASK; |
| 230 | address >= TASK_SIZE && address < FIXADDR_TOP; | 230 | address >= TASK_SIZE && address < FIXADDR_TOP; |
| 231 | address += PMD_SIZE) { | 231 | address += PMD_SIZE) { |
| 232 | |||
| 233 | unsigned long flags; | ||
| 234 | struct page *page; | 232 | struct page *page; |
| 235 | 233 | ||
| 236 | spin_lock_irqsave(&pgd_lock, flags); | 234 | spin_lock(&pgd_lock); |
| 237 | list_for_each_entry(page, &pgd_list, lru) { | 235 | list_for_each_entry(page, &pgd_list, lru) { |
| 238 | spinlock_t *pgt_lock; | 236 | spinlock_t *pgt_lock; |
| 239 | pmd_t *ret; | 237 | pmd_t *ret; |
| 240 | 238 | ||
| 239 | /* the pgt_lock only for Xen */ | ||
| 241 | pgt_lock = &pgd_page_get_mm(page)->page_table_lock; | 240 | pgt_lock = &pgd_page_get_mm(page)->page_table_lock; |
| 242 | 241 | ||
| 243 | spin_lock(pgt_lock); | 242 | spin_lock(pgt_lock); |
| @@ -247,7 +246,7 @@ void vmalloc_sync_all(void) | |||
| 247 | if (!ret) | 246 | if (!ret) |
| 248 | break; | 247 | break; |
| 249 | } | 248 | } |
| 250 | spin_unlock_irqrestore(&pgd_lock, flags); | 249 | spin_unlock(&pgd_lock); |
| 251 | } | 250 | } |
| 252 | } | 251 | } |
| 253 | 252 | ||
