Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7b082008 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "mm: oom_kill: Support further prioritization of OOM kills"

parents eed96359 0c1d7417
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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;
+27 −0
Original line number Diff line number Diff line
@@ -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
+51 −10
Original line number Diff line number Diff line
@@ -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;
@@ -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.
@@ -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);

	/*
@@ -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)
@@ -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);