diff options
Diffstat (limited to 'mm/debug.c')
| -rw-r--r-- | mm/debug.c | 18 | 
1 files changed, 16 insertions, 2 deletions
| diff --git a/mm/debug.c b/mm/debug.c index 56e2d9125ea5..38c926520c97 100644 --- a/mm/debug.c +++ b/mm/debug.c @@ -43,12 +43,25 @@ const struct trace_print_flags vmaflag_names[] = {  void __dump_page(struct page *page, const char *reason)  { +	bool page_poisoned = PagePoisoned(page); +	int mapcount; + +	/* +	 * If struct page is poisoned don't access Page*() functions as that +	 * leads to recursive loop. Page*() check for poisoned pages, and calls +	 * dump_page() when detected. +	 */ +	if (page_poisoned) { +		pr_emerg("page:%px is uninitialized and poisoned", page); +		goto hex_only; +	} +  	/*  	 * Avoid VM_BUG_ON() in page_mapcount().  	 * page->_mapcount space in struct page is used by sl[aou]b pages to  	 * encode own info.  	 */ -	int mapcount = PageSlab(page) ? 0 : page_mapcount(page); +	mapcount = PageSlab(page) ? 0 : page_mapcount(page);  	pr_emerg("page:%px count:%d mapcount:%d mapping:%px index:%#lx",  		  page, page_ref_count(page), mapcount, @@ -60,6 +73,7 @@ void __dump_page(struct page *page, const char *reason)  	pr_emerg("flags: %#lx(%pGp)\n", page->flags, &page->flags); +hex_only:  	print_hex_dump(KERN_ALERT, "raw: ", DUMP_PREFIX_NONE, 32,  			sizeof(unsigned long), page,  			sizeof(struct page), false); @@ -68,7 +82,7 @@ void __dump_page(struct page *page, const char *reason)  		pr_alert("page dumped because: %s\n", reason);  #ifdef CONFIG_MEMCG -	if (page->mem_cgroup) +	if (!page_poisoned && page->mem_cgroup)  		pr_alert("page->mem_cgroup:%px\n", page->mem_cgroup);  #endif  } |