aboutsummaryrefslogtreecommitdiffstats
path: root/mm/oom_kill.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/oom_kill.c')
-rw-r--r--mm/oom_kill.c53
1 files changed, 30 insertions, 23 deletions
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index bada3d03119f..20f41b082e16 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -204,16 +204,30 @@ static struct task_struct *select_bad_process(unsigned long *ppoints)
204 do_posix_clock_monotonic_gettime(&uptime); 204 do_posix_clock_monotonic_gettime(&uptime);
205 do_each_thread(g, p) { 205 do_each_thread(g, p) {
206 unsigned long points; 206 unsigned long points;
207 int releasing;
208 207
209 /* skip kernel threads */ 208 /*
209 * skip kernel threads and tasks which have already released
210 * their mm.
211 */
210 if (!p->mm) 212 if (!p->mm)
211 continue; 213 continue;
212 /* skip the init task with pid == 1 */ 214 /* skip the init task */
213 if (p->pid == 1) 215 if (is_init(p))
214 continue; 216 continue;
215 217
216 /* 218 /*
219 * This task already has access to memory reserves and is
220 * being killed. Don't allow any other task access to the
221 * memory reserve.
222 *
223 * Note: this may have a chance of deadlock if it gets
224 * blocked waiting for another task which itself is waiting
225 * for memory. Is there a better alternative?
226 */
227 if (test_tsk_thread_flag(p, TIF_MEMDIE))
228 return ERR_PTR(-1UL);
229
230 /*
217 * This is in the process of releasing memory so wait for it 231 * This is in the process of releasing memory so wait for it
218 * to finish before killing some other task by mistake. 232 * to finish before killing some other task by mistake.
219 * 233 *
@@ -221,21 +235,16 @@ static struct task_struct *select_bad_process(unsigned long *ppoints)
221 * go ahead if it is exiting: this will simply set TIF_MEMDIE, 235 * go ahead if it is exiting: this will simply set TIF_MEMDIE,
222 * which will allow it to gain access to memory reserves in 236 * which will allow it to gain access to memory reserves in
223 * the process of exiting and releasing its resources. 237 * the process of exiting and releasing its resources.
224 * Otherwise we could get an OOM deadlock. 238 * Otherwise we could get an easy OOM deadlock.
225 */ 239 */
226 releasing = test_tsk_thread_flag(p, TIF_MEMDIE) || 240 if (p->flags & PF_EXITING) {
227 p->flags & PF_EXITING; 241 if (p != current)
228 if (releasing) { 242 return ERR_PTR(-1UL);
229 /* PF_DEAD tasks have already released their mm */ 243
230 if (p->flags & PF_DEAD) 244 chosen = p;
231 continue; 245 *ppoints = ULONG_MAX;
232 if (p->flags & PF_EXITING && p == current) {
233 chosen = p;
234 *ppoints = ULONG_MAX;
235 break;
236 }
237 return ERR_PTR(-1UL);
238 } 246 }
247
239 if (p->oomkilladj == OOM_DISABLE) 248 if (p->oomkilladj == OOM_DISABLE)
240 continue; 249 continue;
241 250
@@ -245,6 +254,7 @@ static struct task_struct *select_bad_process(unsigned long *ppoints)
245 *ppoints = points; 254 *ppoints = points;
246 } 255 }
247 } while_each_thread(g, p); 256 } while_each_thread(g, p);
257
248 return chosen; 258 return chosen;
249} 259}
250 260
@@ -255,20 +265,17 @@ static struct task_struct *select_bad_process(unsigned long *ppoints)
255 */ 265 */
256static void __oom_kill_task(struct task_struct *p, const char *message) 266static void __oom_kill_task(struct task_struct *p, const char *message)
257{ 267{
258 if (p->pid == 1) { 268 if (is_init(p)) {
259 WARN_ON(1); 269 WARN_ON(1);
260 printk(KERN_WARNING "tried to kill init!\n"); 270 printk(KERN_WARNING "tried to kill init!\n");
261 return; 271 return;
262 } 272 }
263 273
264 task_lock(p); 274 if (!p->mm) {
265 if (!p->mm || p->mm == &init_mm) {
266 WARN_ON(1); 275 WARN_ON(1);
267 printk(KERN_WARNING "tried to kill an mm-less task!\n"); 276 printk(KERN_WARNING "tried to kill an mm-less task!\n");
268 task_unlock(p);
269 return; 277 return;
270 } 278 }
271 task_unlock(p);
272 279
273 if (message) { 280 if (message) {
274 printk(KERN_ERR "%s: Killed process %d (%s).\n", 281 printk(KERN_ERR "%s: Killed process %d (%s).\n",
@@ -302,7 +309,7 @@ static int oom_kill_task(struct task_struct *p, const char *message)
302 * However, this is of no concern to us. 309 * However, this is of no concern to us.
303 */ 310 */
304 311
305 if (mm == NULL || mm == &init_mm) 312 if (mm == NULL)
306 return 1; 313 return 1;
307 314
308 __oom_kill_task(p, message); 315 __oom_kill_task(p, message);