aboutsummaryrefslogtreecommitdiffstats
path: root/mm/oom_kill.c
diff options
context:
space:
mode:
authorKOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>2010-08-19 17:13:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-20 12:34:55 -0400
commitb52723c5607f7684c2c0c075f86f86da0d7fb6d0 (patch)
tree97db08ef9d74c8fcacff6a96070854a5bc276419 /mm/oom_kill.c
parentbe71cf2202971e50ce4953d473649c724799eb8a (diff)
oom: fix tasklist_lock leak
Commit 0aad4b3124 ("oom: fold __out_of_memory into out_of_memory") introduced a tasklist_lock leak. Then it caused following obvious danger warnings and panic. ================================================ [ BUG: lock held when returning to user space! ] ------------------------------------------------ rsyslogd/1422 is leaving the kernel with locks still held! 1 lock held by rsyslogd/1422: #0: (tasklist_lock){.+.+.+}, at: [<ffffffff810faf64>] out_of_memory+0x164/0x3f0 BUG: scheduling while atomic: rsyslogd/1422/0x00000002 INFO: lockdep is turned off. This patch fixes it. Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Reviewed-by: Minchan Kim <minchan.kim@gmail.com> Acked-by: David Rientjes <rientjes@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/oom_kill.c')
-rw-r--r--mm/oom_kill.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 17d48a67e7b7..c48c5ef3ccfd 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -646,6 +646,7 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
646 unsigned long freed = 0; 646 unsigned long freed = 0;
647 unsigned int points; 647 unsigned int points;
648 enum oom_constraint constraint = CONSTRAINT_NONE; 648 enum oom_constraint constraint = CONSTRAINT_NONE;
649 int killed = 0;
649 650
650 blocking_notifier_call_chain(&oom_notify_list, 0, &freed); 651 blocking_notifier_call_chain(&oom_notify_list, 0, &freed);
651 if (freed > 0) 652 if (freed > 0)
@@ -683,7 +684,7 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
683 if (!oom_kill_process(current, gfp_mask, order, 0, totalpages, 684 if (!oom_kill_process(current, gfp_mask, order, 0, totalpages,
684 NULL, nodemask, 685 NULL, nodemask,
685 "Out of memory (oom_kill_allocating_task)")) 686 "Out of memory (oom_kill_allocating_task)"))
686 return; 687 goto out;
687 } 688 }
688 689
689retry: 690retry:
@@ -691,7 +692,7 @@ retry:
691 constraint == CONSTRAINT_MEMORY_POLICY ? nodemask : 692 constraint == CONSTRAINT_MEMORY_POLICY ? nodemask :
692 NULL); 693 NULL);
693 if (PTR_ERR(p) == -1UL) 694 if (PTR_ERR(p) == -1UL)
694 return; 695 goto out;
695 696
696 /* Found nothing?!?! Either we hang forever, or we panic. */ 697 /* Found nothing?!?! Either we hang forever, or we panic. */
697 if (!p) { 698 if (!p) {
@@ -703,13 +704,15 @@ retry:
703 if (oom_kill_process(p, gfp_mask, order, points, totalpages, NULL, 704 if (oom_kill_process(p, gfp_mask, order, points, totalpages, NULL,
704 nodemask, "Out of memory")) 705 nodemask, "Out of memory"))
705 goto retry; 706 goto retry;
707 killed = 1;
708out:
706 read_unlock(&tasklist_lock); 709 read_unlock(&tasklist_lock);
707 710
708 /* 711 /*
709 * Give "p" a good chance of killing itself before we 712 * Give "p" a good chance of killing itself before we
710 * retry to allocate memory unless "p" is current 713 * retry to allocate memory unless "p" is current
711 */ 714 */
712 if (!test_thread_flag(TIF_MEMDIE)) 715 if (killed && !test_thread_flag(TIF_MEMDIE))
713 schedule_timeout_uninterruptible(1); 716 schedule_timeout_uninterruptible(1);
714} 717}
715 718