aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory-failure.c
diff options
context:
space:
mode:
authorWu Fengguang <fengguang.wu@intel.com>2009-12-16 06:19:59 -0500
committerAndi Kleen <ak@linux.intel.com>2009-12-16 06:19:59 -0500
commit478c5ffc0b50527bd2390f2daa46cc16276b8413 (patch)
treef58f5be9760fd0e81567611cf6e9f9bc77d1d3cd /mm/memory-failure.c
parent1a9b5b7fe0c5dad8a635288882d36785dea742f9 (diff)
HWPOISON: add page flags filter
When specified, only poison pages if ((page_flags & mask) == value). - corrupt-filter-flags-mask - corrupt-filter-flags-value This allows stress testing of many kinds of pages. Strictly speaking, the buddy pages requires taking zone lock, to avoid setting PG_hwpoison on a "was buddy but now allocated to someone" page. However we can just do nothing because we set PG_locked in the beginning, this prevents the page allocator from allocating it to someone. (It will BUG() on the unexpected PG_locked, which is fine for hwpoison testing.) [AK: Add select PROC_PAGE_MONITOR to satisfy dependency] CC: Nick Piggin <npiggin@suse.de> Signed-off-by: Wu Fengguang <fengguang.wu@intel.com> Signed-off-by: Andi Kleen <ak@linux.intel.com>
Diffstat (limited to 'mm/memory-failure.c')
-rw-r--r--mm/memory-failure.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 82ac73436d0e..22d2b2028e54 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -34,6 +34,7 @@
34#include <linux/kernel.h> 34#include <linux/kernel.h>
35#include <linux/mm.h> 35#include <linux/mm.h>
36#include <linux/page-flags.h> 36#include <linux/page-flags.h>
37#include <linux/kernel-page-flags.h>
37#include <linux/sched.h> 38#include <linux/sched.h>
38#include <linux/ksm.h> 39#include <linux/ksm.h>
39#include <linux/rmap.h> 40#include <linux/rmap.h>
@@ -50,8 +51,12 @@ atomic_long_t mce_bad_pages __read_mostly = ATOMIC_LONG_INIT(0);
50 51
51u32 hwpoison_filter_dev_major = ~0U; 52u32 hwpoison_filter_dev_major = ~0U;
52u32 hwpoison_filter_dev_minor = ~0U; 53u32 hwpoison_filter_dev_minor = ~0U;
54u64 hwpoison_filter_flags_mask;
55u64 hwpoison_filter_flags_value;
53EXPORT_SYMBOL_GPL(hwpoison_filter_dev_major); 56EXPORT_SYMBOL_GPL(hwpoison_filter_dev_major);
54EXPORT_SYMBOL_GPL(hwpoison_filter_dev_minor); 57EXPORT_SYMBOL_GPL(hwpoison_filter_dev_minor);
58EXPORT_SYMBOL_GPL(hwpoison_filter_flags_mask);
59EXPORT_SYMBOL_GPL(hwpoison_filter_flags_value);
55 60
56static int hwpoison_filter_dev(struct page *p) 61static int hwpoison_filter_dev(struct page *p)
57{ 62{
@@ -83,11 +88,26 @@ static int hwpoison_filter_dev(struct page *p)
83 return 0; 88 return 0;
84} 89}
85 90
91static int hwpoison_filter_flags(struct page *p)
92{
93 if (!hwpoison_filter_flags_mask)
94 return 0;
95
96 if ((stable_page_flags(p) & hwpoison_filter_flags_mask) ==
97 hwpoison_filter_flags_value)
98 return 0;
99 else
100 return -EINVAL;
101}
102
86int hwpoison_filter(struct page *p) 103int hwpoison_filter(struct page *p)
87{ 104{
88 if (hwpoison_filter_dev(p)) 105 if (hwpoison_filter_dev(p))
89 return -EINVAL; 106 return -EINVAL;
90 107
108 if (hwpoison_filter_flags(p))
109 return -EINVAL;
110
91 return 0; 111 return 0;
92} 112}
93EXPORT_SYMBOL_GPL(hwpoison_filter); 113EXPORT_SYMBOL_GPL(hwpoison_filter);