@@ -440,8 +440,17 @@ static void dump_oom_summary(struct oom_control *oc, struct task_struct *victim)
from_kuid(&init_user_ns, task_uid(victim)));
}
+static void oom_holdoff_expired(struct timer_list *unused)
+{
+}
+static DEFINE_TIMER(oom_timer, oom_holdoff_expired);
+
static void dump_header(struct oom_control *oc)
{
+ unsigned long holdoff = jiffies;
+
+ if (timer_pending(&oom_timer))
+ return;
pr_warn("%s invoked oom-killer: gfp_mask=%#x(%pGg), order=%d, oom_score_adj=%hd\n",
current->comm, oc->gfp_mask, &oc->gfp_mask, oc->order,
current->signal->oom_score_adj);
@@ -458,6 +467,10 @@ static void dump_header(struct oom_control *oc)
}
if (sysctl_oom_dump_tasks)
dump_tasks(oc->memcg, oc->nodemask);
+ holdoff = jiffies - holdoff;
+ if (holdoff < 5 * HZ)
+ holdoff = 5 * HZ;
+ mod_timer(&oom_timer, jiffies + holdoff);
}
/*
@@ -939,8 +952,6 @@ static void oom_kill_process(struct oom_control *oc, const char *message)
{
struct task_struct *victim = oc->chosen;
struct mem_cgroup *oom_group;
- static DEFINE_RATELIMIT_STATE(oom_rs, DEFAULT_RATELIMIT_INTERVAL,
- DEFAULT_RATELIMIT_BURST);
/*
* If the task is already exiting, don't alarm the sysadmin or kill
@@ -957,8 +968,7 @@ static void oom_kill_process(struct oom_control *oc, const char *message)
}
task_unlock(victim);
- if (__ratelimit(&oom_rs))
- dump_header(oc);
+ dump_header(oc);
dump_oom_summary(oc, victim);
/*
@@ -1001,6 +1011,7 @@ static void check_panic_on_oom(struct oom_control *oc,
/* Do not panic for oom kills triggered by sysrq */
if (is_sysrq_oom(oc))
return;
+ del_timer_sync(&oom_timer);
dump_header(oc);
panic("Out of memory: %s panic_on_oom is enabled\n",
sysctl_panic_on_oom == 2 ? "compulsory" : "system-wide");
@@ -1085,6 +1096,8 @@ bool out_of_memory(struct oom_control *oc)
select_bad_process(oc);
/* Found nothing?!?! */
if (!oc->chosen) {
+ if (!is_sysrq_oom(oc) && !is_memcg_oom(oc))
+ del_timer_sync(&oom_timer);
dump_header(oc);
pr_warn("Out of memory and no killable processes...\n");
/*
Since the owner of oom_lock cannot send SIGKILL before dump_header() completes (which might take minutes if preempted by concurrently allocating threads) while concurrently allocating threads are expecting that sleeping for one jiffy is sufficient, we need to make sure that dump_header() is rarely called so that concurrently allocating threads won't waste CPU time too much. This patch makes sure that we waited for at least 5 seconds before calling dump_header() again. This patch is not helpful for the first call. But holding off for jiffies spent for previous dump_header() (or at least 5 seconds) should be able to prevent concurrently allocating threads from wasting CPU time for subsequent dump_header() calls. Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Cc: yuzhoujian <yuzhoujian@didichuxing.com> Cc: Michal Hocko <mhocko@suse.com> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: David Rientjes <rientjes@google.com> Cc: "Kirill A . Shutemov" <kirill.shutemov@linux.intel.com> Cc: Roman Gushchin <guro@fb.com> Cc: Yang Shi <yang.s@alibaba-inc.com> --- mm/oom_kill.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-)