diff options
-rw-r--r-- | include/linux/mm.h | 3 | ||||
-rw-r--r-- | mm/memory.c | 18 |
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); |