|
@@ -25,6 +25,7 @@
|
|
|
#include <linux/cpuset.h>
|
|
|
#include <linux/module.h>
|
|
|
#include <linux/notifier.h>
|
|
|
+#include <linux/memcontrol.h>
|
|
|
|
|
|
int sysctl_panic_on_oom;
|
|
|
int sysctl_oom_kill_allocating_task;
|
|
@@ -50,7 +51,8 @@ static DEFINE_SPINLOCK(zone_scan_mutex);
|
|
|
* of least surprise ... (be careful when you change it)
|
|
|
*/
|
|
|
|
|
|
-unsigned long badness(struct task_struct *p, unsigned long uptime)
|
|
|
+unsigned long badness(struct task_struct *p, unsigned long uptime,
|
|
|
+ struct mem_cgroup *mem)
|
|
|
{
|
|
|
unsigned long points, cpu_time, run_time, s;
|
|
|
struct mm_struct *mm;
|
|
@@ -63,6 +65,13 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_CGROUP_MEM_CONT
|
|
|
+ if (mem != NULL && mm->mem_cgroup != mem) {
|
|
|
+ task_unlock(p);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
/*
|
|
|
* The memory size of the process is the basis for the badness.
|
|
|
*/
|
|
@@ -193,7 +202,8 @@ static inline enum oom_constraint constrained_alloc(struct zonelist *zonelist,
|
|
|
*
|
|
|
* (not docbooked, we don't want this one cluttering up the manual)
|
|
|
*/
|
|
|
-static struct task_struct *select_bad_process(unsigned long *ppoints)
|
|
|
+static struct task_struct *select_bad_process(unsigned long *ppoints,
|
|
|
+ struct mem_cgroup *mem)
|
|
|
{
|
|
|
struct task_struct *g, *p;
|
|
|
struct task_struct *chosen = NULL;
|
|
@@ -247,7 +257,7 @@ static struct task_struct *select_bad_process(unsigned long *ppoints)
|
|
|
if (p->oomkilladj == OOM_DISABLE)
|
|
|
continue;
|
|
|
|
|
|
- points = badness(p, uptime.tv_sec);
|
|
|
+ points = badness(p, uptime.tv_sec, mem);
|
|
|
if (points > *ppoints || !chosen) {
|
|
|
chosen = p;
|
|
|
*ppoints = points;
|
|
@@ -368,6 +378,31 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
|
|
|
return oom_kill_task(p);
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_CGROUP_MEM_CONT
|
|
|
+void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask)
|
|
|
+{
|
|
|
+ unsigned long points = 0;
|
|
|
+ struct task_struct *p;
|
|
|
+
|
|
|
+ cgroup_lock();
|
|
|
+ rcu_read_lock();
|
|
|
+retry:
|
|
|
+ p = select_bad_process(&points, mem);
|
|
|
+ if (PTR_ERR(p) == -1UL)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ if (!p)
|
|
|
+ p = current;
|
|
|
+
|
|
|
+ if (oom_kill_process(p, gfp_mask, 0, points,
|
|
|
+ "Memory cgroup out of memory"))
|
|
|
+ goto retry;
|
|
|
+out:
|
|
|
+ rcu_read_unlock();
|
|
|
+ cgroup_unlock();
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
static BLOCKING_NOTIFIER_HEAD(oom_notify_list);
|
|
|
|
|
|
int register_oom_notifier(struct notifier_block *nb)
|
|
@@ -484,7 +519,7 @@ retry:
|
|
|
* Rambo mode: Shoot down a process and hope it solves whatever
|
|
|
* issues we may have.
|
|
|
*/
|
|
|
- p = select_bad_process(&points);
|
|
|
+ p = select_bad_process(&points, NULL);
|
|
|
|
|
|
if (PTR_ERR(p) == -1UL)
|
|
|
goto out;
|