diff options
Diffstat (limited to 'mm/memory.c')
-rw-r--r-- | mm/memory.c | 52 |
1 files changed, 40 insertions, 12 deletions
diff --git a/mm/memory.c b/mm/memory.c index 89339c61f8e5..cda04b19f733 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -52,6 +52,9 @@ | |||
52 | #include <linux/writeback.h> | 52 | #include <linux/writeback.h> |
53 | #include <linux/memcontrol.h> | 53 | #include <linux/memcontrol.h> |
54 | #include <linux/mmu_notifier.h> | 54 | #include <linux/mmu_notifier.h> |
55 | #include <linux/kallsyms.h> | ||
56 | #include <linux/swapops.h> | ||
57 | #include <linux/elf.h> | ||
55 | 58 | ||
56 | #include <asm/pgalloc.h> | 59 | #include <asm/pgalloc.h> |
57 | #include <asm/uaccess.h> | 60 | #include <asm/uaccess.h> |
@@ -59,9 +62,6 @@ | |||
59 | #include <asm/tlbflush.h> | 62 | #include <asm/tlbflush.h> |
60 | #include <asm/pgtable.h> | 63 | #include <asm/pgtable.h> |
61 | 64 | ||
62 | #include <linux/swapops.h> | ||
63 | #include <linux/elf.h> | ||
64 | |||
65 | #include "internal.h" | 65 | #include "internal.h" |
66 | 66 | ||
67 | #ifndef CONFIG_NEED_MULTIPLE_NODES | 67 | #ifndef CONFIG_NEED_MULTIPLE_NODES |
@@ -375,15 +375,41 @@ static inline void add_mm_rss(struct mm_struct *mm, int file_rss, int anon_rss) | |||
375 | * | 375 | * |
376 | * The calling function must still handle the error. | 376 | * The calling function must still handle the error. |
377 | */ | 377 | */ |
378 | static void print_bad_pte(struct vm_area_struct *vma, pte_t pte, | 378 | static void print_bad_pte(struct vm_area_struct *vma, unsigned long addr, |
379 | unsigned long vaddr) | 379 | pte_t pte, struct page *page) |
380 | { | 380 | { |
381 | printk(KERN_ERR "Bad pte = %08llx, process = %s, " | 381 | pgd_t *pgd = pgd_offset(vma->vm_mm, addr); |
382 | "vm_flags = %lx, vaddr = %lx\n", | 382 | pud_t *pud = pud_offset(pgd, addr); |
383 | (long long)pte_val(pte), | 383 | pmd_t *pmd = pmd_offset(pud, addr); |
384 | (vma->vm_mm == current->mm ? current->comm : "???"), | 384 | struct address_space *mapping; |
385 | vma->vm_flags, vaddr); | 385 | pgoff_t index; |
386 | |||
387 | mapping = vma->vm_file ? vma->vm_file->f_mapping : NULL; | ||
388 | index = linear_page_index(vma, addr); | ||
389 | |||
390 | printk(KERN_EMERG "Bad page map in process %s pte:%08llx pmd:%08llx\n", | ||
391 | current->comm, | ||
392 | (long long)pte_val(pte), (long long)pmd_val(*pmd)); | ||
393 | if (page) { | ||
394 | printk(KERN_EMERG | ||
395 | "page:%p flags:%p count:%d mapcount:%d mapping:%p index:%lx\n", | ||
396 | page, (void *)page->flags, page_count(page), | ||
397 | page_mapcount(page), page->mapping, page->index); | ||
398 | } | ||
399 | printk(KERN_EMERG | ||
400 | "addr:%p vm_flags:%08lx anon_vma:%p mapping:%p index:%lx\n", | ||
401 | (void *)addr, vma->vm_flags, vma->anon_vma, mapping, index); | ||
402 | /* | ||
403 | * Choose text because data symbols depend on CONFIG_KALLSYMS_ALL=y | ||
404 | */ | ||
405 | if (vma->vm_ops) | ||
406 | print_symbol(KERN_EMERG "vma->vm_ops->fault: %s\n", | ||
407 | (unsigned long)vma->vm_ops->fault); | ||
408 | if (vma->vm_file && vma->vm_file->f_op) | ||
409 | print_symbol(KERN_EMERG "vma->vm_file->f_op->mmap: %s\n", | ||
410 | (unsigned long)vma->vm_file->f_op->mmap); | ||
386 | dump_stack(); | 411 | dump_stack(); |
412 | add_taint(TAINT_BAD_PAGE); | ||
387 | } | 413 | } |
388 | 414 | ||
389 | static inline int is_cow_mapping(unsigned int flags) | 415 | static inline int is_cow_mapping(unsigned int flags) |
@@ -773,6 +799,8 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb, | |||
773 | file_rss--; | 799 | file_rss--; |
774 | } | 800 | } |
775 | page_remove_rmap(page, vma); | 801 | page_remove_rmap(page, vma); |
802 | if (unlikely(page_mapcount(page) < 0)) | ||
803 | print_bad_pte(vma, addr, ptent, page); | ||
776 | tlb_remove_page(tlb, page); | 804 | tlb_remove_page(tlb, page); |
777 | continue; | 805 | continue; |
778 | } | 806 | } |
@@ -2684,7 +2712,7 @@ static int do_nonlinear_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2684 | /* | 2712 | /* |
2685 | * Page table corrupted: show pte and kill process. | 2713 | * Page table corrupted: show pte and kill process. |
2686 | */ | 2714 | */ |
2687 | print_bad_pte(vma, orig_pte, address); | 2715 | print_bad_pte(vma, address, orig_pte, NULL); |
2688 | return VM_FAULT_OOM; | 2716 | return VM_FAULT_OOM; |
2689 | } | 2717 | } |
2690 | 2718 | ||