aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKirill A. Shutemov <kirill.shutemov@linux.intel.com>2013-11-21 17:32:09 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-11-21 19:42:28 -0500
commitc283610e44ec4ccc412dde8b71cf297ed9515f2f (patch)
treedd3c83db8dabefbeb3733cd428cced7c62602beb
parent3a72660b07d86d60457ca32080b1ce8c2b628ee2 (diff)
x86, mm: do not leak page->ptl for pmd page tables
There are two code paths how page with pmd page table can be freed: pmd_free() and pmd_free_tlb(). I've missed the second one and didn't add page table destructor call there. It leads to leak of page->ptl for pmd page tables, if dynamically allocated page->ptl is in use. The patch adds the missed destructor and modifies documentation accordingly. Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Reported-by: Andrey Vagin <avagin@openvz.org> Tested-by: Andrey Vagin <avagin@openvz.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--Documentation/vm/split_page_table_lock6
-rw-r--r--arch/x86/mm/pgtable.c4
2 files changed, 6 insertions, 4 deletions
diff --git a/Documentation/vm/split_page_table_lock b/Documentation/vm/split_page_table_lock
index 7521d367f21d..6dea4fd5c961 100644
--- a/Documentation/vm/split_page_table_lock
+++ b/Documentation/vm/split_page_table_lock
@@ -63,9 +63,9 @@ levels.
63PMD split lock enabling requires pgtable_pmd_page_ctor() call on PMD table 63PMD split lock enabling requires pgtable_pmd_page_ctor() call on PMD table
64allocation and pgtable_pmd_page_dtor() on freeing. 64allocation and pgtable_pmd_page_dtor() on freeing.
65 65
66Allocation usually happens in pmd_alloc_one(), freeing in pmd_free(), but 66Allocation usually happens in pmd_alloc_one(), freeing in pmd_free() and
67make sure you cover all PMD table allocation / freeing paths: i.e X86_PAE 67pmd_free_tlb(), but make sure you cover all PMD table allocation / freeing
68preallocate few PMDs on pgd_alloc(). 68paths: i.e X86_PAE preallocate few PMDs on pgd_alloc().
69 69
70With everything in place you can set CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK. 70With everything in place you can set CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK.
71 71
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
index 36aa999b2631..c96314abd144 100644
--- a/arch/x86/mm/pgtable.c
+++ b/arch/x86/mm/pgtable.c
@@ -61,6 +61,7 @@ void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
61#if PAGETABLE_LEVELS > 2 61#if PAGETABLE_LEVELS > 2
62void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd) 62void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
63{ 63{
64 struct page *page = virt_to_page(pmd);
64 paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT); 65 paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT);
65 /* 66 /*
66 * NOTE! For PAE, any changes to the top page-directory-pointer-table 67 * NOTE! For PAE, any changes to the top page-directory-pointer-table
@@ -69,7 +70,8 @@ void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
69#ifdef CONFIG_X86_PAE 70#ifdef CONFIG_X86_PAE
70 tlb->need_flush_all = 1; 71 tlb->need_flush_all = 1;
71#endif 72#endif
72 tlb_remove_page(tlb, virt_to_page(pmd)); 73 pgtable_pmd_page_dtor(page);
74 tlb_remove_page(tlb, page);
73} 75}
74 76
75#if PAGETABLE_LEVELS > 3 77#if PAGETABLE_LEVELS > 3