Blame view
mm/hwpoison-inject.c
2.82 KB
09c434b8a treewide: Add SPD... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
25985edce Fix common misspe... |
2 |
/* Inject a hwpoison memory failure on a arbitrary pfn */ |
cae681fc1 HWPOISON: Add sim... |
3 4 5 6 |
#include <linux/module.h> #include <linux/debugfs.h> #include <linux/kernel.h> #include <linux/mm.h> |
31d3d3484 HWPOISON: limit h... |
7 8 |
#include <linux/swap.h> #include <linux/pagemap.h> |
43131e141 HWPOISON, hugetlb... |
9 |
#include <linux/hugetlb.h> |
7c116f2b0 HWPOISON: add fs/... |
10 |
#include "internal.h" |
cae681fc1 HWPOISON: Add sim... |
11 |
|
847ce401d HWPOISON: Add unp... |
12 |
static struct dentry *hwpoison_dir; |
cae681fc1 HWPOISON: Add sim... |
13 14 15 |
static int hwpoison_inject(void *data, u64 val) { |
31d3d3484 HWPOISON: limit h... |
16 17 |
unsigned long pfn = val; struct page *p; |
43131e141 HWPOISON, hugetlb... |
18 |
struct page *hpage; |
31d3d3484 HWPOISON: limit h... |
19 |
int err; |
cae681fc1 HWPOISON: Add sim... |
20 21 |
if (!capable(CAP_SYS_ADMIN)) return -EPERM; |
31d3d3484 HWPOISON: limit h... |
22 23 24 25 26 |
if (!pfn_valid(pfn)) return -ENXIO; p = pfn_to_page(pfn); |
43131e141 HWPOISON, hugetlb... |
27 |
hpage = compound_head(p); |
31d3d3484 HWPOISON: limit h... |
28 29 30 |
/* * This implies unable to support free buddy pages. */ |
ead07f6a8 mm/memory-failure... |
31 |
if (!get_hwpoison_page(p)) |
31d3d3484 HWPOISON: limit h... |
32 |
return 0; |
fb31ba30f mm/hwpoison: fix ... |
33 34 |
if (!hwpoison_filter_enable) goto inject; |
8bcb74de7 mm: hwpoison: cal... |
35 |
shake_page(hpage, 0); |
31d3d3484 HWPOISON: limit h... |
36 37 38 |
/* * This implies unable to support non-LRU pages. */ |
e386eed89 mm/hwpoison-injec... |
39 |
if (!PageLRU(hpage) && !PageHuge(p)) |
7ea434a4e mm/hwpoison-injec... |
40 |
goto put_out; |
31d3d3484 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 HWPOISON: Clean u... |
45 |
* memory_failure() will redo the check reliably inside page lock. |
31d3d3484 HWPOISON: limit h... |
46 |
*/ |
43131e141 HWPOISON, hugetlb... |
47 |
err = hwpoison_filter(hpage); |
31d3d3484 HWPOISON: limit h... |
48 |
if (err) |
7ea434a4e mm/hwpoison-injec... |
49 |
goto put_out; |
31d3d3484 HWPOISON: limit h... |
50 |
|
0d57eb8df HWPOISON: Don't d... |
51 |
inject: |
4883e997b mm/hwpoison: add ... |
52 53 |
pr_info("Injecting memory failure at pfn %#lx ", pfn); |
83b57531c mm/memory_failure... |
54 |
return memory_failure(pfn, MF_COUNT_INCREASED); |
7ea434a4e mm/hwpoison-injec... |
55 |
put_out: |
be91748fa mm/hwpoison: fix ... |
56 |
put_hwpoison_page(p); |
7ea434a4e mm/hwpoison-injec... |
57 |
return 0; |
cae681fc1 HWPOISON: Add sim... |
58 |
} |
847ce401d 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 HWPOISON: Add sim... |
66 67 |
DEFINE_SIMPLE_ATTRIBUTE(hwpoison_fops, NULL, hwpoison_inject, "%lli "); |
847ce401d HWPOISON: Add unp... |
68 69 |
DEFINE_SIMPLE_ATTRIBUTE(unpoison_fops, NULL, hwpoison_unpoison, "%lli "); |
cae681fc1 HWPOISON: Add sim... |
70 71 72 |
static void pfn_inject_exit(void) { |
c2ea2181d mm/hwpoison-injec... |
73 |
debugfs_remove_recursive(hwpoison_dir); |
cae681fc1 HWPOISON: Add sim... |
74 75 76 77 78 |
} static int pfn_inject_init(void) { hwpoison_dir = debugfs_create_dir("hwpoison", NULL); |
847ce401d HWPOISON: Add unp... |
79 80 81 82 83 84 |
/* * 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. */ |
2fcc6e202 hwpoison-inject: ... |
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
debugfs_create_file("corrupt-pfn", 0200, hwpoison_dir, NULL, &hwpoison_fops); debugfs_create_file("unpoison-pfn", 0200, hwpoison_dir, NULL, &unpoison_fops); debugfs_create_u32("corrupt-filter-enable", 0600, hwpoison_dir, &hwpoison_filter_enable); debugfs_create_u32("corrupt-filter-dev-major", 0600, hwpoison_dir, &hwpoison_filter_dev_major); debugfs_create_u32("corrupt-filter-dev-minor", 0600, hwpoison_dir, &hwpoison_filter_dev_minor); debugfs_create_u64("corrupt-filter-flags-mask", 0600, hwpoison_dir, &hwpoison_filter_flags_mask); debugfs_create_u64("corrupt-filter-flags-value", 0600, hwpoison_dir, &hwpoison_filter_flags_value); |
478c5ffc0 HWPOISON: add pag... |
105 |
|
94a59fb36 hwpoison: use pag... |
106 |
#ifdef CONFIG_MEMCG |
2fcc6e202 hwpoison-inject: ... |
107 108 |
debugfs_create_u64("corrupt-filter-memcg", 0600, hwpoison_dir, &hwpoison_filter_memcg); |
4fd466eb4 HWPOISON: add mem... |
109 |
#endif |
cae681fc1 HWPOISON: Add sim... |
110 111 112 113 114 115 |
return 0; } module_init(pfn_inject_init); module_exit(pfn_inject_exit); MODULE_LICENSE("GPL"); |