diff options
| author | Olof Johansson <olof@lixom.net> | 2012-11-25 21:34:34 -0800 | 
|---|---|---|
| committer | Olof Johansson <olof@lixom.net> | 2012-11-25 21:34:34 -0800 | 
| commit | 0f9cb211ba5db93d488fe6b154138231fdd0e22d (patch) | |
| tree | 293871b042e9ebc49b1d783f1b110eef541ddc97 /fs/proc/base.c | |
| parent | 007108a2279123ad6639b6c653ad1a731febb60f (diff) | |
| parent | 9489e9dcae718d5fde988e4a684a0f55b5f94d17 (diff) | |
| download | olio-linux-3.10-0f9cb211ba5db93d488fe6b154138231fdd0e22d.tar.xz olio-linux-3.10-0f9cb211ba5db93d488fe6b154138231fdd0e22d.zip  | |
Merge tag 'v3.7-rc7' into next/cleanup
Merging in mainline back to next/cleanup since it has collected a few
conflicts between fixes going upstream and some of the cleanup patches.
Git doesn't auto-resolve some of them, and they're mostly noise so let's
take care of it locally.
Conflicts are in:
	arch/arm/mach-omap2/omap_hwmod_44xx_data.c
	arch/arm/plat-omap/i2c.c
	drivers/video/omap2/dss/dss.c
Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'fs/proc/base.c')
| -rw-r--r-- | fs/proc/base.c | 109 | 
1 files changed, 109 insertions, 0 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 144a96732dd..3c231adf845 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -873,6 +873,113 @@ static const struct file_operations proc_environ_operations = {  	.release	= mem_release,  }; +static ssize_t oom_adj_read(struct file *file, char __user *buf, size_t count, +			    loff_t *ppos) +{ +	struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); +	char buffer[PROC_NUMBUF]; +	int oom_adj = OOM_ADJUST_MIN; +	size_t len; +	unsigned long flags; + +	if (!task) +		return -ESRCH; +	if (lock_task_sighand(task, &flags)) { +		if (task->signal->oom_score_adj == OOM_SCORE_ADJ_MAX) +			oom_adj = OOM_ADJUST_MAX; +		else +			oom_adj = (task->signal->oom_score_adj * -OOM_DISABLE) / +				  OOM_SCORE_ADJ_MAX; +		unlock_task_sighand(task, &flags); +	} +	put_task_struct(task); +	len = snprintf(buffer, sizeof(buffer), "%d\n", oom_adj); +	return simple_read_from_buffer(buf, count, ppos, buffer, len); +} + +static ssize_t oom_adj_write(struct file *file, const char __user *buf, +			     size_t count, loff_t *ppos) +{ +	struct task_struct *task; +	char buffer[PROC_NUMBUF]; +	int oom_adj; +	unsigned long flags; +	int err; + +	memset(buffer, 0, sizeof(buffer)); +	if (count > sizeof(buffer) - 1) +		count = sizeof(buffer) - 1; +	if (copy_from_user(buffer, buf, count)) { +		err = -EFAULT; +		goto out; +	} + +	err = kstrtoint(strstrip(buffer), 0, &oom_adj); +	if (err) +		goto out; +	if ((oom_adj < OOM_ADJUST_MIN || oom_adj > OOM_ADJUST_MAX) && +	     oom_adj != OOM_DISABLE) { +		err = -EINVAL; +		goto out; +	} + +	task = get_proc_task(file->f_path.dentry->d_inode); +	if (!task) { +		err = -ESRCH; +		goto out; +	} + +	task_lock(task); +	if (!task->mm) { +		err = -EINVAL; +		goto err_task_lock; +	} + +	if (!lock_task_sighand(task, &flags)) { +		err = -ESRCH; +		goto err_task_lock; +	} + +	/* +	 * Scale /proc/pid/oom_score_adj appropriately ensuring that a maximum +	 * value is always attainable. +	 */ +	if (oom_adj == OOM_ADJUST_MAX) +		oom_adj = OOM_SCORE_ADJ_MAX; +	else +		oom_adj = (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE; + +	if (oom_adj < task->signal->oom_score_adj && +	    !capable(CAP_SYS_RESOURCE)) { +		err = -EACCES; +		goto err_sighand; +	} + +	/* +	 * /proc/pid/oom_adj is provided for legacy purposes, ask users to use +	 * /proc/pid/oom_score_adj instead. +	 */ +	printk_once(KERN_WARNING "%s (%d): /proc/%d/oom_adj is deprecated, please use /proc/%d/oom_score_adj instead.\n", +		  current->comm, task_pid_nr(current), task_pid_nr(task), +		  task_pid_nr(task)); + +	task->signal->oom_score_adj = oom_adj; +	trace_oom_score_adj_update(task); +err_sighand: +	unlock_task_sighand(task, &flags); +err_task_lock: +	task_unlock(task); +	put_task_struct(task); +out: +	return err < 0 ? err : count; +} + +static const struct file_operations proc_oom_adj_operations = { +	.read		= oom_adj_read, +	.write		= oom_adj_write, +	.llseek		= generic_file_llseek, +}; +  static ssize_t oom_score_adj_read(struct file *file, char __user *buf,  					size_t count, loff_t *ppos)  { @@ -2598,6 +2705,7 @@ static const struct pid_entry tgid_base_stuff[] = {  	REG("cgroup",  S_IRUGO, proc_cgroup_operations),  #endif  	INF("oom_score",  S_IRUGO, proc_oom_score), +	REG("oom_adj",    S_IRUGO|S_IWUSR, proc_oom_adj_operations),  	REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),  #ifdef CONFIG_AUDITSYSCALL  	REG("loginuid",   S_IWUSR|S_IRUGO, proc_loginuid_operations), @@ -2964,6 +3072,7 @@ static const struct pid_entry tid_base_stuff[] = {  	REG("cgroup",  S_IRUGO, proc_cgroup_operations),  #endif  	INF("oom_score", S_IRUGO, proc_oom_score), +	REG("oom_adj",   S_IRUGO|S_IWUSR, proc_oom_adj_operations),  	REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),  #ifdef CONFIG_AUDITSYSCALL  	REG("loginuid",  S_IWUSR|S_IRUGO, proc_loginuid_operations),  |