Commit 478c5ffc0b50527bd2390f2daa46cc16276b8413
Committed by
Andi Kleen
1 parent
1a9b5b7fe0
Exists in
master
and in
4 other branches
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>
Showing 5 changed files with 43 additions and 0 deletions Side-by-side Diff
Documentation/vm/hwpoison.txt
... | ... | @@ -123,6 +123,16 @@ |
123 | 123 | by block device major/minor. -1U is the wildcard value. |
124 | 124 | This should be only used for testing with artificial injection. |
125 | 125 | |
126 | + | |
127 | +corrupt-filter-flags-mask | |
128 | +corrupt-filter-flags-value | |
129 | + | |
130 | +When specified, only poison pages if ((page_flags & mask) == value). | |
131 | +This allows stress testing of many kinds of pages. The page_flags | |
132 | +are the same as in /proc/kpageflags. The flag bits are defined in | |
133 | +include/linux/kernel-page-flags.h and documented in | |
134 | +Documentation/vm/pagemap.txt | |
135 | + | |
126 | 136 | Architecture specific MCE injector |
127 | 137 | |
128 | 138 | x86 has mce-inject, mce-test |
mm/Kconfig
mm/hwpoison-inject.c
... | ... | @@ -102,6 +102,16 @@ |
102 | 102 | if (!dentry) |
103 | 103 | goto fail; |
104 | 104 | |
105 | + dentry = debugfs_create_u64("corrupt-filter-flags-mask", 0600, | |
106 | + hwpoison_dir, &hwpoison_filter_flags_mask); | |
107 | + if (!dentry) | |
108 | + goto fail; | |
109 | + | |
110 | + dentry = debugfs_create_u64("corrupt-filter-flags-value", 0600, | |
111 | + hwpoison_dir, &hwpoison_filter_flags_value); | |
112 | + if (!dentry) | |
113 | + goto fail; | |
114 | + | |
105 | 115 | return 0; |
106 | 116 | fail: |
107 | 117 | pfn_inject_exit(); |
mm/internal.h
mm/memory-failure.c
... | ... | @@ -34,6 +34,7 @@ |
34 | 34 | #include <linux/kernel.h> |
35 | 35 | #include <linux/mm.h> |
36 | 36 | #include <linux/page-flags.h> |
37 | +#include <linux/kernel-page-flags.h> | |
37 | 38 | #include <linux/sched.h> |
38 | 39 | #include <linux/ksm.h> |
39 | 40 | #include <linux/rmap.h> |
40 | 41 | |
... | ... | @@ -50,8 +51,12 @@ |
50 | 51 | |
51 | 52 | u32 hwpoison_filter_dev_major = ~0U; |
52 | 53 | u32 hwpoison_filter_dev_minor = ~0U; |
54 | +u64 hwpoison_filter_flags_mask; | |
55 | +u64 hwpoison_filter_flags_value; | |
53 | 56 | EXPORT_SYMBOL_GPL(hwpoison_filter_dev_major); |
54 | 57 | EXPORT_SYMBOL_GPL(hwpoison_filter_dev_minor); |
58 | +EXPORT_SYMBOL_GPL(hwpoison_filter_flags_mask); | |
59 | +EXPORT_SYMBOL_GPL(hwpoison_filter_flags_value); | |
55 | 60 | |
56 | 61 | static int hwpoison_filter_dev(struct page *p) |
57 | 62 | { |
58 | 63 | |
... | ... | @@ -83,9 +88,24 @@ |
83 | 88 | return 0; |
84 | 89 | } |
85 | 90 | |
91 | +static 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 | + | |
86 | 103 | int hwpoison_filter(struct page *p) |
87 | 104 | { |
88 | 105 | if (hwpoison_filter_dev(p)) |
106 | + return -EINVAL; | |
107 | + | |
108 | + if (hwpoison_filter_flags(p)) | |
89 | 109 | return -EINVAL; |
90 | 110 | |
91 | 111 | return 0; |