aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKautuk Consul <consul.kautuk@gmail.com>2012-03-25 06:37:48 -0400
committerGeert Uytterhoeven <geert@linux-m68k.org>2012-04-22 14:16:49 -0400
commitb637a6b16731d806ae2c8b9619a5619a2f283f15 (patch)
tree1f7f86a392b36b6dfb160449736a8a43647e84c4
parent107b5d5302b184b72a2f12d9d23f2fcd4ce8a6ec (diff)
m68k/mm: Port OOM changes to do_page_fault()
Commit d065bd810b6deb67d4897a14bfe21f8eb526ba99 (mm: retry page fault when blocking on disk transfer) and commit 37b23e0525d393d48a7d59f870b3bc061a30ccdb (x86,mm: make pagefault killable) The above commits introduced changes into the x86 pagefault handler for making the page fault handler retryable as well as killable. These changes reduce the mmap_sem hold time, which is crucial during OOM killer invocation. Port these changes to m68k. Signed-off-by: Kautuk Consul <consul.kautuk@gmail.com> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
-rw-r--r--arch/m68k/mm/fault.c42
1 files changed, 34 insertions, 8 deletions
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c
index 6b020a8461e7..aeebbb7b30f0 100644
--- a/arch/m68k/mm/fault.c
+++ b/arch/m68k/mm/fault.c
@@ -72,7 +72,8 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
72{ 72{
73 struct mm_struct *mm = current->mm; 73 struct mm_struct *mm = current->mm;
74 struct vm_area_struct * vma; 74 struct vm_area_struct * vma;
75 int write, fault; 75 int fault;
76 unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
76 77
77#ifdef DEBUG 78#ifdef DEBUG
78 printk ("do page fault:\nregs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n", 79 printk ("do page fault:\nregs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n",
@@ -87,6 +88,7 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
87 if (in_atomic() || !mm) 88 if (in_atomic() || !mm)
88 goto no_context; 89 goto no_context;
89 90
91retry:
90 down_read(&mm->mmap_sem); 92 down_read(&mm->mmap_sem);
91 93
92 vma = find_vma(mm, address); 94 vma = find_vma(mm, address);
@@ -117,14 +119,13 @@ good_area:
117#ifdef DEBUG 119#ifdef DEBUG
118 printk("do_page_fault: good_area\n"); 120 printk("do_page_fault: good_area\n");
119#endif 121#endif
120 write = 0;
121 switch (error_code & 3) { 122 switch (error_code & 3) {
122 default: /* 3: write, present */ 123 default: /* 3: write, present */
123 /* fall through */ 124 /* fall through */
124 case 2: /* write, not present */ 125 case 2: /* write, not present */
125 if (!(vma->vm_flags & VM_WRITE)) 126 if (!(vma->vm_flags & VM_WRITE))
126 goto acc_err; 127 goto acc_err;
127 write++; 128 flags |= FAULT_FLAG_WRITE;
128 break; 129 break;
129 case 1: /* read, present */ 130 case 1: /* read, present */
130 goto acc_err; 131 goto acc_err;
@@ -139,10 +140,14 @@ good_area:
139 * the fault. 140 * the fault.
140 */ 141 */
141 142
142 fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0); 143 fault = handle_mm_fault(mm, vma, address, flags);
143#ifdef DEBUG 144#ifdef DEBUG
144 printk("handle_mm_fault returns %d\n",fault); 145 printk("handle_mm_fault returns %d\n",fault);
145#endif 146#endif
147
148 if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
149 return 0;
150
146 if (unlikely(fault & VM_FAULT_ERROR)) { 151 if (unlikely(fault & VM_FAULT_ERROR)) {
147 if (fault & VM_FAULT_OOM) 152 if (fault & VM_FAULT_OOM)
148 goto out_of_memory; 153 goto out_of_memory;
@@ -150,10 +155,31 @@ good_area:
150 goto bus_err; 155 goto bus_err;
151 BUG(); 156 BUG();
152 } 157 }
153 if (fault & VM_FAULT_MAJOR) 158
154 current->maj_flt++; 159 /*
155 else 160 * Major/minor page fault accounting is only done on the
156 current->min_flt++; 161 * initial attempt. If we go through a retry, it is extremely
162 * likely that the page will be found in page cache at that point.
163 */
164 if (flags & FAULT_FLAG_ALLOW_RETRY) {
165 if (fault & VM_FAULT_MAJOR)
166 current->maj_flt++;
167 else
168 current->min_flt++;
169 if (fault & VM_FAULT_RETRY) {
170 /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
171 * of starvation. */
172 flags &= ~FAULT_FLAG_ALLOW_RETRY;
173
174 /*
175 * No need to up_read(&mm->mmap_sem) as we would
176 * have already released it in __lock_page_or_retry
177 * in mm/filemap.c.
178 */
179
180 goto retry;
181 }
182 }
157 183
158 up_read(&mm->mmap_sem); 184 up_read(&mm->mmap_sem);
159 return 0; 185 return 0;