Blame view

mm/hwpoison-inject.c 3.23 KB
25985edce   Lucas De Marchi   Fix common misspe...
1
  /* Inject a hwpoison memory failure on a arbitrary pfn */
cae681fc1   Andi Kleen   HWPOISON: Add sim...
2
3
4
5
  #include <linux/module.h>
  #include <linux/debugfs.h>
  #include <linux/kernel.h>
  #include <linux/mm.h>
31d3d3484   Wu Fengguang   HWPOISON: limit h...
6
7
  #include <linux/swap.h>
  #include <linux/pagemap.h>
43131e141   Naoya Horiguchi   HWPOISON, hugetlb...
8
  #include <linux/hugetlb.h>
7c116f2b0   Wu Fengguang   HWPOISON: add fs/...
9
  #include "internal.h"
cae681fc1   Andi Kleen   HWPOISON: Add sim...
10

847ce401d   Wu Fengguang   HWPOISON: Add unp...
11
  static struct dentry *hwpoison_dir;
cae681fc1   Andi Kleen   HWPOISON: Add sim...
12
13
14
  
  static int hwpoison_inject(void *data, u64 val)
  {
31d3d3484   Wu Fengguang   HWPOISON: limit h...
15
16
  	unsigned long pfn = val;
  	struct page *p;
43131e141   Naoya Horiguchi   HWPOISON, hugetlb...
17
  	struct page *hpage;
31d3d3484   Wu Fengguang   HWPOISON: limit h...
18
  	int err;
cae681fc1   Andi Kleen   HWPOISON: Add sim...
19
20
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
31d3d3484   Wu Fengguang   HWPOISON: limit h...
21
22
23
24
25
  
  	if (!pfn_valid(pfn))
  		return -ENXIO;
  
  	p = pfn_to_page(pfn);
43131e141   Naoya Horiguchi   HWPOISON, hugetlb...
26
  	hpage = compound_head(p);
31d3d3484   Wu Fengguang   HWPOISON: limit h...
27
28
29
  	/*
  	 * This implies unable to support free buddy pages.
  	 */
ead07f6a8   Naoya Horiguchi   mm/memory-failure...
30
  	if (!get_hwpoison_page(p))
31d3d3484   Wu Fengguang   HWPOISON: limit h...
31
  		return 0;
fb31ba30f   Wanpeng Li   mm/hwpoison: fix ...
32
33
  	if (!hwpoison_filter_enable)
  		goto inject;
e386eed89   Naoya Horiguchi   mm/hwpoison-injec...
34
35
  	if (!PageLRU(hpage) && !PageHuge(p))
  		shake_page(hpage, 0);
31d3d3484   Wu Fengguang   HWPOISON: limit h...
36
37
38
  	/*
  	 * This implies unable to support non-LRU pages.
  	 */
e386eed89   Naoya Horiguchi   mm/hwpoison-injec...
39
  	if (!PageLRU(hpage) && !PageHuge(p))
7ea434a4e   Naoya Horiguchi   mm/hwpoison-injec...
40
  		goto put_out;
31d3d3484   Wu Fengguang   HWPOISON: limit h...
41
42
43
44
  
  	/*
  	 * 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).
cd42f4a3b   Tony Luck   HWPOISON: Clean u...
45
  	 * memory_failure() will redo the check reliably inside page lock.
31d3d3484   Wu Fengguang   HWPOISON: limit h...
46
  	 */
43131e141   Naoya Horiguchi   HWPOISON, hugetlb...
47
  	err = hwpoison_filter(hpage);
31d3d3484   Wu Fengguang   HWPOISON: limit h...
48
  	if (err)
7ea434a4e   Naoya Horiguchi   mm/hwpoison-injec...
49
  		goto put_out;
31d3d3484   Wu Fengguang   HWPOISON: limit h...
50

0d57eb8df   Andi Kleen   HWPOISON: Don't d...
51
  inject:
4883e997b   Wanpeng Li   mm/hwpoison: add ...
52
53
  	pr_info("Injecting memory failure at pfn %#lx
  ", pfn);
cd42f4a3b   Tony Luck   HWPOISON: Clean u...
54
  	return memory_failure(pfn, 18, MF_COUNT_INCREASED);
7ea434a4e   Naoya Horiguchi   mm/hwpoison-injec...
55
  put_out:
be91748fa   Wanpeng Li   mm/hwpoison: fix ...
56
  	put_hwpoison_page(p);
7ea434a4e   Naoya Horiguchi   mm/hwpoison-injec...
57
  	return 0;
cae681fc1   Andi Kleen   HWPOISON: Add sim...
58
  }
847ce401d   Wu Fengguang   HWPOISON: Add unp...
59
60
61
62
63
64
65
  static int hwpoison_unpoison(void *data, u64 val)
  {
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	return unpoison_memory(val);
  }
cae681fc1   Andi Kleen   HWPOISON: Add sim...
66
67
  DEFINE_SIMPLE_ATTRIBUTE(hwpoison_fops, NULL, hwpoison_inject, "%lli
  ");
847ce401d   Wu Fengguang   HWPOISON: Add unp...
68
69
  DEFINE_SIMPLE_ATTRIBUTE(unpoison_fops, NULL, hwpoison_unpoison, "%lli
  ");
cae681fc1   Andi Kleen   HWPOISON: Add sim...
70
71
72
  
  static void pfn_inject_exit(void)
  {
c2ea2181d   Fabian Frederick   mm/hwpoison-injec...
73
  	debugfs_remove_recursive(hwpoison_dir);
cae681fc1   Andi Kleen   HWPOISON: Add sim...
74
75
76
77
  }
  
  static int pfn_inject_init(void)
  {
847ce401d   Wu Fengguang   HWPOISON: Add unp...
78
  	struct dentry *dentry;
cae681fc1   Andi Kleen   HWPOISON: Add sim...
79
80
81
  	hwpoison_dir = debugfs_create_dir("hwpoison", NULL);
  	if (hwpoison_dir == NULL)
  		return -ENOMEM;
847ce401d   Wu Fengguang   HWPOISON: Add unp...
82
83
84
85
86
87
  
  	/*
  	 * 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.
  	 */
2d1e8b3f1   Wanpeng Li   mm/hwpoison-injec...
88
  	dentry = debugfs_create_file("corrupt-pfn", 0200, hwpoison_dir,
cae681fc1   Andi Kleen   HWPOISON: Add sim...
89
  					  NULL, &hwpoison_fops);
847ce401d   Wu Fengguang   HWPOISON: Add unp...
90
91
  	if (!dentry)
  		goto fail;
2d1e8b3f1   Wanpeng Li   mm/hwpoison-injec...
92
  	dentry = debugfs_create_file("unpoison-pfn", 0200, hwpoison_dir,
847ce401d   Wu Fengguang   HWPOISON: Add unp...
93
94
95
  				     NULL, &unpoison_fops);
  	if (!dentry)
  		goto fail;
1bfe5febe   Haicheng Li   HWPOISON: add an ...
96
97
98
99
  	dentry = debugfs_create_u32("corrupt-filter-enable", 0600,
  				    hwpoison_dir, &hwpoison_filter_enable);
  	if (!dentry)
  		goto fail;
7c116f2b0   Wu Fengguang   HWPOISON: add fs/...
100
101
102
103
104
105
106
107
108
  	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   Wu Fengguang   HWPOISON: add pag...
109
110
111
112
113
114
115
116
117
  	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;
94a59fb36   Vladimir Davydov   hwpoison: use pag...
118
  #ifdef CONFIG_MEMCG
4fd466eb4   Andi Kleen   HWPOISON: add mem...
119
120
121
122
123
  	dentry = debugfs_create_u64("corrupt-filter-memcg", 0600,
  				    hwpoison_dir, &hwpoison_filter_memcg);
  	if (!dentry)
  		goto fail;
  #endif
cae681fc1   Andi Kleen   HWPOISON: Add sim...
124
  	return 0;
847ce401d   Wu Fengguang   HWPOISON: Add unp...
125
126
127
  fail:
  	pfn_inject_exit();
  	return -ENOMEM;
cae681fc1   Andi Kleen   HWPOISON: Add sim...
128
129
130
131
132
  }
  
  module_init(pfn_inject_init);
  module_exit(pfn_inject_exit);
  MODULE_LICENSE("GPL");