Index: linux-2.6/mm/memory.c =================================================================== --- linux-2.6.orig/mm/memory.c 2005-03-22 23:04:34.000000000 +1100 +++ linux-2.6/mm/memory.c 2005-03-22 23:11:31.000000000 +1100 @@ -110,13 +110,18 @@ void pmd_clear_bad(pmd_t *pmd) * Note: this doesn't free the actual pages themselves. That * has been handled earlier when unmapping all the memory regions. */ -static void free_pte_range(struct mmu_gather *tlb, pmd_t *pmd) +static void free_pte_range(struct mmu_gather *tlb, pmd_t *pmd, + unsigned long addr, unsigned long end, + unsigned long floor, unsigned long ceiling) { - struct page *page = pmd_page(*pmd); - pmd_clear(pmd); - pte_free_tlb(tlb, page); - dec_page_state(nr_page_table_pages); - tlb->mm->nr_ptes--; + if (((addr & PMD_MASK) >= floor) + && (end - 1 <= (ceiling & PMD_MASK) - 1)) { + struct page *page = pmd_page(*pmd); + pmd_clear(pmd); + pte_free_tlb(tlb, page); + dec_page_state(nr_page_table_pages); + tlb->mm->nr_ptes--; + } } static inline void free_pmd_range(struct mmu_gather *tlb, pud_t *pud, @@ -133,7 +138,7 @@ static inline void free_pmd_range(struct next = pmd_addr_end(addr, end); if (pmd_none_or_clear_bad(pmd)) continue; - free_pte_range(tlb, pmd); + free_pte_range(tlb, pmd, addr, end, floor, ceiling); } while (pmd++, addr = next, addr != end); start &= PUD_MASK; @@ -190,18 +195,6 @@ void free_pgd_range(struct mmu_gather ** unsigned long next; unsigned long start; - addr &= PMD_MASK; - if (addr < floor) { - addr += PMD_SIZE; - if (!addr) - return; - } - ceiling &= PMD_MASK; - if (end - 1 > ceiling - 1) - end -= PMD_SIZE; - if (addr > end - 1) - return; - start = addr; pgd = pgd_offset((*tlb)->mm, addr); do { @@ -226,14 +219,6 @@ void free_pgtables(struct mmu_gather **t hugetlb_free_pgd_range(tlb, addr, vma->vm_end, floor, next? next->vm_start: ceiling); } else { - /* - * Optimization: gather nearby vmas into one call down - */ - while (next && next->vm_start <= vma->vm_end + PMD_SIZE - && !is_hugepage_only_range(next->vm_start, HPAGE_SIZE)){ - vma = next; - next = vma->vm_next; - } free_pgd_range(tlb, addr, vma->vm_end, floor, next? next->vm_start: ceiling); }