diff options
author | Andi Kleen <andi@firstfloor.org> | 2009-09-16 11:50:06 +0200 |
---|---|---|
committer | Andi Kleen <ak@linux.intel.com> | 2009-09-16 11:50:06 +0200 |
commit | d1737fdbec7f90edc52dd0c5c3767457f28e78d8 (patch) | |
tree | 8699aabdff713a70665a9f60106ce21012376733 /mm/memory.c | |
parent | ad5fa913991e9e0f122b021e882b0d50051fbdbc (diff) | |
download | linux-d1737fdbec7f90edc52dd0c5c3767457f28e78d8.tar.gz linux-d1737fdbec7f90edc52dd0c5c3767457f28e78d8.tar.bz2 linux-d1737fdbec7f90edc52dd0c5c3767457f28e78d8.zip |
HWPOISON: Add basic support for poisoned pages in fault handler v3
- Add a new VM_FAULT_HWPOISON error code to handle_mm_fault. Right now
architectures have to explicitely enable poison page support, so
this is forward compatible to all architectures. They only need
to add it when they enable poison page support.
- Add poison page handling in swap in fault code
v2: Add missing delayacct_clear_flag (Hidehiro Kawai)
v3: Really use delayacct_clear_flag (Hidehiro Kawai)
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Diffstat (limited to 'mm/memory.c')
-rw-r--r-- | mm/memory.c | 18 |
1 files changed, 15 insertions, 3 deletions
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, if (ret & VM_FAULT_ERROR) { if (ret & VM_FAULT_OOM) return i ? i : -ENOMEM; - else if (ret & VM_FAULT_SIGBUS) + if (ret & + (VM_FAULT_HWPOISON|VM_FAULT_SIGBUS)) return i ? i : -EFAULT; BUG(); } @@ -2511,8 +2512,15 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, goto out; entry = pte_to_swp_entry(orig_pte); - if (is_migration_entry(entry)) { - migration_entry_wait(mm, pmd, address); + if (unlikely(non_swap_entry(entry))) { + if (is_migration_entry(entry)) { + migration_entry_wait(mm, pmd, address); + } else if (is_hwpoison_entry(entry)) { + ret = VM_FAULT_HWPOISON; + } else { + print_bad_pte(vma, address, orig_pte, NULL); + ret = VM_FAULT_OOM; + } goto out; } delayacct_set_flag(DELAYACCT_PF_SWAPIN); @@ -2536,6 +2544,10 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, /* Had to read the page from swap area: Major fault */ ret = VM_FAULT_MAJOR; count_vm_event(PGMAJFAULT); + } else if (PageHWPoison(page)) { + ret = VM_FAULT_HWPOISON; + delayacct_clear_flag(DELAYACCT_PF_SWAPIN); + goto out; } lock_page(page); |