diff options
Diffstat (limited to 'mm/memory-failure.c')
-rw-r--r-- | mm/memory-failure.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index edeaf2319e74..82ac73436d0e 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c | |||
@@ -48,6 +48,50 @@ int sysctl_memory_failure_recovery __read_mostly = 1; | |||
48 | 48 | ||
49 | atomic_long_t mce_bad_pages __read_mostly = ATOMIC_LONG_INIT(0); | 49 | atomic_long_t mce_bad_pages __read_mostly = ATOMIC_LONG_INIT(0); |
50 | 50 | ||
51 | u32 hwpoison_filter_dev_major = ~0U; | ||
52 | u32 hwpoison_filter_dev_minor = ~0U; | ||
53 | EXPORT_SYMBOL_GPL(hwpoison_filter_dev_major); | ||
54 | EXPORT_SYMBOL_GPL(hwpoison_filter_dev_minor); | ||
55 | |||
56 | static int hwpoison_filter_dev(struct page *p) | ||
57 | { | ||
58 | struct address_space *mapping; | ||
59 | dev_t dev; | ||
60 | |||
61 | if (hwpoison_filter_dev_major == ~0U && | ||
62 | hwpoison_filter_dev_minor == ~0U) | ||
63 | return 0; | ||
64 | |||
65 | /* | ||
66 | * page_mapping() does not accept slab page | ||
67 | */ | ||
68 | if (PageSlab(p)) | ||
69 | return -EINVAL; | ||
70 | |||
71 | mapping = page_mapping(p); | ||
72 | if (mapping == NULL || mapping->host == NULL) | ||
73 | return -EINVAL; | ||
74 | |||
75 | dev = mapping->host->i_sb->s_dev; | ||
76 | if (hwpoison_filter_dev_major != ~0U && | ||
77 | hwpoison_filter_dev_major != MAJOR(dev)) | ||
78 | return -EINVAL; | ||
79 | if (hwpoison_filter_dev_minor != ~0U && | ||
80 | hwpoison_filter_dev_minor != MINOR(dev)) | ||
81 | return -EINVAL; | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | int hwpoison_filter(struct page *p) | ||
87 | { | ||
88 | if (hwpoison_filter_dev(p)) | ||
89 | return -EINVAL; | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | EXPORT_SYMBOL_GPL(hwpoison_filter); | ||
94 | |||
51 | /* | 95 | /* |
52 | * Send all the processes who have the page mapped an ``action optional'' | 96 | * Send all the processes who have the page mapped an ``action optional'' |
53 | * signal. | 97 | * signal. |
@@ -843,6 +887,13 @@ int __memory_failure(unsigned long pfn, int trapno, int flags) | |||
843 | res = 0; | 887 | res = 0; |
844 | goto out; | 888 | goto out; |
845 | } | 889 | } |
890 | if (hwpoison_filter(p)) { | ||
891 | if (TestClearPageHWPoison(p)) | ||
892 | atomic_long_dec(&mce_bad_pages); | ||
893 | unlock_page(p); | ||
894 | put_page(p); | ||
895 | return 0; | ||
896 | } | ||
846 | 897 | ||
847 | wait_on_page_writeback(p); | 898 | wait_on_page_writeback(p); |
848 | 899 | ||