Loading include/linux/oom.h +3 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,9 @@ struct oom_control { unsigned long totalpages; struct task_struct *chosen; unsigned long chosen_points; #ifdef CONFIG_PRIORITIZE_OOM_TASKS short min_kill_adj; #endif /* Used to print the constraint info. */ enum oom_constraint constraint; Loading mm/Kconfig +27 −0 Original line number Diff line number Diff line Loading @@ -804,4 +804,31 @@ config ARCH_HAS_PTE_SPECIAL config ARCH_HAS_HUGEPD bool config PRIORITIZE_OOM_TASKS bool "Attempt to further prioritize OOM killer kills" depends on QGKI help When the OOM killer selects a task to kill it considers all tasks with a oom_score_adj value > OOM_SCORE_ADJ_MIN. This doesn't work well when the OS has 'high priority' tasks which should only be considered for killing after all other 'lower priority' tasks have first been killed. Enable this option to impose a limit on the minimum task oom_score_adj which should first be considered for killing before allowing the OOM killer to select tasks without limitation. If unsure, say N. config OOM_TASK_PRIORITY_ADJ_LIMIT int "Min oom_score_adj when priotizing OOM killer kills" depends on PRIORITIZE_OOM_TASKS range -1000 1000 default 0 help With this parameter you can limit the OOM killer to first kill tasks with an oom_score_adj value above a certain threshold before considering tasks with a lower oom_score_adj value. endmenu mm/oom_kill.c +51 −10 Original line number Diff line number Diff line Loading @@ -317,6 +317,10 @@ static int oom_evaluate_task(struct task_struct *task, void *arg) { struct oom_control *oc = arg; unsigned long points; #ifdef CONFIG_PRIORITIZE_OOM_TASKS struct task_struct *p; short adj; #endif if (oom_unkillable_task(task)) goto next; Loading @@ -337,6 +341,18 @@ static int oom_evaluate_task(struct task_struct *task, void *arg) goto abort; } #ifdef CONFIG_PRIORITIZE_OOM_TASKS p = find_lock_task_mm(task); if (!p) goto next; adj = p->signal->oom_score_adj; task_unlock(p); if (adj < oc->min_kill_adj) goto next; #endif /* * If task is allocating a lot of memory and has been marked to be * killed first if it triggers an oom, then select it. Loading Loading @@ -994,7 +1010,11 @@ static void oom_kill_process(struct oom_control *oc, const char *message) } task_unlock(victim); if (__ratelimit(&oom_rs)) if (__ratelimit(&oom_rs) #ifdef CONFIG_PRIORITIZE_OOM_TASKS && oc->min_kill_adj < CONFIG_OOM_TASK_PRIORITY_ADJ_LIMIT #endif ) dump_header(oc, victim); /* Loading Loading @@ -1070,13 +1090,9 @@ bool out_of_memory(struct oom_control *oc) if (oom_killer_disabled) return false; if (try_online_one_block(numa_node_id())) { /* Got some memory back */ WARN(1, "OOM killer had to online a memory block\n"); return true; } #ifdef CONFIG_PRIORITIZE_OOM_TASKS oc->min_kill_adj = OOM_SCORE_ADJ_MIN; #endif if (!is_memcg_oom(oc)) { blocking_notifier_call_chain(&oom_notify_list, 0, &freed); if (freed > 0) Loading Loading @@ -1112,19 +1128,44 @@ bool out_of_memory(struct oom_control *oc) oc->constraint = constrained_alloc(oc); if (oc->constraint != CONSTRAINT_MEMORY_POLICY) oc->nodemask = NULL; check_panic_on_oom(oc); if (!is_memcg_oom(oc) && sysctl_oom_kill_allocating_task && current->mm && !oom_unkillable_task(current) && oom_cpuset_eligible(current, oc) && current->signal->oom_score_adj != OOM_SCORE_ADJ_MIN) { check_panic_on_oom(oc); get_task_struct(current); oc->chosen = current; oom_kill_process(oc, "Out of memory (oom_kill_allocating_task)"); return true; } #ifdef CONFIG_PRIORITIZE_OOM_TASKS if (oc->min_kill_adj < CONFIG_OOM_TASK_PRIORITY_ADJ_LIMIT) { short prev_min_kill_adj = oc->min_kill_adj; oc->min_kill_adj = CONFIG_OOM_TASK_PRIORITY_ADJ_LIMIT; select_bad_process(oc); if (!oc->chosen) { pr_warn_ratelimited("Could not find task with adj >= %d\n", CONFIG_OOM_TASK_PRIORITY_ADJ_LIMIT); oc->min_kill_adj = prev_min_kill_adj; oc->chosen_points = 0; } } #endif if (!oc->chosen) { if (try_online_one_block(numa_node_id())) { /* Got some memory back */ WARN(1, "OOM killer had to online a memory block\n"); return true; } check_panic_on_oom(oc); select_bad_process(oc); } /* Found nothing?!?! */ if (!oc->chosen) { dump_header(oc, NULL); Loading Loading
include/linux/oom.h +3 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,9 @@ struct oom_control { unsigned long totalpages; struct task_struct *chosen; unsigned long chosen_points; #ifdef CONFIG_PRIORITIZE_OOM_TASKS short min_kill_adj; #endif /* Used to print the constraint info. */ enum oom_constraint constraint; Loading
mm/Kconfig +27 −0 Original line number Diff line number Diff line Loading @@ -804,4 +804,31 @@ config ARCH_HAS_PTE_SPECIAL config ARCH_HAS_HUGEPD bool config PRIORITIZE_OOM_TASKS bool "Attempt to further prioritize OOM killer kills" depends on QGKI help When the OOM killer selects a task to kill it considers all tasks with a oom_score_adj value > OOM_SCORE_ADJ_MIN. This doesn't work well when the OS has 'high priority' tasks which should only be considered for killing after all other 'lower priority' tasks have first been killed. Enable this option to impose a limit on the minimum task oom_score_adj which should first be considered for killing before allowing the OOM killer to select tasks without limitation. If unsure, say N. config OOM_TASK_PRIORITY_ADJ_LIMIT int "Min oom_score_adj when priotizing OOM killer kills" depends on PRIORITIZE_OOM_TASKS range -1000 1000 default 0 help With this parameter you can limit the OOM killer to first kill tasks with an oom_score_adj value above a certain threshold before considering tasks with a lower oom_score_adj value. endmenu
mm/oom_kill.c +51 −10 Original line number Diff line number Diff line Loading @@ -317,6 +317,10 @@ static int oom_evaluate_task(struct task_struct *task, void *arg) { struct oom_control *oc = arg; unsigned long points; #ifdef CONFIG_PRIORITIZE_OOM_TASKS struct task_struct *p; short adj; #endif if (oom_unkillable_task(task)) goto next; Loading @@ -337,6 +341,18 @@ static int oom_evaluate_task(struct task_struct *task, void *arg) goto abort; } #ifdef CONFIG_PRIORITIZE_OOM_TASKS p = find_lock_task_mm(task); if (!p) goto next; adj = p->signal->oom_score_adj; task_unlock(p); if (adj < oc->min_kill_adj) goto next; #endif /* * If task is allocating a lot of memory and has been marked to be * killed first if it triggers an oom, then select it. Loading Loading @@ -994,7 +1010,11 @@ static void oom_kill_process(struct oom_control *oc, const char *message) } task_unlock(victim); if (__ratelimit(&oom_rs)) if (__ratelimit(&oom_rs) #ifdef CONFIG_PRIORITIZE_OOM_TASKS && oc->min_kill_adj < CONFIG_OOM_TASK_PRIORITY_ADJ_LIMIT #endif ) dump_header(oc, victim); /* Loading Loading @@ -1070,13 +1090,9 @@ bool out_of_memory(struct oom_control *oc) if (oom_killer_disabled) return false; if (try_online_one_block(numa_node_id())) { /* Got some memory back */ WARN(1, "OOM killer had to online a memory block\n"); return true; } #ifdef CONFIG_PRIORITIZE_OOM_TASKS oc->min_kill_adj = OOM_SCORE_ADJ_MIN; #endif if (!is_memcg_oom(oc)) { blocking_notifier_call_chain(&oom_notify_list, 0, &freed); if (freed > 0) Loading Loading @@ -1112,19 +1128,44 @@ bool out_of_memory(struct oom_control *oc) oc->constraint = constrained_alloc(oc); if (oc->constraint != CONSTRAINT_MEMORY_POLICY) oc->nodemask = NULL; check_panic_on_oom(oc); if (!is_memcg_oom(oc) && sysctl_oom_kill_allocating_task && current->mm && !oom_unkillable_task(current) && oom_cpuset_eligible(current, oc) && current->signal->oom_score_adj != OOM_SCORE_ADJ_MIN) { check_panic_on_oom(oc); get_task_struct(current); oc->chosen = current; oom_kill_process(oc, "Out of memory (oom_kill_allocating_task)"); return true; } #ifdef CONFIG_PRIORITIZE_OOM_TASKS if (oc->min_kill_adj < CONFIG_OOM_TASK_PRIORITY_ADJ_LIMIT) { short prev_min_kill_adj = oc->min_kill_adj; oc->min_kill_adj = CONFIG_OOM_TASK_PRIORITY_ADJ_LIMIT; select_bad_process(oc); if (!oc->chosen) { pr_warn_ratelimited("Could not find task with adj >= %d\n", CONFIG_OOM_TASK_PRIORITY_ADJ_LIMIT); oc->min_kill_adj = prev_min_kill_adj; oc->chosen_points = 0; } } #endif if (!oc->chosen) { if (try_online_one_block(numa_node_id())) { /* Got some memory back */ WARN(1, "OOM killer had to online a memory block\n"); return true; } check_panic_on_oom(oc); select_bad_process(oc); } /* Found nothing?!?! */ if (!oc->chosen) { dump_header(oc, NULL); Loading