The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/mm/hwpoison-inject.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 (!hwpoison_filter_enable)
   24                 goto inject;
   25         if (!pfn_valid(pfn))
   26                 return -ENXIO;
   27 
   28         p = pfn_to_page(pfn);
   29         hpage = compound_head(p);
   30         /*
   31          * This implies unable to support free buddy pages.
   32          */
   33         if (!get_page_unless_zero(hpage))
   34                 return 0;
   35 
   36         if (!PageLRU(p) && !PageHuge(p))
   37                 shake_page(p, 0);
   38         /*
   39          * This implies unable to support non-LRU pages.
   40          */
   41         if (!PageLRU(p) && !PageHuge(p))
   42                 return 0;
   43 
   44         /*
   45          * do a racy check with elevated page count, to make sure PG_hwpoison
   46          * will only be set for the targeted owner (or on a free page).
   47          * We temporarily take page lock for try_get_mem_cgroup_from_page().
   48          * memory_failure() will redo the check reliably inside page lock.
   49          */
   50         lock_page(hpage);
   51         err = hwpoison_filter(hpage);
   52         unlock_page(hpage);
   53         if (err)
   54                 return 0;
   55 
   56 inject:
   57         printk(KERN_INFO "Injecting memory failure at pfn %lx\n", pfn);
   58         return memory_failure(pfn, 18, MF_COUNT_INCREASED);
   59 }
   60 
   61 static int hwpoison_unpoison(void *data, u64 val)
   62 {
   63         if (!capable(CAP_SYS_ADMIN))
   64                 return -EPERM;
   65 
   66         return unpoison_memory(val);
   67 }
   68 
   69 DEFINE_SIMPLE_ATTRIBUTE(hwpoison_fops, NULL, hwpoison_inject, "%lli\n");
   70 DEFINE_SIMPLE_ATTRIBUTE(unpoison_fops, NULL, hwpoison_unpoison, "%lli\n");
   71 
   72 static void pfn_inject_exit(void)
   73 {
   74         if (hwpoison_dir)
   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", 0600, hwpoison_dir,
   92                                           NULL, &hwpoison_fops);
   93         if (!dentry)
   94                 goto fail;
   95 
   96         dentry = debugfs_create_file("unpoison-pfn", 0600, 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_SWAP
  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");

Cache object: 29f171fd0678938b51f1b75069d16e39


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.