aboutsummaryrefslogtreecommitdiffstats
path: root/mm/oom_kill.c
diff options
context:
space:
mode:
authorDavid Rientjes <rientjes@google.com>2010-08-09 20:18:55 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-09 23:44:57 -0400
commite365893236ca78fa1fe2482ccbdc30e9abde6027 (patch)
tree36caf9177f592f0d3a93593b6a569be239aebf91 /mm/oom_kill.c
parent309ed882508cc471320ff79265e7340774d6746c (diff)
oom: remove special handling for pagefault ooms
It is possible to remove the special pagefault oom handler by simply oom locking all system zones and then calling directly into out_of_memory(). All populated zones must have ZONE_OOM_LOCKED set, otherwise there is a parallel oom killing in progress that will lead to eventual memory freeing so it's not necessary to needlessly kill another task. The context in which the pagefault is allocating memory is unknown to the oom killer, so this is done on a system-wide level. If a task has already been oom killed and hasn't fully exited yet, this will be a no-op since select_bad_process() recognizes tasks across the system with TIF_MEMDIE set. Signed-off-by: David Rientjes <rientjes@google.com> Acked-by: Nick Piggin <npiggin@suse.de> Acked-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.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.c86
1 files changed, 57 insertions, 29 deletions
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index fca886d8b5fb..dad13fc41f47 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -631,6 +631,44 @@ void clear_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_mask)
631} 631}
632 632
633/* 633/*
634 * Try to acquire the oom killer lock for all system zones. Returns zero if a
635 * parallel oom killing is taking place, otherwise locks all zones and returns
636 * non-zero.
637 */
638static int try_set_system_oom(void)
639{
640 struct zone *zone;
641 int ret = 1;
642
643 spin_lock(&zone_scan_lock);
644 for_each_populated_zone(zone)
645 if (zone_is_oom_locked(zone)) {
646 ret = 0;
647 goto out;
648 }
649 for_each_populated_zone(zone)
650 zone_set_flag(zone, ZONE_OOM_LOCKED);
651out:
652 spin_unlock(&zone_scan_lock);
653 return ret;
654}
655
656/*
657 * Clears ZONE_OOM_LOCKED for all system zones so that failed allocation
658 * attempts or page faults may now recall the oom killer, if necessary.
659 */
660static void clear_system_oom(void)
661{
662 struct zone *zone;
663
664 spin_lock(&zone_scan_lock);
665 for_each_populated_zone(zone)
666 zone_clear_flag(zone, ZONE_OOM_LOCKED);
667 spin_unlock(&zone_scan_lock);
668}
669
670
671/*
634 * Must be called with tasklist_lock held for read. 672 * Must be called with tasklist_lock held for read.
635 */ 673 */
636static void __out_of_memory(gfp_t gfp_mask, int order, 674static void __out_of_memory(gfp_t gfp_mask, int order,
@@ -665,33 +703,6 @@ retry:
665 goto retry; 703 goto retry;
666} 704}
667 705
668/*
669 * pagefault handler calls into here because it is out of memory but
670 * doesn't know exactly how or why.
671 */
672void pagefault_out_of_memory(void)
673{
674 unsigned long freed = 0;
675
676 blocking_notifier_call_chain(&oom_notify_list, 0, &freed);
677 if (freed > 0)
678 /* Got some memory back in the last second. */
679 return;
680
681 check_panic_on_oom(CONSTRAINT_NONE, 0, 0);
682 read_lock(&tasklist_lock);
683 /* unknown gfp_mask and order */
684 __out_of_memory(0, 0, CONSTRAINT_NONE, NULL);
685 read_unlock(&tasklist_lock);
686
687 /*
688 * Give "p" a good chance of killing itself before we
689 * retry to allocate memory.
690 */
691 if (!test_thread_flag(TIF_MEMDIE))
692 schedule_timeout_uninterruptible(1);
693}
694
695/** 706/**
696 * out_of_memory - kill the "best" process when we run out of memory 707 * out_of_memory - kill the "best" process when we run out of memory
697 * @zonelist: zonelist pointer 708 * @zonelist: zonelist pointer
@@ -708,7 +719,7 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
708 int order, nodemask_t *nodemask) 719 int order, nodemask_t *nodemask)
709{ 720{
710 unsigned long freed = 0; 721 unsigned long freed = 0;
711 enum oom_constraint constraint; 722 enum oom_constraint constraint = CONSTRAINT_NONE;
712 723
713 blocking_notifier_call_chain(&oom_notify_list, 0, &freed); 724 blocking_notifier_call_chain(&oom_notify_list, 0, &freed);
714 if (freed > 0) 725 if (freed > 0)
@@ -729,7 +740,8 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
729 * Check if there were limitations on the allocation (only relevant for 740 * Check if there were limitations on the allocation (only relevant for
730 * NUMA) that may require different handling. 741 * NUMA) that may require different handling.
731 */ 742 */
732 constraint = constrained_alloc(zonelist, gfp_mask, nodemask); 743 if (zonelist)
744 constraint = constrained_alloc(zonelist, gfp_mask, nodemask);
733 check_panic_on_oom(constraint, gfp_mask, order); 745 check_panic_on_oom(constraint, gfp_mask, order);
734 read_lock(&tasklist_lock); 746 read_lock(&tasklist_lock);
735 __out_of_memory(gfp_mask, order, constraint, nodemask); 747 __out_of_memory(gfp_mask, order, constraint, nodemask);
@@ -742,3 +754,19 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
742 if (!test_thread_flag(TIF_MEMDIE)) 754 if (!test_thread_flag(TIF_MEMDIE))
743 schedule_timeout_uninterruptible(1); 755 schedule_timeout_uninterruptible(1);
744} 756}
757
758/*
759 * The pagefault handler calls here because it is out of memory, so kill a
760 * memory-hogging task. If a populated zone has ZONE_OOM_LOCKED set, a parallel
761 * oom killing is already in progress so do nothing. If a task is found with
762 * TIF_MEMDIE set, it has been killed so do nothing and allow it to exit.
763 */
764void pagefault_out_of_memory(void)
765{
766 if (try_set_system_oom()) {
767 out_of_memory(NULL, 0, 0, NULL);
768 clear_system_oom();
769 }
770 if (!test_thread_flag(TIF_MEMDIE))
771 schedule_timeout_uninterruptible(1);
772}