diff options
Diffstat (limited to 'mm/debug-pagealloc.c')
| -rw-r--r-- | mm/debug-pagealloc.c | 59 | 
1 files changed, 16 insertions, 43 deletions
diff --git a/mm/debug-pagealloc.c b/mm/debug-pagealloc.c index a1e3324de2b..789ff70c8a4 100644 --- a/mm/debug-pagealloc.c +++ b/mm/debug-pagealloc.c @@ -1,7 +1,10 @@  #include <linux/kernel.h> +#include <linux/string.h>  #include <linux/mm.h> +#include <linux/highmem.h>  #include <linux/page-debug-flags.h>  #include <linux/poison.h> +#include <linux/ratelimit.h>  static inline void set_page_poison(struct page *page)  { @@ -18,28 +21,13 @@ static inline bool page_poison(struct page *page)  	return test_bit(PAGE_DEBUG_FLAG_POISON, &page->debug_flags);  } -static void poison_highpage(struct page *page) -{ -	/* -	 * Page poisoning for highmem pages is not implemented. -	 * -	 * This can be called from interrupt contexts. -	 * So we need to create a new kmap_atomic slot for this -	 * application and it will need interrupt protection. -	 */ -} -  static void poison_page(struct page *page)  { -	void *addr; +	void *addr = kmap_atomic(page); -	if (PageHighMem(page)) { -		poison_highpage(page); -		return; -	}  	set_page_poison(page); -	addr = page_address(page);  	memset(addr, PAGE_POISON, PAGE_SIZE); +	kunmap_atomic(addr);  }  static void poison_pages(struct page *page, int n) @@ -59,14 +47,12 @@ static bool single_bit_flip(unsigned char a, unsigned char b)  static void check_poison_mem(unsigned char *mem, size_t bytes)  { +	static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 10);  	unsigned char *start;  	unsigned char *end; -	for (start = mem; start < mem + bytes; start++) { -		if (*start != PAGE_POISON) -			break; -	} -	if (start == mem + bytes) +	start = memchr_inv(mem, PAGE_POISON, bytes); +	if (!start)  		return;  	for (end = mem + bytes - 1; end > start; end--) { @@ -74,7 +60,7 @@ static void check_poison_mem(unsigned char *mem, size_t bytes)  			break;  	} -	if (!printk_ratelimit()) +	if (!__ratelimit(&ratelimit))  		return;  	else if (start == end && single_bit_flip(*start, PAGE_POISON))  		printk(KERN_ERR "pagealloc: single bit error\n"); @@ -86,27 +72,17 @@ static void check_poison_mem(unsigned char *mem, size_t bytes)  	dump_stack();  } -static void unpoison_highpage(struct page *page) -{ -	/* -	 * See comment in poison_highpage(). -	 * Highmem pages should not be poisoned for now -	 */ -	BUG_ON(page_poison(page)); -} -  static void unpoison_page(struct page *page)  { -	if (PageHighMem(page)) { -		unpoison_highpage(page); +	void *addr; + +	if (!page_poison(page))  		return; -	} -	if (page_poison(page)) { -		void *addr = page_address(page); -		check_poison_mem(addr, PAGE_SIZE); -		clear_page_poison(page); -	} +	addr = kmap_atomic(page); +	check_poison_mem(addr, PAGE_SIZE); +	clear_page_poison(page); +	kunmap_atomic(addr);  }  static void unpoison_pages(struct page *page, int n) @@ -119,9 +95,6 @@ static void unpoison_pages(struct page *page, int n)  void kernel_map_pages(struct page *page, int numpages, int enable)  { -	if (!debug_pagealloc_enabled) -		return; -  	if (enable)  		unpoison_pages(page, numpages);  	else  | 
