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