Version:  2.0.40 2.2.26 2.4.37 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10

Linux/mm/hwpoison-inject.c

  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 
 11 static struct dentry *hwpoison_dir;
 12 
 13 static 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_hwpoison_page(p))
 32                 return 0;
 33 
 34         if (!hwpoison_filter_enable)
 35                 goto inject;
 36 
 37         if (!PageLRU(hpage) && !PageHuge(p))
 38                 shake_page(hpage, 0);
 39         /*
 40          * This implies unable to support non-LRU pages.
 41          */
 42         if (!PageLRU(hpage) && !PageHuge(p))
 43                 goto put_out;
 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          * memory_failure() will redo the check reliably inside page lock.
 49          */
 50         err = hwpoison_filter(hpage);
 51         if (err)
 52                 goto put_out;
 53 
 54 inject:
 55         pr_info("Injecting memory failure at pfn %#lx\n", pfn);
 56         return memory_failure(pfn, 18, MF_COUNT_INCREASED);
 57 put_out:
 58         put_hwpoison_page(p);
 59         return 0;
 60 }
 61 
 62 static 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 
 70 DEFINE_SIMPLE_ATTRIBUTE(hwpoison_fops, NULL, hwpoison_inject, "%lli\n");
 71 DEFINE_SIMPLE_ATTRIBUTE(unpoison_fops, NULL, hwpoison_unpoison, "%lli\n");
 72 
 73 static void pfn_inject_exit(void)
 74 {
 75         debugfs_remove_recursive(hwpoison_dir);
 76 }
 77 
 78 static int pfn_inject_init(void)
 79 {
 80         struct dentry *dentry;
 81 
 82         hwpoison_dir = debugfs_create_dir("hwpoison", NULL);
 83         if (hwpoison_dir == NULL)
 84                 return -ENOMEM;
 85 
 86         /*
 87          * Note that the below poison/unpoison interfaces do not involve
 88          * hardware status change, hence do not require hardware support.
 89          * They are mainly for testing hwpoison in software level.
 90          */
 91         dentry = debugfs_create_file("corrupt-pfn", 0200, hwpoison_dir,
 92                                           NULL, &hwpoison_fops);
 93         if (!dentry)
 94                 goto fail;
 95 
 96         dentry = debugfs_create_file("unpoison-pfn", 0200, hwpoison_dir,
 97                                      NULL, &unpoison_fops);
 98         if (!dentry)
 99                 goto fail;
100 
101         dentry = debugfs_create_u32("corrupt-filter-enable", 0600,
102                                     hwpoison_dir, &hwpoison_filter_enable);
103         if (!dentry)
104                 goto fail;
105 
106         dentry = debugfs_create_u32("corrupt-filter-dev-major", 0600,
107                                     hwpoison_dir, &hwpoison_filter_dev_major);
108         if (!dentry)
109                 goto fail;
110 
111         dentry = debugfs_create_u32("corrupt-filter-dev-minor", 0600,
112                                     hwpoison_dir, &hwpoison_filter_dev_minor);
113         if (!dentry)
114                 goto fail;
115 
116         dentry = debugfs_create_u64("corrupt-filter-flags-mask", 0600,
117                                     hwpoison_dir, &hwpoison_filter_flags_mask);
118         if (!dentry)
119                 goto fail;
120 
121         dentry = debugfs_create_u64("corrupt-filter-flags-value", 0600,
122                                     hwpoison_dir, &hwpoison_filter_flags_value);
123         if (!dentry)
124                 goto fail;
125 
126 #ifdef CONFIG_MEMCG
127         dentry = debugfs_create_u64("corrupt-filter-memcg", 0600,
128                                     hwpoison_dir, &hwpoison_filter_memcg);
129         if (!dentry)
130                 goto fail;
131 #endif
132 
133         return 0;
134 fail:
135         pfn_inject_exit();
136         return -ENOMEM;
137 }
138 
139 module_init(pfn_inject_init);
140 module_exit(pfn_inject_exit);
141 MODULE_LICENSE("GPL");
142 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us