diff options
Diffstat (limited to 'mm/debug-pagealloc.c')
-rw-r--r-- | mm/debug-pagealloc.c | 56 |
1 files changed, 16 insertions, 40 deletions
diff --git a/mm/debug-pagealloc.c b/mm/debug-pagealloc.c index a1e3324de2b5..7cea557407f4 100644 --- a/mm/debug-pagealloc.c +++ b/mm/debug-pagealloc.c | |||
@@ -1,7 +1,10 @@ | |||
1 | #include <linux/kernel.h> | 1 | #include <linux/kernel.h> |
2 | #include <linux/string.h> | ||
2 | #include <linux/mm.h> | 3 | #include <linux/mm.h> |
4 | #include <linux/highmem.h> | ||
3 | #include <linux/page-debug-flags.h> | 5 | #include <linux/page-debug-flags.h> |
4 | #include <linux/poison.h> | 6 | #include <linux/poison.h> |
7 | #include <linux/ratelimit.h> | ||
5 | 8 | ||
6 | static inline void set_page_poison(struct page *page) | 9 | static inline void set_page_poison(struct page *page) |
7 | { | 10 | { |
@@ -18,28 +21,13 @@ static inline bool page_poison(struct page *page) | |||
18 | return test_bit(PAGE_DEBUG_FLAG_POISON, &page->debug_flags); | 21 | return test_bit(PAGE_DEBUG_FLAG_POISON, &page->debug_flags); |
19 | } | 22 | } |
20 | 23 | ||
21 | static void poison_highpage(struct page *page) | ||
22 | { | ||
23 | /* | ||
24 | * Page poisoning for highmem pages is not implemented. | ||
25 | * | ||
26 | * This can be called from interrupt contexts. | ||
27 | * So we need to create a new kmap_atomic slot for this | ||
28 | * application and it will need interrupt protection. | ||
29 | */ | ||
30 | } | ||
31 | |||
32 | static void poison_page(struct page *page) | 24 | static void poison_page(struct page *page) |
33 | { | 25 | { |
34 | void *addr; | 26 | void *addr = kmap_atomic(page); |
35 | 27 | ||
36 | if (PageHighMem(page)) { | ||
37 | poison_highpage(page); | ||
38 | return; | ||
39 | } | ||
40 | set_page_poison(page); | 28 | set_page_poison(page); |
41 | addr = page_address(page); | ||
42 | memset(addr, PAGE_POISON, PAGE_SIZE); | 29 | memset(addr, PAGE_POISON, PAGE_SIZE); |
30 | kunmap_atomic(addr); | ||
43 | } | 31 | } |
44 | 32 | ||
45 | static void poison_pages(struct page *page, int n) | 33 | static void poison_pages(struct page *page, int n) |
@@ -59,14 +47,12 @@ static bool single_bit_flip(unsigned char a, unsigned char b) | |||
59 | 47 | ||
60 | static void check_poison_mem(unsigned char *mem, size_t bytes) | 48 | static void check_poison_mem(unsigned char *mem, size_t bytes) |
61 | { | 49 | { |
50 | static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 10); | ||
62 | unsigned char *start; | 51 | unsigned char *start; |
63 | unsigned char *end; | 52 | unsigned char *end; |
64 | 53 | ||
65 | for (start = mem; start < mem + bytes; start++) { | 54 | start = memchr_inv(mem, PAGE_POISON, bytes); |
66 | if (*start != PAGE_POISON) | 55 | if (!start) |
67 | break; | ||
68 | } | ||
69 | if (start == mem + bytes) | ||
70 | return; | 56 | return; |
71 | 57 | ||
72 | for (end = mem + bytes - 1; end > start; end--) { | 58 | for (end = mem + bytes - 1; end > start; end--) { |
@@ -74,7 +60,7 @@ static void check_poison_mem(unsigned char *mem, size_t bytes) | |||
74 | break; | 60 | break; |
75 | } | 61 | } |
76 | 62 | ||
77 | if (!printk_ratelimit()) | 63 | if (!__ratelimit(&ratelimit)) |
78 | return; | 64 | return; |
79 | else if (start == end && single_bit_flip(*start, PAGE_POISON)) | 65 | else if (start == end && single_bit_flip(*start, PAGE_POISON)) |
80 | printk(KERN_ERR "pagealloc: single bit error\n"); | 66 | printk(KERN_ERR "pagealloc: single bit error\n"); |
@@ -86,27 +72,17 @@ static void check_poison_mem(unsigned char *mem, size_t bytes) | |||
86 | dump_stack(); | 72 | dump_stack(); |
87 | } | 73 | } |
88 | 74 | ||
89 | static void unpoison_highpage(struct page *page) | ||
90 | { | ||
91 | /* | ||
92 | * See comment in poison_highpage(). | ||
93 | * Highmem pages should not be poisoned for now | ||
94 | */ | ||
95 | BUG_ON(page_poison(page)); | ||
96 | } | ||
97 | |||
98 | static void unpoison_page(struct page *page) | 75 | static void unpoison_page(struct page *page) |
99 | { | 76 | { |
100 | if (PageHighMem(page)) { | 77 | void *addr; |
101 | unpoison_highpage(page); | 78 | |
79 | if (!page_poison(page)) | ||
102 | return; | 80 | return; |
103 | } | ||
104 | if (page_poison(page)) { | ||
105 | void *addr = page_address(page); | ||
106 | 81 | ||
107 | check_poison_mem(addr, PAGE_SIZE); | 82 | addr = kmap_atomic(page); |
108 | clear_page_poison(page); | 83 | check_poison_mem(addr, PAGE_SIZE); |
109 | } | 84 | clear_page_poison(page); |
85 | kunmap_atomic(addr); | ||
110 | } | 86 | } |
111 | 87 | ||
112 | static void unpoison_pages(struct page *page, int n) | 88 | static void unpoison_pages(struct page *page, int n) |