aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Hansen <dave@sr71.net>2014-01-23 18:52:49 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-23 19:36:50 -0500
commitf0b791a34cb3cffd2bbc3ca4365c9b719fa2c9f3 (patch)
treec4aa42cd8ecd15eca056a944788f5457e3a370ef
parent12ab028be0008640de712ca890dc1a9ae224934d (diff)
mm: print more details for bad_page()
bad_page() is cool in that it prints out a bunch of data about the page. But, I can never remember which page flags are good and which are bad, or whether ->index or ->mapping is required to be NULL. This patch allows bad/dump_page() callers to specify a string about why they are dumping the page and adds explanation strings to a number of places. It also adds a 'bad_flags' argument to bad_page(), which it then dumps out separately from the flags which are actually set. This way, the messages will show specifically why the page was bad, *specifically* which flags it is complaining about, if it was a page flag combination which was the problem. [akpm@linux-foundation.org: switch to pr_alert] Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Reviewed-by: Christoph Lameter <cl@linux.com> Cc: Andi Kleen <andi@firstfloor.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/mm.h4
-rw-r--r--mm/balloon_compaction.c4
-rw-r--r--mm/memory.c2
-rw-r--r--mm/memory_hotplug.c2
-rw-r--r--mm/page_alloc.c72
5 files changed, 61 insertions, 23 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h
index a512dd836931..03bbcb84d96e 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2029,7 +2029,9 @@ extern void shake_page(struct page *p, int access);
2029extern atomic_long_t num_poisoned_pages; 2029extern atomic_long_t num_poisoned_pages;
2030extern int soft_offline_page(struct page *page, int flags); 2030extern int soft_offline_page(struct page *page, int flags);
2031 2031
2032extern void dump_page(struct page *page); 2032extern void dump_page(struct page *page, char *reason);
2033extern void dump_page_badflags(struct page *page, char *reason,
2034 unsigned long badflags);
2033 2035
2034#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_HUGETLBFS) 2036#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_HUGETLBFS)
2035extern void clear_huge_page(struct page *page, 2037extern void clear_huge_page(struct page *page,
diff --git a/mm/balloon_compaction.c b/mm/balloon_compaction.c
index 07dbc8ec46cf..6e45a5074bf0 100644
--- a/mm/balloon_compaction.c
+++ b/mm/balloon_compaction.c
@@ -267,7 +267,7 @@ void balloon_page_putback(struct page *page)
267 put_page(page); 267 put_page(page);
268 } else { 268 } else {
269 WARN_ON(1); 269 WARN_ON(1);
270 dump_page(page); 270 dump_page(page, "not movable balloon page");
271 } 271 }
272 unlock_page(page); 272 unlock_page(page);
273} 273}
@@ -287,7 +287,7 @@ int balloon_page_migrate(struct page *newpage,
287 BUG_ON(!trylock_page(newpage)); 287 BUG_ON(!trylock_page(newpage));
288 288
289 if (WARN_ON(!__is_movable_balloon_page(page))) { 289 if (WARN_ON(!__is_movable_balloon_page(page))) {
290 dump_page(page); 290 dump_page(page, "not movable balloon page");
291 unlock_page(newpage); 291 unlock_page(newpage);
292 return rc; 292 return rc;
293 } 293 }
diff --git a/mm/memory.c b/mm/memory.c
index 86487dfa5e59..71d70c082b98 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -671,7 +671,7 @@ static void print_bad_pte(struct vm_area_struct *vma, unsigned long addr,
671 current->comm, 671 current->comm,
672 (long long)pte_val(pte), (long long)pmd_val(*pmd)); 672 (long long)pte_val(pte), (long long)pmd_val(*pmd));
673 if (page) 673 if (page)
674 dump_page(page); 674 dump_page(page, "bad pte");
675 printk(KERN_ALERT 675 printk(KERN_ALERT
676 "addr:%p vm_flags:%08lx anon_vma:%p mapping:%p index:%lx\n", 676 "addr:%p vm_flags:%08lx anon_vma:%p mapping:%p index:%lx\n",
677 (void *)addr, vma->vm_flags, vma->anon_vma, mapping, index); 677 (void *)addr, vma->vm_flags, vma->anon_vma, mapping, index);
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index cc2ab37220b7..a512a47241a4 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1309,7 +1309,7 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
1309#ifdef CONFIG_DEBUG_VM 1309#ifdef CONFIG_DEBUG_VM
1310 printk(KERN_ALERT "removing pfn %lx from LRU failed\n", 1310 printk(KERN_ALERT "removing pfn %lx from LRU failed\n",
1311 pfn); 1311 pfn);
1312 dump_page(page); 1312 dump_page(page, "failed to remove from LRU");
1313#endif 1313#endif
1314 put_page(page); 1314 put_page(page);
1315 /* Because we don't have big zone->lock. we should 1315 /* Because we don't have big zone->lock. we should
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 533e2147d14f..1939f4446a36 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -295,7 +295,7 @@ static inline int bad_range(struct zone *zone, struct page *page)
295} 295}
296#endif 296#endif
297 297
298static void bad_page(struct page *page) 298static void bad_page(struct page *page, char *reason, unsigned long bad_flags)
299{ 299{
300 static unsigned long resume; 300 static unsigned long resume;
301 static unsigned long nr_shown; 301 static unsigned long nr_shown;
@@ -329,7 +329,7 @@ static void bad_page(struct page *page)
329 329
330 printk(KERN_ALERT "BUG: Bad page state in process %s pfn:%05lx\n", 330 printk(KERN_ALERT "BUG: Bad page state in process %s pfn:%05lx\n",
331 current->comm, page_to_pfn(page)); 331 current->comm, page_to_pfn(page));
332 dump_page(page); 332 dump_page_badflags(page, reason, bad_flags);
333 333
334 print_modules(); 334 print_modules();
335 dump_stack(); 335 dump_stack();
@@ -383,7 +383,7 @@ static int destroy_compound_page(struct page *page, unsigned long order)
383 int bad = 0; 383 int bad = 0;
384 384
385 if (unlikely(compound_order(page) != order)) { 385 if (unlikely(compound_order(page) != order)) {
386 bad_page(page); 386 bad_page(page, "wrong compound order", 0);
387 bad++; 387 bad++;
388 } 388 }
389 389
@@ -392,8 +392,11 @@ static int destroy_compound_page(struct page *page, unsigned long order)
392 for (i = 1; i < nr_pages; i++) { 392 for (i = 1; i < nr_pages; i++) {
393 struct page *p = page + i; 393 struct page *p = page + i;
394 394
395 if (unlikely(!PageTail(p) || (p->first_page != page))) { 395 if (unlikely(!PageTail(p))) {
396 bad_page(page); 396 bad_page(page, "PageTail not set", 0);
397 bad++;
398 } else if (unlikely(p->first_page != page)) {
399 bad_page(page, "first_page not consistent", 0);
397 bad++; 400 bad++;
398 } 401 }
399 __ClearPageTail(p); 402 __ClearPageTail(p);
@@ -618,12 +621,23 @@ out:
618 621
619static inline int free_pages_check(struct page *page) 622static inline int free_pages_check(struct page *page)
620{ 623{
621 if (unlikely(page_mapcount(page) | 624 char *bad_reason = NULL;
622 (page->mapping != NULL) | 625 unsigned long bad_flags = 0;
623 (atomic_read(&page->_count) != 0) | 626
624 (page->flags & PAGE_FLAGS_CHECK_AT_FREE) | 627 if (unlikely(page_mapcount(page)))
625 (mem_cgroup_bad_page_check(page)))) { 628 bad_reason = "nonzero mapcount";
626 bad_page(page); 629 if (unlikely(page->mapping != NULL))
630 bad_reason = "non-NULL mapping";
631 if (unlikely(atomic_read(&page->_count) != 0))
632 bad_reason = "nonzero _count";
633 if (unlikely(page->flags & PAGE_FLAGS_CHECK_AT_FREE)) {
634 bad_reason = "PAGE_FLAGS_CHECK_AT_FREE flag(s) set";
635 bad_flags = PAGE_FLAGS_CHECK_AT_FREE;
636 }
637 if (unlikely(mem_cgroup_bad_page_check(page)))
638 bad_reason = "cgroup check failed";
639 if (unlikely(bad_reason)) {
640 bad_page(page, bad_reason, bad_flags);
627 return 1; 641 return 1;
628 } 642 }
629 page_cpupid_reset_last(page); 643 page_cpupid_reset_last(page);
@@ -843,12 +857,23 @@ static inline void expand(struct zone *zone, struct page *page,
843 */ 857 */
844static inline int check_new_page(struct page *page) 858static inline int check_new_page(struct page *page)
845{ 859{
846 if (unlikely(page_mapcount(page) | 860 char *bad_reason = NULL;
847 (page->mapping != NULL) | 861 unsigned long bad_flags = 0;
848 (atomic_read(&page->_count) != 0) | 862
849 (page->flags & PAGE_FLAGS_CHECK_AT_PREP) | 863 if (unlikely(page_mapcount(page)))
850 (mem_cgroup_bad_page_check(page)))) { 864 bad_reason = "nonzero mapcount";
851 bad_page(page); 865 if (unlikely(page->mapping != NULL))
866 bad_reason = "non-NULL mapping";
867 if (unlikely(atomic_read(&page->_count) != 0))
868 bad_reason = "nonzero _count";
869 if (unlikely(page->flags & PAGE_FLAGS_CHECK_AT_PREP)) {
870 bad_reason = "PAGE_FLAGS_CHECK_AT_PREP flag set";
871 bad_flags = PAGE_FLAGS_CHECK_AT_PREP;
872 }
873 if (unlikely(mem_cgroup_bad_page_check(page)))
874 bad_reason = "cgroup check failed";
875 if (unlikely(bad_reason)) {
876 bad_page(page, bad_reason, bad_flags);
852 return 1; 877 return 1;
853 } 878 }
854 return 0; 879 return 0;
@@ -6494,12 +6519,23 @@ static void dump_page_flags(unsigned long flags)
6494 printk(")\n"); 6519 printk(")\n");
6495} 6520}
6496 6521
6497void dump_page(struct page *page) 6522void dump_page_badflags(struct page *page, char *reason, unsigned long badflags)
6498{ 6523{
6499 printk(KERN_ALERT 6524 printk(KERN_ALERT
6500 "page:%p count:%d mapcount:%d mapping:%p index:%#lx\n", 6525 "page:%p count:%d mapcount:%d mapping:%p index:%#lx\n",
6501 page, atomic_read(&page->_count), page_mapcount(page), 6526 page, atomic_read(&page->_count), page_mapcount(page),
6502 page->mapping, page->index); 6527 page->mapping, page->index);
6503 dump_page_flags(page->flags); 6528 dump_page_flags(page->flags);
6529 if (reason)
6530 pr_alert("page dumped because: %s\n", reason);
6531 if (page->flags & badflags) {
6532 pr_alert("bad because of flags:\n");
6533 dump_page_flags(page->flags & badflags);
6534 }
6504 mem_cgroup_print_bad_page(page); 6535 mem_cgroup_print_bad_page(page);
6505} 6536}
6537
6538void dump_page(struct page *page, char *reason)
6539{
6540 dump_page_badflags(page, reason, 0);
6541}