diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-24 10:53:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-24 10:53:22 -0400 |
commit | db16826367fefcb0ddb93d76b66adc52eb4e6339 (patch) | |
tree | 626224c1eb1eb79c522714591f208b4fdbdcd9d4 /include/linux | |
parent | cd6045138ed1bb5d8773e940d51c34318eef3ef2 (diff) | |
parent | 465fdd97cbe16ef8727221857e96ef62dd352017 (diff) |
Merge branch 'hwpoison' of git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-mce-2.6
* 'hwpoison' of git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-mce-2.6: (21 commits)
HWPOISON: Enable error_remove_page on btrfs
HWPOISON: Add simple debugfs interface to inject hwpoison on arbitary PFNs
HWPOISON: Add madvise() based injector for hardware poisoned pages v4
HWPOISON: Enable error_remove_page for NFS
HWPOISON: Enable .remove_error_page for migration aware file systems
HWPOISON: The high level memory error handler in the VM v7
HWPOISON: Add PR_MCE_KILL prctl to control early kill behaviour per process
HWPOISON: shmem: call set_page_dirty() with locked page
HWPOISON: Define a new error_remove_page address space op for async truncation
HWPOISON: Add invalidate_inode_page
HWPOISON: Refactor truncate to allow direct truncating of page v2
HWPOISON: check and isolate corrupted free pages v2
HWPOISON: Handle hardware poisoned pages in try_to_unmap
HWPOISON: Use bitmask/action code for try_to_unmap behaviour
HWPOISON: x86: Add VM_FAULT_HWPOISON handling to x86 page fault handler v2
HWPOISON: Add poison check to page fault handling
HWPOISON: Add basic support for poisoned pages in fault handler v3
HWPOISON: Add new SIGBUS error codes for hardware poison signals
HWPOISON: Add support for poison swap entries v2
HWPOISON: Export some rmap vma locking to outside world
...
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/fs.h | 1 | ||||
-rw-r--r-- | include/linux/mm.h | 15 | ||||
-rw-r--r-- | include/linux/page-flags.h | 17 | ||||
-rw-r--r-- | include/linux/prctl.h | 2 | ||||
-rw-r--r-- | include/linux/rmap.h | 21 | ||||
-rw-r--r-- | include/linux/sched.h | 2 | ||||
-rw-r--r-- | include/linux/swap.h | 34 | ||||
-rw-r--r-- | include/linux/swapops.h | 38 |
8 files changed, 121 insertions, 9 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h index 33ed6644abd0..78e95b8b66d4 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -595,6 +595,7 @@ struct address_space_operations { | |||
595 | int (*launder_page) (struct page *); | 595 | int (*launder_page) (struct page *); |
596 | int (*is_partially_uptodate) (struct page *, read_descriptor_t *, | 596 | int (*is_partially_uptodate) (struct page *, read_descriptor_t *, |
597 | unsigned long); | 597 | unsigned long); |
598 | int (*error_remove_page)(struct address_space *, struct page *); | ||
598 | }; | 599 | }; |
599 | 600 | ||
600 | /* | 601 | /* |
diff --git a/include/linux/mm.h b/include/linux/mm.h index 87218ae84e36..6953a5a53e44 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -695,11 +695,12 @@ static inline int page_mapped(struct page *page) | |||
695 | #define VM_FAULT_SIGBUS 0x0002 | 695 | #define VM_FAULT_SIGBUS 0x0002 |
696 | #define VM_FAULT_MAJOR 0x0004 | 696 | #define VM_FAULT_MAJOR 0x0004 |
697 | #define VM_FAULT_WRITE 0x0008 /* Special case for get_user_pages */ | 697 | #define VM_FAULT_WRITE 0x0008 /* Special case for get_user_pages */ |
698 | #define VM_FAULT_HWPOISON 0x0010 /* Hit poisoned page */ | ||
698 | 699 | ||
699 | #define VM_FAULT_NOPAGE 0x0100 /* ->fault installed the pte, not return page */ | 700 | #define VM_FAULT_NOPAGE 0x0100 /* ->fault installed the pte, not return page */ |
700 | #define VM_FAULT_LOCKED 0x0200 /* ->fault locked the returned page */ | 701 | #define VM_FAULT_LOCKED 0x0200 /* ->fault locked the returned page */ |
701 | 702 | ||
702 | #define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS) | 703 | #define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_HWPOISON) |
703 | 704 | ||
704 | /* | 705 | /* |
705 | * Can be called by the pagefault handler when it gets a VM_FAULT_OOM. | 706 | * Can be called by the pagefault handler when it gets a VM_FAULT_OOM. |
@@ -794,6 +795,11 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping, | |||
794 | extern int vmtruncate(struct inode * inode, loff_t offset); | 795 | extern int vmtruncate(struct inode * inode, loff_t offset); |
795 | extern int vmtruncate_range(struct inode * inode, loff_t offset, loff_t end); | 796 | extern int vmtruncate_range(struct inode * inode, loff_t offset, loff_t end); |
796 | 797 | ||
798 | int truncate_inode_page(struct address_space *mapping, struct page *page); | ||
799 | int generic_error_remove_page(struct address_space *mapping, struct page *page); | ||
800 | |||
801 | int invalidate_inode_page(struct page *page); | ||
802 | |||
797 | #ifdef CONFIG_MMU | 803 | #ifdef CONFIG_MMU |
798 | extern int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, | 804 | extern int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, |
799 | unsigned long address, unsigned int flags); | 805 | unsigned long address, unsigned int flags); |
@@ -1308,5 +1314,12 @@ void vmemmap_populate_print_last(void); | |||
1308 | extern int account_locked_memory(struct mm_struct *mm, struct rlimit *rlim, | 1314 | extern int account_locked_memory(struct mm_struct *mm, struct rlimit *rlim, |
1309 | size_t size); | 1315 | size_t size); |
1310 | extern void refund_locked_memory(struct mm_struct *mm, size_t size); | 1316 | extern void refund_locked_memory(struct mm_struct *mm, size_t size); |
1317 | |||
1318 | extern void memory_failure(unsigned long pfn, int trapno); | ||
1319 | extern int __memory_failure(unsigned long pfn, int trapno, int ref); | ||
1320 | extern int sysctl_memory_failure_early_kill; | ||
1321 | extern int sysctl_memory_failure_recovery; | ||
1322 | extern atomic_long_t mce_bad_pages; | ||
1323 | |||
1311 | #endif /* __KERNEL__ */ | 1324 | #endif /* __KERNEL__ */ |
1312 | #endif /* _LINUX_MM_H */ | 1325 | #endif /* _LINUX_MM_H */ |
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 13de789f0a5c..6b202b173955 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h | |||
@@ -51,6 +51,9 @@ | |||
51 | * PG_buddy is set to indicate that the page is free and in the buddy system | 51 | * PG_buddy is set to indicate that the page is free and in the buddy system |
52 | * (see mm/page_alloc.c). | 52 | * (see mm/page_alloc.c). |
53 | * | 53 | * |
54 | * PG_hwpoison indicates that a page got corrupted in hardware and contains | ||
55 | * data with incorrect ECC bits that triggered a machine check. Accessing is | ||
56 | * not safe since it may cause another machine check. Don't touch! | ||
54 | */ | 57 | */ |
55 | 58 | ||
56 | /* | 59 | /* |
@@ -102,6 +105,9 @@ enum pageflags { | |||
102 | #ifdef CONFIG_ARCH_USES_PG_UNCACHED | 105 | #ifdef CONFIG_ARCH_USES_PG_UNCACHED |
103 | PG_uncached, /* Page has been mapped as uncached */ | 106 | PG_uncached, /* Page has been mapped as uncached */ |
104 | #endif | 107 | #endif |
108 | #ifdef CONFIG_MEMORY_FAILURE | ||
109 | PG_hwpoison, /* hardware poisoned page. Don't touch */ | ||
110 | #endif | ||
105 | __NR_PAGEFLAGS, | 111 | __NR_PAGEFLAGS, |
106 | 112 | ||
107 | /* Filesystems */ | 113 | /* Filesystems */ |
@@ -269,6 +275,15 @@ PAGEFLAG(Uncached, uncached) | |||
269 | PAGEFLAG_FALSE(Uncached) | 275 | PAGEFLAG_FALSE(Uncached) |
270 | #endif | 276 | #endif |
271 | 277 | ||
278 | #ifdef CONFIG_MEMORY_FAILURE | ||
279 | PAGEFLAG(HWPoison, hwpoison) | ||
280 | TESTSETFLAG(HWPoison, hwpoison) | ||
281 | #define __PG_HWPOISON (1UL << PG_hwpoison) | ||
282 | #else | ||
283 | PAGEFLAG_FALSE(HWPoison) | ||
284 | #define __PG_HWPOISON 0 | ||
285 | #endif | ||
286 | |||
272 | static inline int PageUptodate(struct page *page) | 287 | static inline int PageUptodate(struct page *page) |
273 | { | 288 | { |
274 | int ret = test_bit(PG_uptodate, &(page)->flags); | 289 | int ret = test_bit(PG_uptodate, &(page)->flags); |
@@ -393,7 +408,7 @@ static inline void __ClearPageTail(struct page *page) | |||
393 | 1 << PG_private | 1 << PG_private_2 | \ | 408 | 1 << PG_private | 1 << PG_private_2 | \ |
394 | 1 << PG_buddy | 1 << PG_writeback | 1 << PG_reserved | \ | 409 | 1 << PG_buddy | 1 << PG_writeback | 1 << PG_reserved | \ |
395 | 1 << PG_slab | 1 << PG_swapcache | 1 << PG_active | \ | 410 | 1 << PG_slab | 1 << PG_swapcache | 1 << PG_active | \ |
396 | 1 << PG_unevictable | __PG_MLOCKED) | 411 | 1 << PG_unevictable | __PG_MLOCKED | __PG_HWPOISON) |
397 | 412 | ||
398 | /* | 413 | /* |
399 | * Flags checked when a page is prepped for return by the page allocator. | 414 | * Flags checked when a page is prepped for return by the page allocator. |
diff --git a/include/linux/prctl.h b/include/linux/prctl.h index 07bff666e65b..931150566ade 100644 --- a/include/linux/prctl.h +++ b/include/linux/prctl.h | |||
@@ -88,4 +88,6 @@ | |||
88 | #define PR_TASK_PERF_EVENTS_DISABLE 31 | 88 | #define PR_TASK_PERF_EVENTS_DISABLE 31 |
89 | #define PR_TASK_PERF_EVENTS_ENABLE 32 | 89 | #define PR_TASK_PERF_EVENTS_ENABLE 32 |
90 | 90 | ||
91 | #define PR_MCE_KILL 33 | ||
92 | |||
91 | #endif /* _LINUX_PRCTL_H */ | 93 | #endif /* _LINUX_PRCTL_H */ |
diff --git a/include/linux/rmap.h b/include/linux/rmap.h index 477841d29fce..cb0ba7032609 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h | |||
@@ -81,7 +81,19 @@ static inline void page_dup_rmap(struct page *page) | |||
81 | */ | 81 | */ |
82 | int page_referenced(struct page *, int is_locked, | 82 | int page_referenced(struct page *, int is_locked, |
83 | struct mem_cgroup *cnt, unsigned long *vm_flags); | 83 | struct mem_cgroup *cnt, unsigned long *vm_flags); |
84 | int try_to_unmap(struct page *, int ignore_refs); | 84 | enum ttu_flags { |
85 | TTU_UNMAP = 0, /* unmap mode */ | ||
86 | TTU_MIGRATION = 1, /* migration mode */ | ||
87 | TTU_MUNLOCK = 2, /* munlock mode */ | ||
88 | TTU_ACTION_MASK = 0xff, | ||
89 | |||
90 | TTU_IGNORE_MLOCK = (1 << 8), /* ignore mlock */ | ||
91 | TTU_IGNORE_ACCESS = (1 << 9), /* don't age */ | ||
92 | TTU_IGNORE_HWPOISON = (1 << 10),/* corrupted page is recoverable */ | ||
93 | }; | ||
94 | #define TTU_ACTION(x) ((x) & TTU_ACTION_MASK) | ||
95 | |||
96 | int try_to_unmap(struct page *, enum ttu_flags flags); | ||
85 | 97 | ||
86 | /* | 98 | /* |
87 | * Called from mm/filemap_xip.c to unmap empty zero page | 99 | * Called from mm/filemap_xip.c to unmap empty zero page |
@@ -108,6 +120,13 @@ int page_mkclean(struct page *); | |||
108 | */ | 120 | */ |
109 | int try_to_munlock(struct page *); | 121 | int try_to_munlock(struct page *); |
110 | 122 | ||
123 | /* | ||
124 | * Called by memory-failure.c to kill processes. | ||
125 | */ | ||
126 | struct anon_vma *page_lock_anon_vma(struct page *page); | ||
127 | void page_unlock_anon_vma(struct anon_vma *anon_vma); | ||
128 | int page_mapped_in_vma(struct page *page, struct vm_area_struct *vma); | ||
129 | |||
111 | #else /* !CONFIG_MMU */ | 130 | #else /* !CONFIG_MMU */ |
112 | 131 | ||
113 | #define anon_vma_init() do {} while (0) | 132 | #define anon_vma_init() do {} while (0) |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 8a16f6d11dcd..75e6e60bf583 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1734,6 +1734,7 @@ extern cputime_t task_gtime(struct task_struct *p); | |||
1734 | #define PF_EXITPIDONE 0x00000008 /* pi exit done on shut down */ | 1734 | #define PF_EXITPIDONE 0x00000008 /* pi exit done on shut down */ |
1735 | #define PF_VCPU 0x00000010 /* I'm a virtual CPU */ | 1735 | #define PF_VCPU 0x00000010 /* I'm a virtual CPU */ |
1736 | #define PF_FORKNOEXEC 0x00000040 /* forked but didn't exec */ | 1736 | #define PF_FORKNOEXEC 0x00000040 /* forked but didn't exec */ |
1737 | #define PF_MCE_PROCESS 0x00000080 /* process policy on mce errors */ | ||
1737 | #define PF_SUPERPRIV 0x00000100 /* used super-user privileges */ | 1738 | #define PF_SUPERPRIV 0x00000100 /* used super-user privileges */ |
1738 | #define PF_DUMPCORE 0x00000200 /* dumped core */ | 1739 | #define PF_DUMPCORE 0x00000200 /* dumped core */ |
1739 | #define PF_SIGNALED 0x00000400 /* killed by a signal */ | 1740 | #define PF_SIGNALED 0x00000400 /* killed by a signal */ |
@@ -1753,6 +1754,7 @@ extern cputime_t task_gtime(struct task_struct *p); | |||
1753 | #define PF_SPREAD_PAGE 0x01000000 /* Spread page cache over cpuset */ | 1754 | #define PF_SPREAD_PAGE 0x01000000 /* Spread page cache over cpuset */ |
1754 | #define PF_SPREAD_SLAB 0x02000000 /* Spread some slab caches over cpuset */ | 1755 | #define PF_SPREAD_SLAB 0x02000000 /* Spread some slab caches over cpuset */ |
1755 | #define PF_THREAD_BOUND 0x04000000 /* Thread bound to specific cpu */ | 1756 | #define PF_THREAD_BOUND 0x04000000 /* Thread bound to specific cpu */ |
1757 | #define PF_MCE_EARLY 0x08000000 /* Early kill for mce process policy */ | ||
1756 | #define PF_MEMPOLICY 0x10000000 /* Non-default NUMA mempolicy */ | 1758 | #define PF_MEMPOLICY 0x10000000 /* Non-default NUMA mempolicy */ |
1757 | #define PF_MUTEX_TESTER 0x20000000 /* Thread belongs to the rt mutex tester */ | 1759 | #define PF_MUTEX_TESTER 0x20000000 /* Thread belongs to the rt mutex tester */ |
1758 | #define PF_FREEZER_SKIP 0x40000000 /* Freezer should not count it as freezeable */ | 1760 | #define PF_FREEZER_SKIP 0x40000000 /* Freezer should not count it as freezeable */ |
diff --git a/include/linux/swap.h b/include/linux/swap.h index 82232dbea3f7..4ec90019c1a4 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h | |||
@@ -34,16 +34,38 @@ static inline int current_is_kswapd(void) | |||
34 | * the type/offset into the pte as 5/27 as well. | 34 | * the type/offset into the pte as 5/27 as well. |
35 | */ | 35 | */ |
36 | #define MAX_SWAPFILES_SHIFT 5 | 36 | #define MAX_SWAPFILES_SHIFT 5 |
37 | #ifndef CONFIG_MIGRATION | 37 | |
38 | #define MAX_SWAPFILES (1 << MAX_SWAPFILES_SHIFT) | 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 | #else | 51 | #else |
40 | /* Use last two entries for page migration swap entries */ | 52 | #define SWP_MIGRATION_NUM 0 |
41 | #define MAX_SWAPFILES ((1 << MAX_SWAPFILES_SHIFT)-2) | ||
42 | #define SWP_MIGRATION_READ MAX_SWAPFILES | ||
43 | #define SWP_MIGRATION_WRITE (MAX_SWAPFILES + 1) | ||
44 | #endif | 53 | #endif |
45 | 54 | ||
46 | /* | 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) | ||
67 | |||
68 | /* | ||
47 | * Magic header for a swap area. The first part of the union is | 69 | * Magic header for a swap area. The first part of the union is |
48 | * what the swap magic looks like for the old (limited to 128MB) | 70 | * what the swap magic looks like for the old (limited to 128MB) |
49 | * swap area format, the second part of the union adds - in the | 71 | * swap area format, the second part of the union adds - in the |
diff --git a/include/linux/swapops.h b/include/linux/swapops.h index 6ec39ab27b4b..cd42e30b7c6e 100644 --- a/include/linux/swapops.h +++ b/include/linux/swapops.h | |||
@@ -131,3 +131,41 @@ static inline int is_write_migration_entry(swp_entry_t entry) | |||
131 | 131 | ||
132 | #endif | 132 | #endif |
133 | 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 | ||