diff options
Diffstat (limited to 'arch/um/kernel/trap.c')
-rw-r--r-- | arch/um/kernel/trap.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index dafc94715950..3be60765c0e2 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c | |||
@@ -30,6 +30,8 @@ int handle_page_fault(unsigned long address, unsigned long ip, | |||
30 | pmd_t *pmd; | 30 | pmd_t *pmd; |
31 | pte_t *pte; | 31 | pte_t *pte; |
32 | int err = -EFAULT; | 32 | int err = -EFAULT; |
33 | unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | | ||
34 | (is_write ? FAULT_FLAG_WRITE : 0); | ||
33 | 35 | ||
34 | *code_out = SEGV_MAPERR; | 36 | *code_out = SEGV_MAPERR; |
35 | 37 | ||
@@ -40,6 +42,7 @@ int handle_page_fault(unsigned long address, unsigned long ip, | |||
40 | if (in_atomic()) | 42 | if (in_atomic()) |
41 | goto out_nosemaphore; | 43 | goto out_nosemaphore; |
42 | 44 | ||
45 | retry: | ||
43 | down_read(&mm->mmap_sem); | 46 | down_read(&mm->mmap_sem); |
44 | vma = find_vma(mm, address); | 47 | vma = find_vma(mm, address); |
45 | if (!vma) | 48 | if (!vma) |
@@ -65,7 +68,11 @@ good_area: | |||
65 | do { | 68 | do { |
66 | int fault; | 69 | int fault; |
67 | 70 | ||
68 | fault = handle_mm_fault(mm, vma, address, is_write ? FAULT_FLAG_WRITE : 0); | 71 | fault = handle_mm_fault(mm, vma, address, flags); |
72 | |||
73 | if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) | ||
74 | goto out_nosemaphore; | ||
75 | |||
69 | if (unlikely(fault & VM_FAULT_ERROR)) { | 76 | if (unlikely(fault & VM_FAULT_ERROR)) { |
70 | if (fault & VM_FAULT_OOM) { | 77 | if (fault & VM_FAULT_OOM) { |
71 | goto out_of_memory; | 78 | goto out_of_memory; |
@@ -75,10 +82,17 @@ good_area: | |||
75 | } | 82 | } |
76 | BUG(); | 83 | BUG(); |
77 | } | 84 | } |
78 | if (fault & VM_FAULT_MAJOR) | 85 | if (flags & FAULT_FLAG_ALLOW_RETRY) { |
79 | current->maj_flt++; | 86 | if (fault & VM_FAULT_MAJOR) |
80 | else | 87 | current->maj_flt++; |
81 | current->min_flt++; | 88 | else |
89 | current->min_flt++; | ||
90 | if (fault & VM_FAULT_RETRY) { | ||
91 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | ||
92 | |||
93 | goto retry; | ||
94 | } | ||
95 | } | ||
82 | 96 | ||
83 | pgd = pgd_offset(mm, address); | 97 | pgd = pgd_offset(mm, address); |
84 | pud = pud_offset(pgd, address); | 98 | pud = pud_offset(pgd, address); |