]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] hugepage pagetable freeing fix
authorAndrew Morton <akpm@osdl.org>
Tue, 30 Dec 2003 07:47:37 +0000 (23:47 -0800)
committerLinus Torvalds <torvalds@home.osdl.org>
Tue, 30 Dec 2003 07:47:37 +0000 (23:47 -0800)
From: "Seth, Rohit" <rohit.seth@intel.com>

We recently covered a bug in mm/mmap.c on IA-64.  While unmapping a address
space, unmap_region calls free_pgtables to possibly free the pages that are
used for page tables.  Currently no distinction is made between freeing a
region that is mapped by normal pages vs the pages that are mapped by
hugepages.  Architecture specific code needs to handle cases where PTEs
corresponding to a region that is mapped by hugepages is properly getting
unmapped.  Attached please find a patch that makes the required changes in
generic part of kernel.  We will need to send a separate IA-64 patch to use
this new semantics.  Currently, so not to disturb the PPC (as that is the
only arch that had ARCH_HAS_HUGEPAGE_ONLY_RANGE defined) we are mapping back
the definition of new function hugetlb_free_pgtables to free_pgtables.

include/asm-ppc64/page.h
include/linux/hugetlb.h
mm/mmap.c

index 29e5738f7180613999188492011dc2ce098452d0..5674054309ef92b2258ecb684c63b71e7727f4bd 100644 (file)
@@ -41,6 +41,7 @@
        ( ((addr > (TASK_HPAGE_BASE-len)) && (addr < TASK_HPAGE_END)) || \
          ((current->mm->context & CONTEXT_LOW_HPAGES) && \
           (addr > (TASK_HPAGE_BASE_32-len)) && (addr < TASK_HPAGE_END_32)) )
+#define hugetlb_free_pgtables free_pgtables
 #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
 
 #define in_hugepage_area(context, addr) \
index b3dd00de8dc342e8fcca6f649b65ba55c23cda0f..72bda668895b9b10699968ba6d7c0edb3dbd40f9 100644 (file)
@@ -39,6 +39,7 @@ mark_mm_hugetlb(struct mm_struct *mm, struct vm_area_struct *vma)
 
 #ifndef ARCH_HAS_HUGEPAGE_ONLY_RANGE
 #define is_hugepage_only_range(addr, len)      0
+#define hugetlb_free_pgtables(tlb, prev, start, end) do { } while (0)
 #endif
 
 #else /* !CONFIG_HUGETLB_PAGE */
@@ -63,6 +64,7 @@ static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
 #define is_aligned_hugepage_range(addr, len)   0
 #define pmd_huge(x)    0
 #define is_hugepage_only_range(addr, len)      0
+#define hugetlb_free_pgtables(tlb, prev, start, end) do { } while (0)
 
 #ifndef HPAGE_MASK
 #define HPAGE_MASK     0               /* Keep the compiler happy */
index 5b2e70ba6450361e9bf8da732cac08504f50dc8f..ad33ebb86c9687dc3bb08e488b66bb0a5df023aa 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1138,7 +1138,11 @@ static void unmap_region(struct mm_struct *mm,
        tlb = tlb_gather_mmu(mm, 0);
        unmap_vmas(&tlb, mm, vma, start, end, &nr_accounted);
        vm_unacct_memory(nr_accounted);
-       free_pgtables(tlb, prev, start, end);
+
+       if (is_hugepage_only_range(start, end - start))
+               hugetlb_free_pgtables(tlb, prev, start, end);
+       else
+               free_pgtables(tlb, prev, start, end);
        tlb_finish_mmu(tlb, start, end);
 }