Blame view

mm/hwpoison-inject.c 3.19 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;
8bcb74de7   Naoya Horiguchi   mm: hwpoison: cal...
34
  	shake_page(hpage, 0);
31d3d3484   Wu Fengguang   HWPOISON: limit h...
35
36
37
  	/*
  	 * This implies unable to support non-LRU pages.
  	 */
e386eed89   Naoya Horiguchi   mm/hwpoison-injec...
38
  	if (!PageLRU(hpage) && !PageHuge(p))
7ea434a4e   Naoya Horiguchi   mm/hwpoison-injec...
39
  		goto put_out;
31d3d3484   Wu Fengguang   HWPOISON: limit h...
40
41
42
43
  
  	/*
  	 * 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...
44
  	 * memory_failure() will redo the check reliably inside page lock.
31d3d3484   Wu Fengguang   HWPOISON: limit h...
45
  	 */
43131e141   Naoya Horiguchi   HWPOISON, hugetlb...
46
  	err = hwpoison_filter(hpage);
31d3d3484   Wu Fengguang   HWPOISON: limit h...
47
  	if (err)
7ea434a4e   Naoya Horiguchi   mm/hwpoison-injec...
48
  		goto put_out;
31d3d3484   Wu Fengguang   HWPOISON: limit h...
49

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