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 ebcd3decac89..7e91b5f9f690 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -1326,7 +1326,8 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1326 | if (ret & VM_FAULT_ERROR) { | 1326 | if (ret & VM_FAULT_ERROR) { |
1327 | if (ret & VM_FAULT_OOM) | 1327 | if (ret & VM_FAULT_OOM) |
1328 | return i ? i : -ENOMEM; | 1328 | return i ? i : -ENOMEM; |
1329 | else if (ret & VM_FAULT_SIGBUS) | 1329 | if (ret & |
1330 | (VM_FAULT_HWPOISON|VM_FAULT_SIGBUS)) | ||
1330 | return i ? i : -EFAULT; | 1331 | return i ? i : -EFAULT; |
1331 | BUG(); | 1332 | BUG(); |
1332 | } | 1333 | } |
@@ -2503,8 +2504,15 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2503 | goto out; | 2504 | goto out; |
2504 | 2505 | ||
2505 | entry = pte_to_swp_entry(orig_pte); | 2506 | entry = pte_to_swp_entry(orig_pte); |
2506 | if (is_migration_entry(entry)) { | 2507 | if (unlikely(non_swap_entry(entry))) { |
2507 | migration_entry_wait(mm, pmd, address); | 2508 | if (is_migration_entry(entry)) { |
2509 | migration_entry_wait(mm, pmd, address); | ||
2510 | } else if (is_hwpoison_entry(entry)) { | ||
2511 | ret = VM_FAULT_HWPOISON; | ||
2512 | } else { | ||
2513 | print_bad_pte(vma, address, orig_pte, NULL); | ||
2514 | ret = VM_FAULT_OOM; | ||
2515 | } | ||
2508 | goto out; | 2516 | goto out; |
2509 | } | 2517 | } |
2510 | delayacct_set_flag(DELAYACCT_PF_SWAPIN); | 2518 | delayacct_set_flag(DELAYACCT_PF_SWAPIN); |
@@ -2528,6 +2536,10 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2528 | /* Had to read the page from swap area: Major fault */ | 2536 | /* Had to read the page from swap area: Major fault */ |
2529 | ret = VM_FAULT_MAJOR; | 2537 | ret = VM_FAULT_MAJOR; |
2530 | count_vm_event(PGMAJFAULT); | 2538 | count_vm_event(PGMAJFAULT); |
2539 | } else if (PageHWPoison(page)) { | ||
2540 | ret = VM_FAULT_HWPOISON; | ||
2541 | delayacct_clear_flag(DELAYACCT_PF_SWAPIN); | ||
2542 | goto out; | ||
2531 | } | 2543 | } |
2532 | 2544 | ||
2533 | lock_page(page); | 2545 | lock_page(page); |
@@ -2704,6 +2716,12 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2704 | if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE))) | 2716 | if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE))) |
2705 | return ret; | 2717 | return ret; |
2706 | 2718 | ||
2719 | if (unlikely(PageHWPoison(vmf.page))) { | ||
2720 | if (ret & VM_FAULT_LOCKED) | ||
2721 | unlock_page(vmf.page); | ||
2722 | return VM_FAULT_HWPOISON; | ||
2723 | } | ||
2724 | |||
2707 | /* | 2725 | /* |
2708 | * For consistency in subsequent calls, make the faulted page always | 2726 | * For consistency in subsequent calls, make the faulted page always |
2709 | * locked. | 2727 | * locked. |