diff options
| author | Nick Piggin <nickpiggin@yahoo.com.au> | 2006-12-22 04:09:33 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-22 11:55:49 -0500 |
| commit | 7de6b8057976584e5a422574cae4dd21c677b4d4 (patch) | |
| tree | 900bc533401715eec4e44b73e388a74f08b3f1a5 | |
| parent | 19900cdee29c812857ce938ab449e1053d516252 (diff) | |
[PATCH] mm: more rmap debugging
Add more debugging in the rmap code in an attempt to locate to source of
the occasional "mapcount went negative" assertions.
Cc: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
| -rw-r--r-- | include/linux/rmap.h | 2 | ||||
| -rw-r--r-- | mm/filemap_xip.c | 2 | ||||
| -rw-r--r-- | mm/fremap.c | 2 | ||||
| -rw-r--r-- | mm/memory.c | 4 | ||||
| -rw-r--r-- | mm/rmap.c | 13 |
5 files changed, 15 insertions, 8 deletions
diff --git a/include/linux/rmap.h b/include/linux/rmap.h index 36f850373d2c..bdd277223af0 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h | |||
| @@ -72,7 +72,7 @@ void __anon_vma_link(struct vm_area_struct *); | |||
| 72 | void page_add_anon_rmap(struct page *, struct vm_area_struct *, unsigned long); | 72 | void page_add_anon_rmap(struct page *, struct vm_area_struct *, unsigned long); |
| 73 | void page_add_new_anon_rmap(struct page *, struct vm_area_struct *, unsigned long); | 73 | void page_add_new_anon_rmap(struct page *, struct vm_area_struct *, unsigned long); |
| 74 | void page_add_file_rmap(struct page *); | 74 | void page_add_file_rmap(struct page *); |
| 75 | void page_remove_rmap(struct page *); | 75 | void page_remove_rmap(struct page *, struct vm_area_struct *); |
| 76 | 76 | ||
| 77 | /** | 77 | /** |
| 78 | * page_dup_rmap - duplicate pte mapping to a page | 78 | * page_dup_rmap - duplicate pte mapping to a page |
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c index 8d667617f558..45b3553865cf 100644 --- a/mm/filemap_xip.c +++ b/mm/filemap_xip.c | |||
| @@ -189,7 +189,7 @@ __xip_unmap (struct address_space * mapping, | |||
| 189 | /* Nuke the page table entry. */ | 189 | /* Nuke the page table entry. */ |
| 190 | flush_cache_page(vma, address, pte_pfn(*pte)); | 190 | flush_cache_page(vma, address, pte_pfn(*pte)); |
| 191 | pteval = ptep_clear_flush(vma, address, pte); | 191 | pteval = ptep_clear_flush(vma, address, pte); |
| 192 | page_remove_rmap(page); | 192 | page_remove_rmap(page, vma); |
| 193 | dec_mm_counter(mm, file_rss); | 193 | dec_mm_counter(mm, file_rss); |
| 194 | BUG_ON(pte_dirty(pteval)); | 194 | BUG_ON(pte_dirty(pteval)); |
| 195 | pte_unmap_unlock(pte, ptl); | 195 | pte_unmap_unlock(pte, ptl); |
diff --git a/mm/fremap.c b/mm/fremap.c index b77a002c3352..4e3f53dd5fd4 100644 --- a/mm/fremap.c +++ b/mm/fremap.c | |||
| @@ -33,7 +33,7 @@ static int zap_pte(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 33 | if (page) { | 33 | if (page) { |
| 34 | if (pte_dirty(pte)) | 34 | if (pte_dirty(pte)) |
| 35 | set_page_dirty(page); | 35 | set_page_dirty(page); |
| 36 | page_remove_rmap(page); | 36 | page_remove_rmap(page, vma); |
| 37 | page_cache_release(page); | 37 | page_cache_release(page); |
| 38 | } | 38 | } |
| 39 | } else { | 39 | } else { |
diff --git a/mm/memory.c b/mm/memory.c index c00bac66ce9f..563792f4f687 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
| @@ -681,7 +681,7 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb, | |||
| 681 | mark_page_accessed(page); | 681 | mark_page_accessed(page); |
| 682 | file_rss--; | 682 | file_rss--; |
| 683 | } | 683 | } |
| 684 | page_remove_rmap(page); | 684 | page_remove_rmap(page, vma); |
| 685 | tlb_remove_page(tlb, page); | 685 | tlb_remove_page(tlb, page); |
| 686 | continue; | 686 | continue; |
| 687 | } | 687 | } |
| @@ -1586,7 +1586,7 @@ gotten: | |||
| 1586 | page_table = pte_offset_map_lock(mm, pmd, address, &ptl); | 1586 | page_table = pte_offset_map_lock(mm, pmd, address, &ptl); |
| 1587 | if (likely(pte_same(*page_table, orig_pte))) { | 1587 | if (likely(pte_same(*page_table, orig_pte))) { |
| 1588 | if (old_page) { | 1588 | if (old_page) { |
| 1589 | page_remove_rmap(old_page); | 1589 | page_remove_rmap(old_page, vma); |
| 1590 | if (!PageAnon(old_page)) { | 1590 | if (!PageAnon(old_page)) { |
| 1591 | dec_mm_counter(mm, file_rss); | 1591 | dec_mm_counter(mm, file_rss); |
| 1592 | inc_mm_counter(mm, anon_rss); | 1592 | inc_mm_counter(mm, anon_rss); |
| @@ -47,6 +47,7 @@ | |||
| 47 | #include <linux/rmap.h> | 47 | #include <linux/rmap.h> |
| 48 | #include <linux/rcupdate.h> | 48 | #include <linux/rcupdate.h> |
| 49 | #include <linux/module.h> | 49 | #include <linux/module.h> |
| 50 | #include <linux/kallsyms.h> | ||
| 50 | 51 | ||
| 51 | #include <asm/tlbflush.h> | 52 | #include <asm/tlbflush.h> |
| 52 | 53 | ||
| @@ -567,14 +568,20 @@ void page_add_file_rmap(struct page *page) | |||
| 567 | * | 568 | * |
| 568 | * The caller needs to hold the pte lock. | 569 | * The caller needs to hold the pte lock. |
| 569 | */ | 570 | */ |
| 570 | void page_remove_rmap(struct page *page) | 571 | void page_remove_rmap(struct page *page, struct vm_area_struct *vma) |
| 571 | { | 572 | { |
| 572 | if (atomic_add_negative(-1, &page->_mapcount)) { | 573 | if (atomic_add_negative(-1, &page->_mapcount)) { |
| 573 | if (unlikely(page_mapcount(page) < 0)) { | 574 | if (unlikely(page_mapcount(page) < 0)) { |
| 574 | printk (KERN_EMERG "Eeek! page_mapcount(page) went negative! (%d)\n", page_mapcount(page)); | 575 | printk (KERN_EMERG "Eeek! page_mapcount(page) went negative! (%d)\n", page_mapcount(page)); |
| 576 | printk (KERN_EMERG " page pfn = %lx\n", page_to_pfn(page)); | ||
| 575 | printk (KERN_EMERG " page->flags = %lx\n", page->flags); | 577 | printk (KERN_EMERG " page->flags = %lx\n", page->flags); |
| 576 | printk (KERN_EMERG " page->count = %x\n", page_count(page)); | 578 | printk (KERN_EMERG " page->count = %x\n", page_count(page)); |
| 577 | printk (KERN_EMERG " page->mapping = %p\n", page->mapping); | 579 | printk (KERN_EMERG " page->mapping = %p\n", page->mapping); |
| 580 | print_symbol (KERN_EMERG " vma->vm_ops = %s\n", (unsigned long)vma->vm_ops); | ||
| 581 | if (vma->vm_ops) | ||
| 582 | print_symbol (KERN_EMERG " vma->vm_ops->nopage = %s\n", (unsigned long)vma->vm_ops->nopage); | ||
| 583 | if (vma->vm_file && vma->vm_file->f_op) | ||
| 584 | print_symbol (KERN_EMERG " vma->vm_file->f_op->mmap = %s\n", (unsigned long)vma->vm_file->f_op->mmap); | ||
| 578 | BUG(); | 585 | BUG(); |
| 579 | } | 586 | } |
| 580 | 587 | ||
| @@ -679,7 +686,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, | |||
| 679 | dec_mm_counter(mm, file_rss); | 686 | dec_mm_counter(mm, file_rss); |
| 680 | 687 | ||
| 681 | 688 | ||
| 682 | page_remove_rmap(page); | 689 | page_remove_rmap(page, vma); |
| 683 | page_cache_release(page); | 690 | page_cache_release(page); |
| 684 | 691 | ||
| 685 | out_unmap: | 692 | out_unmap: |
| @@ -769,7 +776,7 @@ static void try_to_unmap_cluster(unsigned long cursor, | |||
| 769 | if (pte_dirty(pteval)) | 776 | if (pte_dirty(pteval)) |
| 770 | set_page_dirty(page); | 777 | set_page_dirty(page); |
| 771 | 778 | ||
| 772 | page_remove_rmap(page); | 779 | page_remove_rmap(page, vma); |
| 773 | page_cache_release(page); | 780 | page_cache_release(page); |
| 774 | dec_mm_counter(mm, file_rss); | 781 | dec_mm_counter(mm, file_rss); |
| 775 | (*mapcount)--; | 782 | (*mapcount)--; |
