aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorDavid Rientjes <rientjes@google.com>2010-08-09 20:19:46 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-09 23:45:02 -0400
commita63d83f427fbce97a6cea0db2e64b0eb8435cd10 (patch)
tree8ac229cdf6e2289d97e82e35774057106fe7f4a2 /include
parent74bcbf40546bb7500f2a7ba4ff3cc056a6bd004a (diff)
oom: badness heuristic rewrite
This a complete rewrite of the oom killer's badness() heuristic which is used to determine which task to kill in oom conditions. The goal is to make it as simple and predictable as possible so the results are better understood and we end up killing the task which will lead to the most memory freeing while still respecting the fine-tuning from userspace. Instead of basing the heuristic on mm->total_vm for each task, the task's rss and swap space is used instead. This is a better indication of the amount of memory that will be freeable if the oom killed task is chosen and subsequently exits. This helps specifically in cases where KDE or GNOME is chosen for oom kill on desktop systems instead of a memory hogging task. The baseline for the heuristic is a proportion of memory that each task is currently using in memory plus swap compared to the amount of "allowable" memory. "Allowable," in this sense, means the system-wide resources for unconstrained oom conditions, the set of mempolicy nodes, the mems attached to current's cpuset, or a memory controller's limit. The proportion is given on a scale of 0 (never kill) to 1000 (always kill), roughly meaning that if a task has a badness() score of 500 that the task consumes approximately 50% of allowable memory resident in RAM or in swap space. The proportion is always relative to the amount of "allowable" memory and not the total amount of RAM systemwide so that mempolicies and cpusets may operate in isolation; they shall not need to know the true size of the machine on which they are running if they are bound to a specific set of nodes or mems, respectively. Root tasks are given 3% extra memory just like __vm_enough_memory() provides in LSMs. In the event of two tasks consuming similar amounts of memory, it is generally better to save root's task. Because of the change in the badness() heuristic's baseline, it is also necessary to introduce a new user interface to tune it. It's not possible to redefine the meaning of /proc/pid/oom_adj with a new scale since the ABI cannot be changed for backward compatability. Instead, a new tunable, /proc/pid/oom_score_adj, is added that ranges from -1000 to +1000. It may be used to polarize the heuristic such that certain tasks are never considered for oom kill while others may always be considered. The value is added directly into the badness() score so a value of -500, for example, means to discount 50% of its memory consumption in comparison to other tasks either on the system, bound to the mempolicy, in the cpuset, or sharing the same memory controller. /proc/pid/oom_adj is changed so that its meaning is rescaled into the units used by /proc/pid/oom_score_adj, and vice versa. Changing one of these per-task tunables will rescale the value of the other to an equivalent meaning. Although /proc/pid/oom_adj was originally defined as a bitshift on the badness score, it now shares the same linear growth as /proc/pid/oom_score_adj but with different granularity. This is required so the ABI is not broken with userspace applications and allows oom_adj to be deprecated for future removal. Signed-off-by: David Rientjes <rientjes@google.com> Cc: Nick Piggin <npiggin@suse.de> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Balbir Singh <balbir@in.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include')
-rw-r--r--include/linux/memcontrol.h8
-rw-r--r--include/linux/oom.h14
-rw-r--r--include/linux/sched.h3
3 files changed, 23 insertions, 2 deletions
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 9f1afd361583..73564cac38c7 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -125,6 +125,8 @@ void mem_cgroup_update_file_mapped(struct page *page, int val);
125unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order, 125unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
126 gfp_t gfp_mask, int nid, 126 gfp_t gfp_mask, int nid,
127 int zid); 127 int zid);
128u64 mem_cgroup_get_limit(struct mem_cgroup *mem);
129
128#else /* CONFIG_CGROUP_MEM_RES_CTLR */ 130#else /* CONFIG_CGROUP_MEM_RES_CTLR */
129struct mem_cgroup; 131struct mem_cgroup;
130 132
@@ -304,6 +306,12 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
304 return 0; 306 return 0;
305} 307}
306 308
309static inline
310u64 mem_cgroup_get_limit(struct mem_cgroup *mem)
311{
312 return 0;
313}
314
307#endif /* CONFIG_CGROUP_MEM_CONT */ 315#endif /* CONFIG_CGROUP_MEM_CONT */
308 316
309#endif /* _LINUX_MEMCONTROL_H */ 317#endif /* _LINUX_MEMCONTROL_H */
diff --git a/include/linux/oom.h b/include/linux/oom.h
index 40e5e3a6bc20..73b8d7b6dd19 100644
--- a/include/linux/oom.h
+++ b/include/linux/oom.h
@@ -1,14 +1,24 @@
1#ifndef __INCLUDE_LINUX_OOM_H 1#ifndef __INCLUDE_LINUX_OOM_H
2#define __INCLUDE_LINUX_OOM_H 2#define __INCLUDE_LINUX_OOM_H
3 3
4/* /proc/<pid>/oom_adj set to -17 protects from the oom-killer */ 4/*
5 * /proc/<pid>/oom_adj set to -17 protects from the oom-killer
6 */
5#define OOM_DISABLE (-17) 7#define OOM_DISABLE (-17)
6/* inclusive */ 8/* inclusive */
7#define OOM_ADJUST_MIN (-16) 9#define OOM_ADJUST_MIN (-16)
8#define OOM_ADJUST_MAX 15 10#define OOM_ADJUST_MAX 15
9 11
12/*
13 * /proc/<pid>/oom_score_adj set to OOM_SCORE_ADJ_MIN disables oom killing for
14 * pid.
15 */
16#define OOM_SCORE_ADJ_MIN (-1000)
17#define OOM_SCORE_ADJ_MAX 1000
18
10#ifdef __KERNEL__ 19#ifdef __KERNEL__
11 20
21#include <linux/sched.h>
12#include <linux/types.h> 22#include <linux/types.h>
13#include <linux/nodemask.h> 23#include <linux/nodemask.h>
14 24
@@ -27,6 +37,8 @@ enum oom_constraint {
27 CONSTRAINT_MEMCG, 37 CONSTRAINT_MEMCG,
28}; 38};
29 39
40extern unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *mem,
41 const nodemask_t *nodemask, unsigned long totalpages);
30extern int try_set_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_flags); 42extern int try_set_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_flags);
31extern void clear_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_flags); 43extern void clear_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_flags);
32 44
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 9591907c4f79..ce160d68f5e7 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -621,7 +621,8 @@ struct signal_struct {
621 struct tty_audit_buf *tty_audit_buf; 621 struct tty_audit_buf *tty_audit_buf;
622#endif 622#endif
623 623
624 int oom_adj; /* OOM kill score adjustment (bit shift) */ 624 int oom_adj; /* OOM kill score adjustment (bit shift) */
625 int oom_score_adj; /* OOM kill score adjustment */
625}; 626};
626 627
627/* Context switch must be unlocked if interrupts are to be enabled */ 628/* Context switch must be unlocked if interrupts are to be enabled */