Re: [PATCH 1/5] freepgt: free_pgtables use vma list

Nick Piggin
2005-03-22T12:17:36Z

[-- Attachment #1: Type: text/plain, Size: 535 bytes --]

Andrew Morton wrote:
> With these six patches the ppc64 is hitting the BUG in exit_mmap():
>
> BUG_ON(mm->nr_ptes); /* This is just debugging */
>
> fairly early in boot.
>

No doubt Hugh will have this fixed before long... but if you
have time to spare, you may just try hitting it on the head
and making it a bit dumber. It might help show where the problem
is.

- don't span multiple vmas
- don't be so smart about avoiding unfreeable regions

I dunno. Maybe it won't help at all. Maybe it will make things
worse :P

[-- Attachment #2: ptclr-nosmart.patch --]
[-- Type: text/plain, Size: 2267 bytes --]

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);
}