Commit a7420aa54dbf699a5a05feba3c859b6baaa3938c

Authored by Andi Kleen
Committed by Andi Kleen
1 parent 10be22dfe1

HWPOISON: Add support for poison swap entries v2

Memory migration uses special swap entry types to trigger special actions on
page faults. Extend this mechanism to also support poisoned swap entries, to
trigger poison handling on page faults. This allows follow-on patches to
prevent processes from faulting in poisoned pages again.

v2: Fix overflow in MAX_SWAPFILES (Fengguang Wu)
v3: Better overflow fix (Hidehiro Kawai)

Signed-off-by: Andi Kleen <ak@linux.intel.com>

Showing 3 changed files with 68 additions and 8 deletions Side-by-side Diff

include/linux/swap.h
... ... @@ -34,14 +34,36 @@
34 34 * the type/offset into the pte as 5/27 as well.
35 35 */
36 36 #define MAX_SWAPFILES_SHIFT 5
37   -#ifndef CONFIG_MIGRATION
38   -#define MAX_SWAPFILES (1 << MAX_SWAPFILES_SHIFT)
  37 +
  38 +/*
  39 + * Use some of the swap files numbers for other purposes. This
  40 + * is a convenient way to hook into the VM to trigger special
  41 + * actions on faults.
  42 + */
  43 +
  44 +/*
  45 + * NUMA node memory migration support
  46 + */
  47 +#ifdef CONFIG_MIGRATION
  48 +#define SWP_MIGRATION_NUM 2
  49 +#define SWP_MIGRATION_READ (MAX_SWAPFILES + SWP_HWPOISON_NUM)
  50 +#define SWP_MIGRATION_WRITE (MAX_SWAPFILES + SWP_HWPOISON_NUM + 1)
39 51 #else
40   -/* Use last two entries for page migration swap entries */
41   -#define MAX_SWAPFILES ((1 << MAX_SWAPFILES_SHIFT)-2)
42   -#define SWP_MIGRATION_READ MAX_SWAPFILES
43   -#define SWP_MIGRATION_WRITE (MAX_SWAPFILES + 1)
  52 +#define SWP_MIGRATION_NUM 0
44 53 #endif
  54 +
  55 +/*
  56 + * Handling of hardware poisoned pages with memory corruption.
  57 + */
  58 +#ifdef CONFIG_MEMORY_FAILURE
  59 +#define SWP_HWPOISON_NUM 1
  60 +#define SWP_HWPOISON MAX_SWAPFILES
  61 +#else
  62 +#define SWP_HWPOISON_NUM 0
  63 +#endif
  64 +
  65 +#define MAX_SWAPFILES \
  66 + ((1 << MAX_SWAPFILES_SHIFT) - SWP_MIGRATION_NUM - SWP_HWPOISON_NUM)
45 67  
46 68 /*
47 69 * Magic header for a swap area. The first part of the union is
include/linux/swapops.h
... ... @@ -130,4 +130,43 @@
130 130 }
131 131  
132 132 #endif
  133 +
  134 +#ifdef CONFIG_MEMORY_FAILURE
  135 +/*
  136 + * Support for hardware poisoned pages
  137 + */
  138 +static inline swp_entry_t make_hwpoison_entry(struct page *page)
  139 +{
  140 + BUG_ON(!PageLocked(page));
  141 + return swp_entry(SWP_HWPOISON, page_to_pfn(page));
  142 +}
  143 +
  144 +static inline int is_hwpoison_entry(swp_entry_t entry)
  145 +{
  146 + return swp_type(entry) == SWP_HWPOISON;
  147 +}
  148 +#else
  149 +
  150 +static inline swp_entry_t make_hwpoison_entry(struct page *page)
  151 +{
  152 + return swp_entry(0, 0);
  153 +}
  154 +
  155 +static inline int is_hwpoison_entry(swp_entry_t swp)
  156 +{
  157 + return 0;
  158 +}
  159 +#endif
  160 +
  161 +#if defined(CONFIG_MEMORY_FAILURE) || defined(CONFIG_MIGRATION)
  162 +static inline int non_swap_entry(swp_entry_t entry)
  163 +{
  164 + return swp_type(entry) >= MAX_SWAPFILES;
  165 +}
  166 +#else
  167 +static inline int non_swap_entry(swp_entry_t entry)
  168 +{
  169 + return 0;
  170 +}
  171 +#endif
... ... @@ -699,7 +699,7 @@
699 699 struct swap_info_struct *p;
700 700 struct page *page = NULL;
701 701  
702   - if (is_migration_entry(entry))
  702 + if (non_swap_entry(entry))
703 703 return 1;
704 704  
705 705 p = swap_info_get(entry);
... ... @@ -2085,7 +2085,7 @@
2085 2085 int count;
2086 2086 bool has_cache;
2087 2087  
2088   - if (is_migration_entry(entry))
  2088 + if (non_swap_entry(entry))
2089 2089 return -EINVAL;
2090 2090  
2091 2091 type = swp_type(entry);