diff options
Diffstat (limited to 'arch/x86/mm')
-rw-r--r-- | arch/x86/mm/fault.c | 35 |
1 files changed, 17 insertions, 18 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 6d77c3866faa..3aaeffcfd67a 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
@@ -842,23 +842,15 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address, | |||
842 | force_sig_info_fault(SIGBUS, code, address, tsk, fault); | 842 | force_sig_info_fault(SIGBUS, code, address, tsk, fault); |
843 | } | 843 | } |
844 | 844 | ||
845 | static noinline int | 845 | static noinline void |
846 | mm_fault_error(struct pt_regs *regs, unsigned long error_code, | 846 | mm_fault_error(struct pt_regs *regs, unsigned long error_code, |
847 | unsigned long address, unsigned int fault) | 847 | unsigned long address, unsigned int fault) |
848 | { | 848 | { |
849 | /* | 849 | if (fatal_signal_pending(current) && !(error_code & PF_USER)) { |
850 | * Pagefault was interrupted by SIGKILL. We have no reason to | 850 | up_read(¤t->mm->mmap_sem); |
851 | * continue pagefault. | 851 | no_context(regs, error_code, address, 0, 0); |
852 | */ | 852 | return; |
853 | if (fatal_signal_pending(current)) { | ||
854 | if (!(fault & VM_FAULT_RETRY)) | ||
855 | up_read(¤t->mm->mmap_sem); | ||
856 | if (!(error_code & PF_USER)) | ||
857 | no_context(regs, error_code, address, 0, 0); | ||
858 | return 1; | ||
859 | } | 853 | } |
860 | if (!(fault & VM_FAULT_ERROR)) | ||
861 | return 0; | ||
862 | 854 | ||
863 | if (fault & VM_FAULT_OOM) { | 855 | if (fault & VM_FAULT_OOM) { |
864 | /* Kernel mode? Handle exceptions or die: */ | 856 | /* Kernel mode? Handle exceptions or die: */ |
@@ -866,7 +858,7 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code, | |||
866 | up_read(¤t->mm->mmap_sem); | 858 | up_read(¤t->mm->mmap_sem); |
867 | no_context(regs, error_code, address, | 859 | no_context(regs, error_code, address, |
868 | SIGSEGV, SEGV_MAPERR); | 860 | SIGSEGV, SEGV_MAPERR); |
869 | return 1; | 861 | return; |
870 | } | 862 | } |
871 | 863 | ||
872 | up_read(¤t->mm->mmap_sem); | 864 | up_read(¤t->mm->mmap_sem); |
@@ -884,7 +876,6 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code, | |||
884 | else | 876 | else |
885 | BUG(); | 877 | BUG(); |
886 | } | 878 | } |
887 | return 1; | ||
888 | } | 879 | } |
889 | 880 | ||
890 | static int spurious_fault_check(unsigned long error_code, pte_t *pte) | 881 | static int spurious_fault_check(unsigned long error_code, pte_t *pte) |
@@ -1189,9 +1180,17 @@ good_area: | |||
1189 | */ | 1180 | */ |
1190 | fault = handle_mm_fault(mm, vma, address, flags); | 1181 | fault = handle_mm_fault(mm, vma, address, flags); |
1191 | 1182 | ||
1192 | if (unlikely(fault & (VM_FAULT_RETRY|VM_FAULT_ERROR))) { | 1183 | /* |
1193 | if (mm_fault_error(regs, error_code, address, fault)) | 1184 | * If we need to retry but a fatal signal is pending, handle the |
1194 | return; | 1185 | * signal first. We do not need to release the mmap_sem because it |
1186 | * would already be released in __lock_page_or_retry in mm/filemap.c. | ||
1187 | */ | ||
1188 | if (unlikely((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))) | ||
1189 | return; | ||
1190 | |||
1191 | if (unlikely(fault & VM_FAULT_ERROR)) { | ||
1192 | mm_fault_error(regs, error_code, address, fault); | ||
1193 | return; | ||
1195 | } | 1194 | } |
1196 | 1195 | ||
1197 | /* | 1196 | /* |