1257 lines · 33.5 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/* *  linux/mm/oom_kill.c * *  Copyright (C)  1998,2000  Rik van Riel *	Thanks go out to Claus Fischer for some serious inspiration and *	for goading me into coding this file... *  Copyright (C)  2010  Google, Inc. *	Rewritten by David Rientjes * *  The routines in this file are used to kill a process when *  we're seriously out of memory. This gets called from __alloc_pages() *  in mm/page_alloc.c when we really run out of memory. * *  Since we won't call these routines often (on a well-configured *  machine) this file will double as a 'coding guide' and a signpost *  for newbie kernel hackers. It features several pointers to major *  kernel subsystems and hints as to where to find out what things do. */ #include <linux/oom.h>#include <linux/mm.h>#include <linux/err.h>#include <linux/gfp.h>#include <linux/sched.h>#include <linux/sched/mm.h>#include <linux/sched/task.h>#include <linux/sched/debug.h>#include <linux/swap.h>#include <linux/syscalls.h>#include <linux/timex.h>#include <linux/jiffies.h>#include <linux/cpuset.h>#include <linux/export.h>#include <linux/notifier.h>#include <linux/memcontrol.h>#include <linux/mempolicy.h>#include <linux/security.h>#include <linux/ptrace.h>#include <linux/freezer.h>#include <linux/ftrace.h>#include <linux/ratelimit.h>#include <linux/kthread.h>#include <linux/init.h>#include <linux/mmu_notifier.h>#include <linux/cred.h>#include <linux/nmi.h> #include <asm/tlb.h>#include "internal.h"#include "slab.h" #define CREATE_TRACE_POINTS#include <trace/events/oom.h> static int sysctl_panic_on_oom;static int sysctl_oom_kill_allocating_task;static int sysctl_oom_dump_tasks = 1; /* * Serializes oom killer invocations (out_of_memory()) from all contexts to * prevent from over eager oom killing (e.g. when the oom killer is invoked * from different domains). * * oom_killer_disable() relies on this lock to stabilize oom_killer_disabled * and mark_oom_victim */DEFINE_MUTEX(oom_lock);/* Serializes oom_score_adj and oom_score_adj_min updates */DEFINE_MUTEX(oom_adj_mutex); static inline bool is_memcg_oom(struct oom_control *oc){	return oc->memcg != NULL;} #ifdef CONFIG_NUMA/** * oom_cpuset_eligible() - check task eligibility for kill * @start: task struct of which task to consider * @oc: pointer to struct oom_control * * Task eligibility is determined by whether or not a candidate task, @tsk, * shares the same mempolicy nodes as current if it is bound by such a policy * and whether or not it has the same set of allowed cpuset nodes. * * This function is assuming oom-killer context and 'current' has triggered * the oom-killer. */static bool oom_cpuset_eligible(struct task_struct *start,				struct oom_control *oc){	struct task_struct *tsk;	bool ret = false;	const nodemask_t *mask = oc->nodemask; 	rcu_read_lock();	for_each_thread(start, tsk) {		if (mask) {			/*			 * If this is a mempolicy constrained oom, tsk's			 * cpuset is irrelevant.  Only return true if its			 * mempolicy intersects current, otherwise it may be			 * needlessly killed.			 */			ret = mempolicy_in_oom_domain(tsk, mask);		} else {			/*			 * This is not a mempolicy constrained oom, so only			 * check the mems of tsk's cpuset.			 */			ret = cpuset_mems_allowed_intersects(current, tsk);		}		if (ret)			break;	}	rcu_read_unlock(); 	return ret;}#elsestatic bool oom_cpuset_eligible(struct task_struct *tsk, struct oom_control *oc){	return true;}#endif /* CONFIG_NUMA */ /* * The process p may have detached its own ->mm while exiting or through * kthread_use_mm(), but one or more of its subthreads may still have a valid * pointer.  Return p, or any of its subthreads with a valid ->mm, with * task_lock() held. */struct task_struct *find_lock_task_mm(struct task_struct *p){	struct task_struct *t; 	guard(rcu)(); 	for_each_thread(p, t) {		task_lock(t);		if (likely(t->mm))			return t;		task_unlock(t);	} 	return NULL;} /* * order == -1 means the oom kill is required by sysrq, otherwise only * for display purposes. */static inline bool is_sysrq_oom(struct oom_control *oc){	return oc->order == -1;} /* return true if the task is not adequate as candidate victim task. */static bool oom_unkillable_task(struct task_struct *p){	if (is_global_init(p))		return true;	if (p->flags & PF_KTHREAD)		return true;	return false;} /* * Check whether unreclaimable slab amount is greater than * all user memory(LRU pages). * dump_unreclaimable_slab() could help in the case that * oom due to too much unreclaimable slab used by kernel.*/static bool should_dump_unreclaim_slab(void){	unsigned long nr_lru; 	nr_lru = global_node_page_state(NR_ACTIVE_ANON) +		 global_node_page_state(NR_INACTIVE_ANON) +		 global_node_page_state(NR_ACTIVE_FILE) +		 global_node_page_state(NR_INACTIVE_FILE) +		 global_node_page_state(NR_ISOLATED_ANON) +		 global_node_page_state(NR_ISOLATED_FILE) +		 global_node_page_state(NR_UNEVICTABLE); 	return (global_node_page_state_pages(NR_SLAB_UNRECLAIMABLE_B) > nr_lru);} /** * oom_badness - heuristic function to determine which candidate task to kill * @p: task struct of which task we should calculate * @totalpages: total present RAM allowed for page allocation * * The heuristic for determining which task to kill is made to be as simple and * predictable as possible.  The goal is to return the highest value for the * task consuming the most memory to avoid subsequent oom failures. */long oom_badness(struct task_struct *p, unsigned long totalpages){	long points;	long adj; 	if (oom_unkillable_task(p))		return LONG_MIN; 	p = find_lock_task_mm(p);	if (!p)		return LONG_MIN; 	/*	 * Do not even consider tasks which are explicitly marked oom	 * unkillable or have been already oom reaped or the are in	 * the middle of vfork	 */	adj = (long)p->signal->oom_score_adj;	if (adj == OOM_SCORE_ADJ_MIN ||			mm_flags_test(MMF_OOM_SKIP, p->mm) ||			in_vfork(p)) {		task_unlock(p);		return LONG_MIN;	} 	/*	 * The baseline for the badness score is the proportion of RAM that each	 * task's rss, pagetable and swap space use.	 */	points = get_mm_rss_sum(p->mm) + get_mm_counter_sum(p->mm, MM_SWAPENTS) +		mm_pgtables_bytes(p->mm) / PAGE_SIZE;	task_unlock(p); 	/* Normalize to oom_score_adj units */	adj *= totalpages / 1000;	points += adj; 	return points;} static const char * const oom_constraint_text[] = {	[CONSTRAINT_NONE] = "CONSTRAINT_NONE",	[CONSTRAINT_CPUSET] = "CONSTRAINT_CPUSET",	[CONSTRAINT_MEMORY_POLICY] = "CONSTRAINT_MEMORY_POLICY",	[CONSTRAINT_MEMCG] = "CONSTRAINT_MEMCG",}; /* * Determine the type of allocation constraint. */static enum oom_constraint constrained_alloc(struct oom_control *oc){	struct zone *zone;	struct zoneref *z;	enum zone_type highest_zoneidx = gfp_zone(oc->gfp_mask);	bool cpuset_limited = false;	int nid; 	if (is_memcg_oom(oc)) {		oc->totalpages = mem_cgroup_get_max(oc->memcg) ?: 1;		return CONSTRAINT_MEMCG;	} 	/* Default to all available memory */	oc->totalpages = totalram_pages() + total_swap_pages; 	if (!IS_ENABLED(CONFIG_NUMA))		return CONSTRAINT_NONE; 	if (!oc->zonelist)		return CONSTRAINT_NONE;	/*	 * Reach here only when __GFP_NOFAIL is used. So, we should avoid	 * to kill current.We have to random task kill in this case.	 * Hopefully, CONSTRAINT_THISNODE...but no way to handle it, now.	 */	if (oc->gfp_mask & __GFP_THISNODE)		return CONSTRAINT_NONE; 	/*	 * This is not a __GFP_THISNODE allocation, so a truncated nodemask in	 * the page allocator means a mempolicy is in effect.  Cpuset policy	 * is enforced in get_page_from_freelist().	 */	if (oc->nodemask &&	    !nodes_subset(node_states[N_MEMORY], *oc->nodemask)) {		oc->totalpages = total_swap_pages;		for_each_node_mask(nid, *oc->nodemask)			oc->totalpages += node_present_pages(nid);		return CONSTRAINT_MEMORY_POLICY;	} 	/* Check this allocation failure is caused by cpuset's wall function */	for_each_zone_zonelist_nodemask(zone, z, oc->zonelist,			highest_zoneidx, oc->nodemask)		if (!cpuset_zone_allowed(zone, oc->gfp_mask))			cpuset_limited = true; 	if (cpuset_limited) {		oc->totalpages = total_swap_pages;		for_each_node_mask(nid, cpuset_current_mems_allowed)			oc->totalpages += node_present_pages(nid);		return CONSTRAINT_CPUSET;	}	return CONSTRAINT_NONE;} static int oom_evaluate_task(struct task_struct *task, void *arg){	struct oom_control *oc = arg;	long points; 	if (oom_unkillable_task(task))		goto next; 	/* p may not have freeable memory in nodemask */	if (!is_memcg_oom(oc) && !oom_cpuset_eligible(task, oc))		goto next; 	/*	 * This task already has access to memory reserves and is being killed.	 * Don't allow any other task to have access to the reserves unless	 * the task has MMF_OOM_SKIP because chances that it would release	 * any memory is quite low.	 */	if (!is_sysrq_oom(oc) && tsk_is_oom_victim(task)) {		if (mm_flags_test(MMF_OOM_SKIP, task->signal->oom_mm))			goto next;		goto abort;	} 	/*	 * If task is allocating a lot of memory and has been marked to be	 * killed first if it triggers an oom, then select it.	 */	if (oom_task_origin(task)) {		points = LONG_MAX;		goto select;	} 	points = oom_badness(task, oc->totalpages);	if (points == LONG_MIN || points < oc->chosen_points)		goto next; select:	if (oc->chosen)		put_task_struct(oc->chosen);	get_task_struct(task);	oc->chosen = task;	oc->chosen_points = points;next:	return 0;abort:	if (oc->chosen)		put_task_struct(oc->chosen);	oc->chosen = (void *)-1UL;	return 1;} /* * Simple selection loop. We choose the process with the highest number of * 'points'. In case scan was aborted, oc->chosen is set to -1. */static void select_bad_process(struct oom_control *oc){	oc->chosen_points = LONG_MIN; 	if (is_memcg_oom(oc))		mem_cgroup_scan_tasks(oc->memcg, oom_evaluate_task, oc);	else {		struct task_struct *p; 		rcu_read_lock();		for_each_process(p)			if (oom_evaluate_task(p, oc))				break;		rcu_read_unlock();	}} static int dump_task(struct task_struct *p, void *arg){	struct oom_control *oc = arg;	struct task_struct *task; 	if (oom_unkillable_task(p))		return 0; 	/* p may not have freeable memory in nodemask */	if (!is_memcg_oom(oc) && !oom_cpuset_eligible(p, oc))		return 0; 	task = find_lock_task_mm(p);	if (!task) {		/*		 * All of p's threads have already detached their mm's. There's		 * no need to report them; they can't be oom killed anyway.		 */		return 0;	} 	pr_info("[%7d] %5d %5d %8lu %8lu %8lu %8lu %9lu %8ld %8lu         %5hd %s\n",		task->pid, from_kuid(&init_user_ns, task_uid(task)),		task->tgid, task->mm->total_vm, get_mm_rss_sum(task->mm),		get_mm_counter_sum(task->mm, MM_ANONPAGES), get_mm_counter_sum(task->mm, MM_FILEPAGES),		get_mm_counter_sum(task->mm, MM_SHMEMPAGES), mm_pgtables_bytes(task->mm),		get_mm_counter_sum(task->mm, MM_SWAPENTS),		task->signal->oom_score_adj, task->comm);	task_unlock(task); 	return 0;} /** * dump_tasks - dump current memory state of all system tasks * @oc: pointer to struct oom_control * * Dumps the current memory state of all eligible tasks.  Tasks not in the same * memcg, not in the same cpuset, or bound to a disjoint set of mempolicy nodes * are not shown. * State information includes task's pid, uid, tgid, vm size, rss, * pgtables_bytes, swapents, oom_score_adj value, and name. */static void dump_tasks(struct oom_control *oc){	pr_info("Tasks state (memory values in pages):\n");	pr_info("[  pid  ]   uid  tgid total_vm      rss rss_anon rss_file rss_shmem pgtables_bytes swapents oom_score_adj name\n"); 	if (is_memcg_oom(oc))		mem_cgroup_scan_tasks(oc->memcg, dump_task, oc);	else {		struct task_struct *p;		int i = 0; 		rcu_read_lock();		for_each_process(p) {			/* Avoid potential softlockup warning */			if ((++i & 1023) == 0)				touch_softlockup_watchdog();			dump_task(p, oc);		}		rcu_read_unlock();	}} static void dump_oom_victim(struct oom_control *oc, struct task_struct *victim){	/* one line summary of the oom killer context. */	pr_info("oom-kill:constraint=%s,nodemask=%*pbl",			oom_constraint_text[oc->constraint],			nodemask_pr_args(oc->nodemask));	cpuset_print_current_mems_allowed();	mem_cgroup_print_oom_context(oc->memcg, victim);	pr_cont(",task=%s,pid=%d,uid=%d\n", victim->comm, victim->pid,		from_kuid(&init_user_ns, task_uid(victim)));} static void dump_header(struct oom_control *oc){	pr_warn("%s invoked oom-killer: gfp_mask=%#x(%pGg), order=%d, oom_score_adj=%d\n",		current->comm, oc->gfp_mask, &oc->gfp_mask, oc->order,			current->signal->oom_score_adj);	if (!IS_ENABLED(CONFIG_COMPACTION) && oc->order)		pr_warn("COMPACTION is disabled!!!\n"); 	dump_stack();	if (is_memcg_oom(oc))		mem_cgroup_print_oom_meminfo(oc->memcg);	else {		__show_mem(SHOW_MEM_FILTER_NODES, oc->nodemask, gfp_zone(oc->gfp_mask));		if (should_dump_unreclaim_slab())			dump_unreclaimable_slab();	}	mem_cgroup_show_protected_memory(oc->memcg);	if (sysctl_oom_dump_tasks)		dump_tasks(oc);} /* * Number of OOM victims in flight */static atomic_t oom_victims = ATOMIC_INIT(0);static DECLARE_WAIT_QUEUE_HEAD(oom_victims_wait); static bool oom_killer_disabled __read_mostly; /* * task->mm can be NULL if the task is the exited group leader.  So to * determine whether the task is using a particular mm, we examine all the * task's threads: if one of those is using this mm then this task was also * using it. */bool process_shares_mm(const struct task_struct *p, const struct mm_struct *mm){	const struct task_struct *t; 	for_each_thread(p, t) {		const struct mm_struct *t_mm = READ_ONCE(t->mm);		if (t_mm)			return t_mm == mm;	}	return false;

Lines 1–500 of 1257.