mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 11:46:19 +00:00
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>
This commit is contained in:
parent
1a9b5b7fe0
commit
478c5ffc0b
5 changed files with 43 additions and 0 deletions
|
@ -123,6 +123,16 @@ Only handle memory failures to pages associated with the file system defined
|
||||||
by block device major/minor. -1U is the wildcard value.
|
by block device major/minor. -1U is the wildcard value.
|
||||||
This should be only used for testing with artificial injection.
|
This should be only used for testing with artificial injection.
|
||||||
|
|
||||||
|
|
||||||
|
corrupt-filter-flags-mask
|
||||||
|
corrupt-filter-flags-value
|
||||||
|
|
||||||
|
When specified, only poison pages if ((page_flags & mask) == value).
|
||||||
|
This allows stress testing of many kinds of pages. The page_flags
|
||||||
|
are the same as in /proc/kpageflags. The flag bits are defined in
|
||||||
|
include/linux/kernel-page-flags.h and documented in
|
||||||
|
Documentation/vm/pagemap.txt
|
||||||
|
|
||||||
Architecture specific MCE injector
|
Architecture specific MCE injector
|
||||||
|
|
||||||
x86 has mce-inject, mce-test
|
x86 has mce-inject, mce-test
|
||||||
|
|
|
@ -253,6 +253,7 @@ config MEMORY_FAILURE
|
||||||
config HWPOISON_INJECT
|
config HWPOISON_INJECT
|
||||||
tristate "Poison pages injector"
|
tristate "Poison pages injector"
|
||||||
depends on MEMORY_FAILURE && DEBUG_KERNEL
|
depends on MEMORY_FAILURE && DEBUG_KERNEL
|
||||||
|
select PROC_PAGE_MONITOR
|
||||||
|
|
||||||
config NOMMU_INITIAL_TRIM_EXCESS
|
config NOMMU_INITIAL_TRIM_EXCESS
|
||||||
int "Turn on mmap() excess space trimming before booting"
|
int "Turn on mmap() excess space trimming before booting"
|
||||||
|
|
|
@ -102,6 +102,16 @@ static int pfn_inject_init(void)
|
||||||
if (!dentry)
|
if (!dentry)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
dentry = debugfs_create_u64("corrupt-filter-flags-mask", 0600,
|
||||||
|
hwpoison_dir, &hwpoison_filter_flags_mask);
|
||||||
|
if (!dentry)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
dentry = debugfs_create_u64("corrupt-filter-flags-value", 0600,
|
||||||
|
hwpoison_dir, &hwpoison_filter_flags_value);
|
||||||
|
if (!dentry)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
fail:
|
fail:
|
||||||
pfn_inject_exit();
|
pfn_inject_exit();
|
||||||
|
|
|
@ -255,3 +255,5 @@ extern int hwpoison_filter(struct page *p);
|
||||||
|
|
||||||
extern u32 hwpoison_filter_dev_major;
|
extern u32 hwpoison_filter_dev_major;
|
||||||
extern u32 hwpoison_filter_dev_minor;
|
extern u32 hwpoison_filter_dev_minor;
|
||||||
|
extern u64 hwpoison_filter_flags_mask;
|
||||||
|
extern u64 hwpoison_filter_flags_value;
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/page-flags.h>
|
#include <linux/page-flags.h>
|
||||||
|
#include <linux/kernel-page-flags.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/ksm.h>
|
#include <linux/ksm.h>
|
||||||
#include <linux/rmap.h>
|
#include <linux/rmap.h>
|
||||||
|
@ -50,8 +51,12 @@ atomic_long_t mce_bad_pages __read_mostly = ATOMIC_LONG_INIT(0);
|
||||||
|
|
||||||
u32 hwpoison_filter_dev_major = ~0U;
|
u32 hwpoison_filter_dev_major = ~0U;
|
||||||
u32 hwpoison_filter_dev_minor = ~0U;
|
u32 hwpoison_filter_dev_minor = ~0U;
|
||||||
|
u64 hwpoison_filter_flags_mask;
|
||||||
|
u64 hwpoison_filter_flags_value;
|
||||||
EXPORT_SYMBOL_GPL(hwpoison_filter_dev_major);
|
EXPORT_SYMBOL_GPL(hwpoison_filter_dev_major);
|
||||||
EXPORT_SYMBOL_GPL(hwpoison_filter_dev_minor);
|
EXPORT_SYMBOL_GPL(hwpoison_filter_dev_minor);
|
||||||
|
EXPORT_SYMBOL_GPL(hwpoison_filter_flags_mask);
|
||||||
|
EXPORT_SYMBOL_GPL(hwpoison_filter_flags_value);
|
||||||
|
|
||||||
static int hwpoison_filter_dev(struct page *p)
|
static int hwpoison_filter_dev(struct page *p)
|
||||||
{
|
{
|
||||||
|
@ -83,11 +88,26 @@ static int hwpoison_filter_dev(struct page *p)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hwpoison_filter_flags(struct page *p)
|
||||||
|
{
|
||||||
|
if (!hwpoison_filter_flags_mask)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ((stable_page_flags(p) & hwpoison_filter_flags_mask) ==
|
||||||
|
hwpoison_filter_flags_value)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
int hwpoison_filter(struct page *p)
|
int hwpoison_filter(struct page *p)
|
||||||
{
|
{
|
||||||
if (hwpoison_filter_dev(p))
|
if (hwpoison_filter_dev(p))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (hwpoison_filter_flags(p))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(hwpoison_filter);
|
EXPORT_SYMBOL_GPL(hwpoison_filter);
|
||||||
|
|
Loading…
Reference in a new issue