Blame view
mm/hwpoison-inject.c
3.33 KB
25985edce Fix common misspe... |
1 |
/* Inject a hwpoison memory failure on a arbitrary pfn */ |
cae681fc1 HWPOISON: Add sim... |
2 3 4 5 |
#include <linux/module.h> #include <linux/debugfs.h> #include <linux/kernel.h> #include <linux/mm.h> |
31d3d3484 HWPOISON: limit h... |
6 7 |
#include <linux/swap.h> #include <linux/pagemap.h> |
43131e141 HWPOISON, hugetlb... |
8 |
#include <linux/hugetlb.h> |
7c116f2b0 HWPOISON: add fs/... |
9 |
#include "internal.h" |
cae681fc1 HWPOISON: Add sim... |
10 |
|
847ce401d HWPOISON: Add unp... |
11 |
static struct dentry *hwpoison_dir; |
cae681fc1 HWPOISON: Add sim... |
12 13 14 |
static int hwpoison_inject(void *data, u64 val) { |
31d3d3484 HWPOISON: limit h... |
15 16 |
unsigned long pfn = val; struct page *p; |
43131e141 HWPOISON, hugetlb... |
17 |
struct page *hpage; |
31d3d3484 HWPOISON: limit h... |
18 |
int err; |
cae681fc1 HWPOISON: Add sim... |
19 20 |
if (!capable(CAP_SYS_ADMIN)) return -EPERM; |
31d3d3484 HWPOISON: limit h... |
21 |
|
0d57eb8df HWPOISON: Don't d... |
22 23 |
if (!hwpoison_filter_enable) goto inject; |
31d3d3484 HWPOISON: limit h... |
24 25 26 27 |
if (!pfn_valid(pfn)) return -ENXIO; p = pfn_to_page(pfn); |
43131e141 HWPOISON, hugetlb... |
28 |
hpage = compound_head(p); |
31d3d3484 HWPOISON: limit h... |
29 30 31 |
/* * This implies unable to support free buddy pages. */ |
43131e141 HWPOISON, hugetlb... |
32 |
if (!get_page_unless_zero(hpage)) |
31d3d3484 HWPOISON: limit h... |
33 |
return 0; |
43131e141 HWPOISON, hugetlb... |
34 |
if (!PageLRU(p) && !PageHuge(p)) |
facb6011f HWPOISON: Add sof... |
35 |
shake_page(p, 0); |
31d3d3484 HWPOISON: limit h... |
36 37 38 |
/* * This implies unable to support non-LRU pages. */ |
43131e141 HWPOISON, hugetlb... |
39 |
if (!PageLRU(p) && !PageHuge(p)) |
31d3d3484 HWPOISON: limit h... |
40 41 42 43 44 45 46 47 |
return 0; /* * do a racy check with elevated page count, to make sure PG_hwpoison * will only be set for the targeted owner (or on a free page). * We temporarily take page lock for try_get_mem_cgroup_from_page(). * __memory_failure() will redo the check reliably inside page lock. */ |
43131e141 HWPOISON, hugetlb... |
48 49 50 |
lock_page(hpage); err = hwpoison_filter(hpage); unlock_page(hpage); |
31d3d3484 HWPOISON: limit h... |
51 52 |
if (err) return 0; |
0d57eb8df HWPOISON: Don't d... |
53 |
inject: |
31d3d3484 HWPOISON: limit h... |
54 55 56 |
printk(KERN_INFO "Injecting memory failure at pfn %lx ", pfn); return __memory_failure(pfn, 18, MF_COUNT_INCREASED); |
cae681fc1 HWPOISON: Add sim... |
57 |
} |
847ce401d HWPOISON: Add unp... |
58 59 60 61 62 63 64 |
static int hwpoison_unpoison(void *data, u64 val) { if (!capable(CAP_SYS_ADMIN)) return -EPERM; return unpoison_memory(val); } |
cae681fc1 HWPOISON: Add sim... |
65 66 |
DEFINE_SIMPLE_ATTRIBUTE(hwpoison_fops, NULL, hwpoison_inject, "%lli "); |
847ce401d HWPOISON: Add unp... |
67 68 |
DEFINE_SIMPLE_ATTRIBUTE(unpoison_fops, NULL, hwpoison_unpoison, "%lli "); |
cae681fc1 HWPOISON: Add sim... |
69 70 71 72 73 74 75 76 77 |
static void pfn_inject_exit(void) { if (hwpoison_dir) debugfs_remove_recursive(hwpoison_dir); } static int pfn_inject_init(void) { |
847ce401d HWPOISON: Add unp... |
78 |
struct dentry *dentry; |
cae681fc1 HWPOISON: Add sim... |
79 80 81 |
hwpoison_dir = debugfs_create_dir("hwpoison", NULL); if (hwpoison_dir == NULL) return -ENOMEM; |
847ce401d HWPOISON: Add unp... |
82 83 84 85 86 87 88 |
/* * Note that the below poison/unpoison interfaces do not involve * hardware status change, hence do not require hardware support. * They are mainly for testing hwpoison in software level. */ dentry = debugfs_create_file("corrupt-pfn", 0600, hwpoison_dir, |
cae681fc1 HWPOISON: Add sim... |
89 |
NULL, &hwpoison_fops); |
847ce401d HWPOISON: Add unp... |
90 91 92 93 94 95 96 |
if (!dentry) goto fail; dentry = debugfs_create_file("unpoison-pfn", 0600, hwpoison_dir, NULL, &unpoison_fops); if (!dentry) goto fail; |
1bfe5febe HWPOISON: add an ... |
97 98 99 100 |
dentry = debugfs_create_u32("corrupt-filter-enable", 0600, hwpoison_dir, &hwpoison_filter_enable); if (!dentry) goto fail; |
7c116f2b0 HWPOISON: add fs/... |
101 102 103 104 105 106 107 108 109 |
dentry = debugfs_create_u32("corrupt-filter-dev-major", 0600, hwpoison_dir, &hwpoison_filter_dev_major); if (!dentry) goto fail; dentry = debugfs_create_u32("corrupt-filter-dev-minor", 0600, hwpoison_dir, &hwpoison_filter_dev_minor); if (!dentry) goto fail; |
478c5ffc0 HWPOISON: add pag... |
110 111 112 113 114 115 116 117 118 |
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; |
4fd466eb4 HWPOISON: add mem... |
119 120 121 122 123 124 |
#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP dentry = debugfs_create_u64("corrupt-filter-memcg", 0600, hwpoison_dir, &hwpoison_filter_memcg); if (!dentry) goto fail; #endif |
cae681fc1 HWPOISON: Add sim... |
125 |
return 0; |
847ce401d HWPOISON: Add unp... |
126 127 128 |
fail: pfn_inject_exit(); return -ENOMEM; |
cae681fc1 HWPOISON: Add sim... |
129 130 131 132 133 |
} module_init(pfn_inject_init); module_exit(pfn_inject_exit); MODULE_LICENSE("GPL"); |