aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/mm.h3
-rw-r--r--mm/memory.c18
2 files changed, 17 insertions, 4 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 9a72cc78e6b8..082b68cb5ffe 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -685,11 +685,12 @@ static inline int page_mapped(struct page *page)
685#define VM_FAULT_SIGBUS 0x0002 685#define VM_FAULT_SIGBUS 0x0002
686#define VM_FAULT_MAJOR 0x0004 686#define VM_FAULT_MAJOR 0x0004
687#define VM_FAULT_WRITE 0x0008 /* Special case for get_user_pages */ 687#define VM_FAULT_WRITE 0x0008 /* Special case for get_user_pages */
688#define VM_FAULT_HWPOISON 0x0010 /* Hit poisoned page */
688 689
689#define VM_FAULT_NOPAGE 0x0100 /* ->fault installed the pte, not return page */ 690#define VM_FAULT_NOPAGE 0x0100 /* ->fault installed the pte, not return page */
690#define VM_FAULT_LOCKED 0x0200 /* ->fault locked the returned page */ 691#define VM_FAULT_LOCKED 0x0200 /* ->fault locked the returned page */
691 692
692#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS) 693#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_HWPOISON)
693 694
694/* 695/*
695 * Can be called by the pagefault handler when it gets a VM_FAULT_OOM. 696 * Can be called by the pagefault handler when it gets a VM_FAULT_OOM.
diff --git a/mm/memory.c b/mm/memory.c
index aede2ce3aba4..02bae2d540d4 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1319,7 +1319,8 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
1319 if (ret & VM_FAULT_ERROR) { 1319 if (ret & VM_FAULT_ERROR) {
1320 if (ret & VM_FAULT_OOM) 1320 if (ret & VM_FAULT_OOM)
1321 return i ? i : -ENOMEM; 1321 return i ? i : -ENOMEM;
1322 else if (ret & VM_FAULT_SIGBUS) 1322 if (ret &
1323 (VM_FAULT_HWPOISON|VM_FAULT_SIGBUS))
1323 return i ? i : -EFAULT; 1324 return i ? i : -EFAULT;
1324 BUG(); 1325 BUG();
1325 } 1326 }
@@ -2511,8 +2512,15 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
2511 goto out; 2512 goto out;
2512 2513
2513 entry = pte_to_swp_entry(orig_pte); 2514 entry = pte_to_swp_entry(orig_pte);
2514 if (is_migration_entry(entry)) { 2515 if (unlikely(non_swap_entry(entry))) {
2515 migration_entry_wait(mm, pmd, address); 2516 if (is_migration_entry(entry)) {
2517 migration_entry_wait(mm, pmd, address);
2518 } else if (is_hwpoison_entry(entry)) {
2519 ret = VM_FAULT_HWPOISON;
2520 } else {
2521 print_bad_pte(vma, address, orig_pte, NULL);
2522 ret = VM_FAULT_OOM;
2523 }
2516 goto out; 2524 goto out;
2517 } 2525 }
2518 delayacct_set_flag(DELAYACCT_PF_SWAPIN); 2526 delayacct_set_flag(DELAYACCT_PF_SWAPIN);
@@ -2536,6 +2544,10 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
2536 /* Had to read the page from swap area: Major fault */ 2544 /* Had to read the page from swap area: Major fault */
2537 ret = VM_FAULT_MAJOR; 2545 ret = VM_FAULT_MAJOR;
2538 count_vm_event(PGMAJFAULT); 2546 count_vm_event(PGMAJFAULT);
2547 } else if (PageHWPoison(page)) {
2548 ret = VM_FAULT_HWPOISON;
2549 delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
2550 goto out;
2539 } 2551 }
2540 2552
2541 lock_page(page); 2553 lock_page(page);