[kernel] r18948 - in dists/squeeze/linux-2.6/debian: . patches/bugfix/x86 patches/features/all/xen patches/series

Ben Hutchings benh at alioth.debian.org
Tue Apr 24 03:37:14 UTC 2012


Author: benh
Date: Tue Apr 24 03:37:12 2012
New Revision: 18948

Log:
[x86] mm: Fix pgd_lock deadlock (Closes: #669335)

This fix was already in the xen featureset had this but not in the
standard patch set.  Fix up the xen patch series accordingly.

Added:
   dists/squeeze/linux-2.6/debian/patches/bugfix/x86/x86-mm-Fix-pgd_lock-deadlock.patch
   dists/squeeze/linux-2.6/debian/patches/series/44
   dists/squeeze/linux-2.6/debian/patches/series/44-extra
      - copied, changed from r18947, dists/squeeze/linux-2.6/debian/patches/series/42-extra
Deleted:
   dists/squeeze/linux-2.6/debian/patches/features/all/xen/x86-mm-Fix-pgd_lock-deadlock.patch
   dists/squeeze/linux-2.6/debian/patches/series/42-extra
Modified:
   dists/squeeze/linux-2.6/debian/changelog
   dists/squeeze/linux-2.6/debian/patches/features/all/xen/x86-mm-Hold-mm-page_table_lock-while-doing-vmalloc_s.patch

Modified: dists/squeeze/linux-2.6/debian/changelog
==============================================================================
--- dists/squeeze/linux-2.6/debian/changelog	Mon Apr 23 05:33:50 2012	(r18947)
+++ dists/squeeze/linux-2.6/debian/changelog	Tue Apr 24 03:37:12 2012	(r18948)
@@ -1,3 +1,10 @@
+linux-2.6 (2.6.32-44) UNRELEASED; urgency=low
+
+  [ Ben Hutchings ]
+  * [x86] mm: Fix pgd_lock deadlock (Closes: #669335)
+
+ -- Ben Hutchings <ben at decadent.org.uk>  Tue, 24 Apr 2012 04:24:55 +0100
+
 linux-2.6 (2.6.32-43) stable; urgency=high
 
   * Ignore arch_pick_mmap_layout ABI change on s390

Added: dists/squeeze/linux-2.6/debian/patches/bugfix/x86/x86-mm-Fix-pgd_lock-deadlock.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/bugfix/x86/x86-mm-Fix-pgd_lock-deadlock.patch	Tue Apr 24 03:37:12 2012	(r18948)
@@ -0,0 +1,224 @@
+From: Andrea Arcangeli <aarcange at redhat.com>
+Date: Wed, 16 Feb 2011 15:45:22 -0800
+Subject: [PATCH] x86/mm: Fix pgd_lock deadlock
+
+commit a79e53d85683c6dd9f99c90511028adc2043031f upstream.
+
+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 at redhat.com>
+Acked-by: Rik van Riel <riel at redhat.com>
+Tested-by: Konrad Rzeszutek Wilk <konrad.wilk at oracle.com>
+Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
+Cc: Peter Zijlstra <peterz at infradead.org>
+Cc: Linus Torvalds <torvalds at linux-foundation.org>
+Cc: <stable at kernel.org>
+LKML-Reference: <201102162345.p1GNjMjm021738 at imap1.linux-foundation.org>
+Signed-off-by: Ingo Molnar <mingo at elte.hu>
+[Backported to 2.6.32 by various people, adjusting context]
+---
+--- a/arch/x86/mm/fault.c
++++ b/arch/x86/mm/fault.c
+@@ -223,15 +223,14 @@ void vmalloc_sync_all(void)
+ 	     address >= TASK_SIZE && address < FIXADDR_TOP;
+ 	     address += PMD_SIZE) {
+ 
+-		unsigned long flags;
+ 		struct page *page;
+ 
+-		spin_lock_irqsave(&pgd_lock, flags);
++		spin_lock(&pgd_lock);
+ 		list_for_each_entry(page, &pgd_list, lru) {
+ 			if (!vmalloc_sync_one(page_address(page), address))
+ 				break;
+ 		}
+-		spin_unlock_irqrestore(&pgd_lock, flags);
++		spin_unlock(&pgd_lock);
+ 	}
+ }
+ 
+@@ -331,13 +330,12 @@ void vmalloc_sync_all(void)
+ 	     address += PGDIR_SIZE) {
+ 
+ 		const pgd_t *pgd_ref = pgd_offset_k(address);
+-		unsigned long flags;
+ 		struct page *page;
+ 
+ 		if (pgd_none(*pgd_ref))
+ 			continue;
+ 
+-		spin_lock_irqsave(&pgd_lock, flags);
++		spin_lock(&pgd_lock);
+ 		list_for_each_entry(page, &pgd_list, lru) {
+ 			pgd_t *pgd;
+ 			pgd = (pgd_t *)page_address(page) + pgd_index(address);
+@@ -346,7 +344,7 @@ void vmalloc_sync_all(void)
+ 			else
+ 				BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
+ 		}
+-		spin_unlock_irqrestore(&pgd_lock, flags);
++		spin_unlock(&pgd_lock);
+ 	}
+ }
+ 
+--- a/arch/x86/mm/pageattr.c
++++ b/arch/x86/mm/pageattr.c
+@@ -56,12 +56,10 @@ static unsigned long direct_pages_count[
+ 
+ void update_page_count(int level, unsigned long pages)
+ {
+-	unsigned long flags;
+-
+ 	/* Protect against CPA */
+-	spin_lock_irqsave(&pgd_lock, flags);
++	spin_lock(&pgd_lock);
+ 	direct_pages_count[level] += pages;
+-	spin_unlock_irqrestore(&pgd_lock, flags);
++	spin_unlock(&pgd_lock);
+ }
+ 
+ static void split_page_count(int level)
+@@ -354,7 +352,7 @@ static int
+ try_preserve_large_page(pte_t *kpte, unsigned long address,
+ 			struct cpa_data *cpa)
+ {
+-	unsigned long nextpage_addr, numpages, pmask, psize, flags, addr, pfn;
++	unsigned long nextpage_addr, numpages, pmask, psize, addr, pfn;
+ 	pte_t new_pte, old_pte, *tmp;
+ 	pgprot_t old_prot, new_prot;
+ 	int i, do_split = 1;
+@@ -363,7 +361,7 @@ try_preserve_large_page(pte_t *kpte, uns
+ 	if (cpa->force_split)
+ 		return 1;
+ 
+-	spin_lock_irqsave(&pgd_lock, flags);
++	spin_lock(&pgd_lock);
+ 	/*
+ 	 * Check for races, another CPU might have split this page
+ 	 * up already:
+@@ -458,14 +456,14 @@ try_preserve_large_page(pte_t *kpte, uns
+ 	}
+ 
+ out_unlock:
+-	spin_unlock_irqrestore(&pgd_lock, flags);
++	spin_unlock(&pgd_lock);
+ 
+ 	return do_split;
+ }
+ 
+ static int split_large_page(pte_t *kpte, unsigned long address)
+ {
+-	unsigned long flags, pfn, pfninc = 1;
++	unsigned long pfn, pfninc = 1;
+ 	unsigned int i, level;
+ 	pte_t *pbase, *tmp;
+ 	pgprot_t ref_prot;
+@@ -479,7 +477,7 @@ static int split_large_page(pte_t *kpte,
+ 	if (!base)
+ 		return -ENOMEM;
+ 
+-	spin_lock_irqsave(&pgd_lock, flags);
++	spin_lock(&pgd_lock);
+ 	/*
+ 	 * Check for races, another CPU might have split this page
+ 	 * up for us already:
+@@ -551,7 +549,7 @@ out_unlock:
+ 	 */
+ 	if (base)
+ 		__free_page(base);
+-	spin_unlock_irqrestore(&pgd_lock, flags);
++	spin_unlock(&pgd_lock);
+ 
+ 	return 0;
+ }
+--- a/arch/x86/mm/pgtable.c
++++ b/arch/x86/mm/pgtable.c
+@@ -110,14 +110,12 @@ static void pgd_ctor(pgd_t *pgd)
+ 
+ static void pgd_dtor(pgd_t *pgd)
+ {
+-	unsigned long flags; /* can be called from interrupt context */
+-
+ 	if (SHARED_KERNEL_PMD)
+ 		return;
+ 
+-	spin_lock_irqsave(&pgd_lock, flags);
++	spin_lock(&pgd_lock);
+ 	pgd_list_del(pgd);
+-	spin_unlock_irqrestore(&pgd_lock, flags);
++	spin_unlock(&pgd_lock);
+ }
+ 
+ /*
+@@ -248,7 +246,6 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+ {
+ 	pgd_t *pgd;
+ 	pmd_t *pmds[PREALLOCATED_PMDS];
+-	unsigned long flags;
+ 
+ 	pgd = (pgd_t *)__get_free_page(PGALLOC_GFP);
+ 
+@@ -268,12 +265,12 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+ 	 * respect to anything walking the pgd_list, so that they
+ 	 * never see a partially populated pgd.
+ 	 */
+-	spin_lock_irqsave(&pgd_lock, flags);
++	spin_lock(&pgd_lock);
+ 
+ 	pgd_ctor(pgd);
+ 	pgd_prepopulate_pmd(mm, pgd, pmds);
+ 
+-	spin_unlock_irqrestore(&pgd_lock, flags);
++	spin_unlock(&pgd_lock);
+ 
+ 	return pgd;
+ 
+--- a/arch/x86/xen/mmu.c
++++ b/arch/x86/xen/mmu.c
+@@ -988,10 +988,9 @@ static void xen_pgd_pin(struct mm_struct
+  */
+ void xen_mm_pin_all(void)
+ {
+-	unsigned long flags;
+ 	struct page *page;
+ 
+-	spin_lock_irqsave(&pgd_lock, flags);
++	spin_lock(&pgd_lock);
+ 
+ 	list_for_each_entry(page, &pgd_list, lru) {
+ 		if (!PagePinned(page)) {
+@@ -1000,7 +999,7 @@ void xen_mm_pin_all(void)
+ 		}
+ 	}
+ 
+-	spin_unlock_irqrestore(&pgd_lock, flags);
++	spin_unlock(&pgd_lock);
+ }
+ 
+ /*
+@@ -1101,10 +1100,9 @@ static void xen_pgd_unpin(struct mm_stru
+  */
+ void xen_mm_unpin_all(void)
+ {
+-	unsigned long flags;
+ 	struct page *page;
+ 
+-	spin_lock_irqsave(&pgd_lock, flags);
++	spin_lock(&pgd_lock);
+ 
+ 	list_for_each_entry(page, &pgd_list, lru) {
+ 		if (PageSavePinned(page)) {
+@@ -1114,7 +1112,7 @@ void xen_mm_unpin_all(void)
+ 		}
+ 	}
+ 
+-	spin_unlock_irqrestore(&pgd_lock, flags);
++	spin_unlock(&pgd_lock);
+ }
+ 
+ void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next)

Modified: dists/squeeze/linux-2.6/debian/patches/features/all/xen/x86-mm-Hold-mm-page_table_lock-while-doing-vmalloc_s.patch
==============================================================================
--- dists/squeeze/linux-2.6/debian/patches/features/all/xen/x86-mm-Hold-mm-page_table_lock-while-doing-vmalloc_s.patch	Mon Apr 23 05:33:50 2012	(r18947)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/xen/x86-mm-Hold-mm-page_table_lock-while-doing-vmalloc_s.patch	Tue Apr 24 03:37:12 2012	(r18948)
@@ -21,6 +21,8 @@
 LKML-Reference: <4CB88A4C.1080305 at goop.org>
 Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge at citrix.com>
 Signed-off-by: H. Peter Anvin <hpa at linux.intel.com>
+[bwh: Adjust context to apply after backported commit
+ a79e53d85683c6dd9f99c90511028adc2043031f 'x86/mm: Fix pgd_lock deadlock']
 ---
  arch/x86/include/asm/pgtable.h |    2 ++
  arch/x86/mm/fault.c            |   11 ++++++++++-
@@ -28,8 +30,6 @@
  arch/x86/mm/pgtable.c          |   20 +++++++++++++++++---
  4 files changed, 36 insertions(+), 4 deletions(-)
 
-diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
-index 2d0a33b..ada823a 100644
 --- a/arch/x86/include/asm/pgtable.h
 +++ b/arch/x86/include/asm/pgtable.h
 @@ -28,6 +28,8 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
@@ -41,13 +41,11 @@
  #ifdef CONFIG_PARAVIRT
  #include <asm/paravirt.h>
  #else  /* !CONFIG_PARAVIRT */
-diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
-index caec229..6c27c39 100644
 --- a/arch/x86/mm/fault.c
 +++ b/arch/x86/mm/fault.c
 @@ -229,7 +229,16 @@ void vmalloc_sync_all(void)
  
- 		spin_lock_irqsave(&pgd_lock, flags);
+ 		spin_lock(&pgd_lock);
  		list_for_each_entry(page, &pgd_list, lru) {
 -			if (!vmalloc_sync_one(page_address(page), address))
 +			spinlock_t *pgt_lock;
@@ -62,9 +60,9 @@
 +			if (!ret)
  				break;
  		}
- 		spin_unlock_irqrestore(&pgd_lock, flags);
+ 		spin_unlock(&pgd_lock);
 @@ -349,11 +349,19 @@
- 		spin_lock_irqsave(&pgd_lock, flags);
+ 		spin_lock(&pgd_lock);
  		list_for_each_entry(page, &pgd_list, lru) {
  			pgd_t *pgd;
 +			spinlock_t *pgt_lock;
@@ -81,10 +79,8 @@
 +
 +			spin_unlock(pgt_lock);
  		}
- 		spin_unlock_irqrestore(&pgd_lock, flags);
+ 		spin_unlock(&pgd_lock);
  	}
-diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
-index 5c4ee42..c70e57d 100644
 --- a/arch/x86/mm/pgtable.c
 +++ b/arch/x86/mm/pgtable.c
 @@ -87,7 +87,19 @@ static inline void pgd_list_del(pgd_t *pgd)
@@ -122,13 +118,10 @@
  static void pgd_dtor(pgd_t *pgd)
 @@ -272,7 +286,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
  	 */
- 	spin_lock_irqsave(&pgd_lock, flags);
+ 	spin_lock(&pgd_lock);
  
 -	pgd_ctor(pgd);
 +	pgd_ctor(mm, pgd);
  	pgd_prepopulate_pmd(mm, pgd, pmds);
  
- 	spin_unlock_irqrestore(&pgd_lock, flags);
--- 
-1.7.4.1
-
+ 	spin_unlock(&pgd_lock);

Added: dists/squeeze/linux-2.6/debian/patches/series/44
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/series/44	Tue Apr 24 03:37:12 2012	(r18948)
@@ -0,0 +1 @@
++ bugfix/x86/x86-mm-Fix-pgd_lock-deadlock.patch

Copied and modified: dists/squeeze/linux-2.6/debian/patches/series/44-extra (from r18947, dists/squeeze/linux-2.6/debian/patches/series/42-extra)
==============================================================================
--- dists/squeeze/linux-2.6/debian/patches/series/42-extra	Mon Apr 23 05:33:50 2012	(r18947, copy source)
+++ dists/squeeze/linux-2.6/debian/patches/series/44-extra	Tue Apr 24 03:37:12 2012	(r18948)
@@ -40,7 +40,6 @@
 + features/all/xen/x86-mm-Hold-mm-page_table_lock-while-doing-vmalloc_s.patch featureset=xen
 + features/all/xen/x86-mm-Fix-incorrect-data-type-in-vmalloc_sync_all.patch featureset=xen
 + features/all/xen/vmalloc-eagerly-clear-ptes-on-vunmap.patch featureset=xen
-+ features/all/xen/x86-mm-Fix-pgd_lock-deadlock.patch featureset=xen
 
 + features/all/xen/xen-apic-use-handle_edge_irq-for-pirq-events.patch featureset=xen
 + features/all/xen/xen-pirq-do-EOI-properly-for-pirq-events.patch featureset=xen



More information about the Kernel-svn-changes mailing list