Index: linux-2.6.27.y/init/Kconfig =================================================================== --- linux-2.6.27.y.orig/init/Kconfig +++ linux-2.6.27.y/init/Kconfig @@ -306,6 +306,23 @@ config CGROUP_DEVICE Provides a cgroup implementing whitelists for devices which a process in the cgroup can mknod or open. +config OOM_PANIC + bool "OOM Panic" + default y + ---help--- + This option enables panic() to be called when a system is out of + memory. This feature along with /proc/sys/kernel/panic allows a + different behavior on out-of-memory conditions when the standard + behavior (killing processes in an attempt to recover) does not + make sense. + + If unsure, say N. + +config OOM_KILL + bool + depends on !OOM_PANIC + default y + config CPUSETS bool "Cpuset support" depends on SMP && CGROUPS Index: linux-2.6.27.y/mm/oom_kill.c =================================================================== --- linux-2.6.27.y.orig/mm/oom_kill.c +++ linux-2.6.27.y/mm/oom_kill.c @@ -177,6 +177,11 @@ unsigned long badness(struct task_struct return points; } +#if defined(CONFIG_OOM_PANIC) && defined(CONFIG_OOM_KILLER) +#warning Only define OOM_PANIC or OOM_KILLER; not both +#endif + +#ifdef CONFIG_OOM_KILLER /* * Determine the type of allocation constraint. */ @@ -454,6 +459,7 @@ out: read_unlock(&tasklist_lock); cgroup_unlock(); } + #endif static BLOCKING_NOTIFIER_HEAD(oom_notify_list); @@ -519,6 +525,7 @@ void clear_zonelist_oom(struct zonelist } spin_unlock(&zone_scan_mutex); } +EXPORT_SYMBOL_GPL(clear_zonelist_oom); /** * out_of_memory - kill the "best" process when we run out of memory @@ -602,3 +609,47 @@ out: if (!test_thread_flag(TIF_MEMDIE)) schedule_timeout_uninterruptible(1); } +#endif /* CONFIG_OOM_KILLER */ + +#ifdef CONFIG_OOM_PANIC +/** + * out_of_memory - panic if the system out of memory? + */ +void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order) +{ + /* + * oom_lock protects out_of_memory()'s static variables. + * It's a global lock; this is not performance-critical. + */ + static spinlock_t oom_lock = SPIN_LOCK_UNLOCKED; + static unsigned long count; + + spin_lock(&oom_lock); + + /* + * If we have gotten only a few failures, + * we're not really oom. + */ + if (++count >= 10) { + /* + * Ok, really out of memory. Panic. + */ + + printk("oom-killer: gfp_mask=0x%x\n", gfp_mask); + show_free_areas(); + + panic("Out Of Memory"); + } + spin_unlock(&oom_lock); +} + +#ifdef CONFIG_CGROUP_MEM_RES_CTLR +void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask) +{ + cgroup_lock(); + panic("Memory cgroup out Of Memory"); + cgroup_unlock(); +} + +#endif +#endif /* CONFIG_OOM_PANIC */ Index: linux-2.6.27.y/mm/oom_panic.c =================================================================== --- /dev/null +++ linux-2.6.27.y/mm/oom_panic.c @@ -0,0 +1,51 @@ +/* + * Just panic() instead of the default behavior of selecting processes + * for death. + * + * Based on + * Modular OOM handlers for 2.6.4 (C) 2003,2004 Tvrtko A. Ursulin + * and + * linux/mm/oom_kill.c (C) 1998,2000 Rik van Riel. + * + * Mark Huang + * + * $Id: oom_panic.c,v 1.1 2004/10/01 17:54:48 mlhuang Exp $ + */ + +#include +#include +#include + +/** + * out_of_memory - is the system out of memory? + */ +void out_of_memory(int gfp_mask) +{ + /* + * oom_lock protects out_of_memory()'s static variables. + * It's a global lock; this is not performance-critical. + */ + static spinlock_t oom_lock = SPIN_LOCK_UNLOCKED; + static unsigned long count; + + spin_lock(&oom_lock); + + /* + * If we have gotten only a few failures, + * we're not really oom. + */ + if (++count < 10) + goto out_unlock; + + /* + * Ok, really out of memory. Panic. + */ + + printk("oom-killer: gfp_mask=0x%x\n", gfp_mask); + show_free_areas(); + + panic("Out Of Memory"); + +out_unlock: + spin_unlock(&oom_lock); +} Index: linux-2.6.27.y/mm/page_alloc.c =================================================================== --- linux-2.6.27.y.orig/mm/page_alloc.c +++ linux-2.6.27.y/mm/page_alloc.c @@ -1588,11 +1588,12 @@ nofail_alloc: if (page) goto got_pg; } else if ((gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY)) { +#ifdef CONFIG_OOM_KILLER if (!try_set_zone_oom(zonelist, gfp_mask)) { schedule_timeout_uninterruptible(1); goto restart; } - +#endif /* * Go through the zonelist yet one more time, keep * very high watermark here, this is only to catch @@ -1603,18 +1604,24 @@ nofail_alloc: order, zonelist, high_zoneidx, ALLOC_WMARK_HIGH|ALLOC_CPUSET); if (page) { +#ifdef CONFIG_OOM_KILLER clear_zonelist_oom(zonelist, gfp_mask); +#endif goto got_pg; } /* The OOM killer will not help higher order allocs so fail */ if (order > PAGE_ALLOC_COSTLY_ORDER) { +#ifdef CONFIG_OOM_KILLER clear_zonelist_oom(zonelist, gfp_mask); +#endif goto nopage; } out_of_memory(zonelist, gfp_mask, order); +#ifdef CONFIG_OOM_KILLER clear_zonelist_oom(zonelist, gfp_mask); +#endif goto restart; }