Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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