diff options
Diffstat (limited to 'mm/memory.c')
-rw-r--r-- | mm/memory.c | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/mm/memory.c b/mm/memory.c index b1443ac07c00..987389a809e7 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -1325,7 +1325,8 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1325 | if (ret & VM_FAULT_ERROR) { | 1325 | if (ret & VM_FAULT_ERROR) { |
1326 | if (ret & VM_FAULT_OOM) | 1326 | if (ret & VM_FAULT_OOM) |
1327 | return i ? i : -ENOMEM; | 1327 | return i ? i : -ENOMEM; |
1328 | else if (ret & VM_FAULT_SIGBUS) | 1328 | if (ret & |
1329 | (VM_FAULT_HWPOISON|VM_FAULT_SIGBUS)) | ||
1329 | return i ? i : -EFAULT; | 1330 | return i ? i : -EFAULT; |
1330 | BUG(); | 1331 | BUG(); |
1331 | } | 1332 | } |
@@ -2559,8 +2560,15 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2559 | goto out; | 2560 | goto out; |
2560 | 2561 | ||
2561 | entry = pte_to_swp_entry(orig_pte); | 2562 | entry = pte_to_swp_entry(orig_pte); |
2562 | if (is_migration_entry(entry)) { | 2563 | if (unlikely(non_swap_entry(entry))) { |
2563 | migration_entry_wait(mm, pmd, address); | 2564 | if (is_migration_entry(entry)) { |
2565 | migration_entry_wait(mm, pmd, address); | ||
2566 | } else if (is_hwpoison_entry(entry)) { | ||
2567 | ret = VM_FAULT_HWPOISON; | ||
2568 | } else { | ||
2569 | print_bad_pte(vma, address, orig_pte, NULL); | ||
2570 | ret = VM_FAULT_OOM; | ||
2571 | } | ||
2564 | goto out; | 2572 | goto out; |
2565 | } | 2573 | } |
2566 | delayacct_set_flag(DELAYACCT_PF_SWAPIN); | 2574 | delayacct_set_flag(DELAYACCT_PF_SWAPIN); |
@@ -2584,6 +2592,10 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2584 | /* Had to read the page from swap area: Major fault */ | 2592 | /* Had to read the page from swap area: Major fault */ |
2585 | ret = VM_FAULT_MAJOR; | 2593 | ret = VM_FAULT_MAJOR; |
2586 | count_vm_event(PGMAJFAULT); | 2594 | count_vm_event(PGMAJFAULT); |
2595 | } else if (PageHWPoison(page)) { | ||
2596 | ret = VM_FAULT_HWPOISON; | ||
2597 | delayacct_clear_flag(DELAYACCT_PF_SWAPIN); | ||
2598 | goto out; | ||
2587 | } | 2599 | } |
2588 | 2600 | ||
2589 | lock_page(page); | 2601 | lock_page(page); |
@@ -2760,6 +2772,12 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2760 | if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE))) | 2772 | if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE))) |
2761 | return ret; | 2773 | return ret; |
2762 | 2774 | ||
2775 | if (unlikely(PageHWPoison(vmf.page))) { | ||
2776 | if (ret & VM_FAULT_LOCKED) | ||
2777 | unlock_page(vmf.page); | ||
2778 | return VM_FAULT_HWPOISON; | ||
2779 | } | ||
2780 | |||
2763 | /* | 2781 | /* |
2764 | * For consistency in subsequent calls, make the faulted page always | 2782 | * For consistency in subsequent calls, make the faulted page always |
2765 | * locked. | 2783 | * locked. |