--- linux-2.6.18.noarch/mm/oom_kill.c.orig +++ linux-2.6.18.noarch/mm/oom_kill.c @@ -306,6 +306,69 @@ static int oom_kill_process(struct task_ return oom_kill_task(p, message); } +int should_oom_kill(void) +{ + static spinlock_t oom_lock = SPIN_LOCK_UNLOCKED; + static unsigned long first, last, count, lastkill; + unsigned long now, since; + int ret = 0; + + spin_lock(&oom_lock); + now = jiffies; + since = now - last; + last = now; + + /* + * If it's been a long time since last failure, + * we're not oom. + */ + if (since > 5*HZ) + goto reset; + + /* + * If we haven't tried for at least one second, + * we're not really oom. + */ + since = now - first; + if (since < HZ) + goto out_unlock; + + /* + * If we have gotten only a few failures, + * we're not really oom. + */ + if (++count < 10) + goto out_unlock; + + /* + * If we just killed a process, wait a while + * to give that task a chance to exit. This + * avoids killing multiple processes needlessly. + */ + since = now - lastkill; + if (since < HZ*5) + goto out_unlock; + + /* + * Ok, really out of memory. Kill something. + */ + lastkill = now; + ret = 1; + +reset: +/* + * We dropped the lock above, so check to be sure the variable + * first only ever increases to prevent false OOM's. + */ + if (time_after(now, first)) + first = now; + count = 0; + +out_unlock: + spin_unlock(&oom_lock); + return ret; +} + /** * out_of_memory - kill the "best" process when we run out of memory * @@ -326,6 +389,9 @@ void out_of_memory(struct zonelist *zone show_mem(); } + if (!should_oom_kill()) + return; + cpuset_lock(); read_lock(&tasklist_lock); --- linux-2.6.18.noarch/mm/vmscan.c.orig +++ linux-2.6.18.noarch/mm/vmscan.c @@ -999,10 +999,8 @@ unsigned long try_to_free_pages(struct z reclaim_state->reclaimed_slab = 0; } total_scanned += sc.nr_scanned; - if (nr_reclaimed >= sc.swap_cluster_max) { - ret = 1; + if (nr_reclaimed >= sc.swap_cluster_max) goto out; - } /* * Try to write back as many pages as we just scanned. This @@ -1030,6 +1028,8 @@ out: zone->prev_priority = zone->temp_priority; } + if (nr_reclaimed) + ret = 1; return ret; }