Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 156926
b: refs/heads/master
c: 0753ba0
h: refs/heads/master
v: v3
  • Loading branch information
KOSAKI Motohiro authored and Linus Torvalds committed Aug 18, 2009
1 parent 7c3e9cc commit 9b8f733
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 55 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 89a4eb4b66e8f4d395e14a14d262dac4d6ca52f0
refs/heads/master: 0753ba01e126020bf0f8150934903b48935b697d
15 changes: 5 additions & 10 deletions trunk/Documentation/filesystems/proc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1167,13 +1167,11 @@ CHAPTER 3: PER-PROCESS PARAMETERS
3.1 /proc/<pid>/oom_adj - Adjust the oom-killer score
------------------------------------------------------

This file can be used to adjust the score used to select which processes should
be killed in an out-of-memory situation. The oom_adj value is a characteristic
of the task's mm, so all threads that share an mm with pid will have the same
oom_adj value. A high value will increase the likelihood of this process being
killed by the oom-killer. Valid values are in the range -16 to +15 as
explained below and a special value of -17, which disables oom-killing
altogether for threads sharing pid's mm.
This file can be used to adjust the score used to select which processes
should be killed in an out-of-memory situation. Giving it a high score will
increase the likelihood of this process being killed by the oom-killer. Valid
values are in the range -16 to +15, plus the special value -17, which disables
oom-killing altogether for this process.

The process to be killed in an out-of-memory situation is selected among all others
based on its badness score. This value equals the original memory size of the process
Expand All @@ -1187,9 +1185,6 @@ the parent's score if they do not share the same memory. Thus forking servers
are the prime candidates to be killed. Having only one 'hungry' child will make
parent less preferable than the child.

/proc/<pid>/oom_adj cannot be changed for kthreads since they are immune from
oom-killing already.

/proc/<pid>/oom_score shows process' current badness score.

The following heuristics are then applied:
Expand Down
19 changes: 3 additions & 16 deletions trunk/fs/proc/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -1003,12 +1003,7 @@ static ssize_t oom_adjust_read(struct file *file, char __user *buf,

if (!task)
return -ESRCH;
task_lock(task);
if (task->mm)
oom_adjust = task->mm->oom_adj;
else
oom_adjust = OOM_DISABLE;
task_unlock(task);
oom_adjust = task->oomkilladj;
put_task_struct(task);

len = snprintf(buffer, sizeof(buffer), "%i\n", oom_adjust);
Expand Down Expand Up @@ -1037,19 +1032,11 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
task = get_proc_task(file->f_path.dentry->d_inode);
if (!task)
return -ESRCH;
task_lock(task);
if (!task->mm) {
task_unlock(task);
put_task_struct(task);
return -EINVAL;
}
if (oom_adjust < task->mm->oom_adj && !capable(CAP_SYS_RESOURCE)) {
task_unlock(task);
if (oom_adjust < task->oomkilladj && !capable(CAP_SYS_RESOURCE)) {
put_task_struct(task);
return -EACCES;
}
task->mm->oom_adj = oom_adjust;
task_unlock(task);
task->oomkilladj = oom_adjust;
put_task_struct(task);
if (end - buffer == 0)
return -EIO;
Expand Down
2 changes: 0 additions & 2 deletions trunk/include/linux/mm_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,6 @@ struct mm_struct {

unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */

s8 oom_adj; /* OOM kill score adjustment (bit shift) */

cpumask_t cpu_vm_mask;

/* Architecture-specific MM context */
Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -1198,6 +1198,7 @@ struct task_struct {
* a short time
*/
unsigned char fpu_counter;
s8 oomkilladj; /* OOM kill score adjustment (bit shift). */
#ifdef CONFIG_BLK_DEV_IO_TRACE
unsigned int btrace_seq;
#endif
Expand Down
1 change: 0 additions & 1 deletion trunk/kernel/fork.c
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,6 @@ static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p)
init_rwsem(&mm->mmap_sem);
INIT_LIST_HEAD(&mm->mmlist);
mm->flags = (current->mm) ? current->mm->flags : default_dump_filter;
mm->oom_adj = (current->mm) ? current->mm->oom_adj : 0;
mm->core_state = NULL;
mm->nr_ptes = 0;
set_mm_counter(mm, file_rss, 0);
Expand Down
64 changes: 39 additions & 25 deletions trunk/mm/oom_kill.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,13 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
unsigned long points, cpu_time, run_time;
struct mm_struct *mm;
struct task_struct *child;
int oom_adj;

task_lock(p);
mm = p->mm;
if (!mm) {
task_unlock(p);
return 0;
}
oom_adj = mm->oom_adj;
if (oom_adj == OOM_DISABLE) {
task_unlock(p);
return 0;
}

/*
* The memory size of the process is the basis for the badness.
Expand Down Expand Up @@ -154,15 +148,15 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
points /= 8;

/*
* Adjust the score by oom_adj.
* Adjust the score by oomkilladj.
*/
if (oom_adj) {
if (oom_adj > 0) {
if (p->oomkilladj) {
if (p->oomkilladj > 0) {
if (!points)
points = 1;
points <<= oom_adj;
points <<= p->oomkilladj;
} else
points >>= -(oom_adj);
points >>= -(p->oomkilladj);
}

#ifdef DEBUG
Expand Down Expand Up @@ -257,8 +251,11 @@ static struct task_struct *select_bad_process(unsigned long *ppoints,
*ppoints = ULONG_MAX;
}

if (p->oomkilladj == OOM_DISABLE)
continue;

points = badness(p, uptime.tv_sec);
if (points > *ppoints) {
if (points > *ppoints || !chosen) {
chosen = p;
*ppoints = points;
}
Expand Down Expand Up @@ -307,7 +304,8 @@ static void dump_tasks(const struct mem_cgroup *mem)
}
printk(KERN_INFO "[%5d] %5d %5d %8lu %8lu %3d %3d %s\n",
p->pid, __task_cred(p)->uid, p->tgid, mm->total_vm,
get_mm_rss(mm), (int)task_cpu(p), mm->oom_adj, p->comm);
get_mm_rss(mm), (int)task_cpu(p), p->oomkilladj,
p->comm);
task_unlock(p);
} while_each_thread(g, p);
}
Expand All @@ -325,8 +323,11 @@ static void __oom_kill_task(struct task_struct *p, int verbose)
return;
}

if (!p->mm)
if (!p->mm) {
WARN_ON(1);
printk(KERN_WARNING "tried to kill an mm-less task!\n");
return;
}

if (verbose)
printk(KERN_ERR "Killed process %d (%s)\n",
Expand All @@ -348,13 +349,28 @@ static int oom_kill_task(struct task_struct *p)
struct mm_struct *mm;
struct task_struct *g, *q;

task_lock(p);
mm = p->mm;
if (!mm || mm->oom_adj == OOM_DISABLE) {
task_unlock(p);

/* WARNING: mm may not be dereferenced since we did not obtain its
* value from get_task_mm(p). This is OK since all we need to do is
* compare mm to q->mm below.
*
* Furthermore, even if mm contains a non-NULL value, p->mm may
* change to NULL at any time since we do not hold task_lock(p).
* However, this is of no concern to us.
*/

if (mm == NULL)
return 1;
}
task_unlock(p);

/*
* Don't kill the process if any threads are set to OOM_DISABLE
*/
do_each_thread(g, q) {
if (q->mm == mm && q->oomkilladj == OOM_DISABLE)
return 1;
} while_each_thread(g, q);

__oom_kill_task(p, 1);

/*
Expand All @@ -377,11 +393,10 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
struct task_struct *c;

if (printk_ratelimit()) {
task_lock(current);
printk(KERN_WARNING "%s invoked oom-killer: "
"gfp_mask=0x%x, order=%d, oom_adj=%d\n",
current->comm, gfp_mask, order,
current->mm ? current->mm->oom_adj : OOM_DISABLE);
"gfp_mask=0x%x, order=%d, oomkilladj=%d\n",
current->comm, gfp_mask, order, current->oomkilladj);
task_lock(current);
cpuset_print_task_mems_allowed(current);
task_unlock(current);
dump_stack();
Expand All @@ -394,9 +409,8 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
/*
* If the task is already exiting, don't alarm the sysadmin or kill
* its children or threads, just set TIF_MEMDIE so it can die quickly
* if its mm is still attached.
*/
if (p->mm && (p->flags & PF_EXITING)) {
if (p->flags & PF_EXITING) {
__oom_kill_task(p, 0);
return 0;
}
Expand Down

0 comments on commit 9b8f733

Please sign in to comment.