From 723548bff1dde9ab6bdb23f4bb92277c4da49473 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Tue, 26 Oct 2010 14:21:25 -0700 Subject: oom: rewrite error handling for oom_adj and oom_score_adj tunables It's better to use proper error handling in oom_adjust_write() and oom_score_adj_write() instead of duplicating the locking order on various exit paths. Suggested-by: Andrew Morton Signed-off-by: David Rientjes Cc: KAMEZAWA Hiroyuki Cc: KOSAKI Motohiro Cc: Rik van Riel Cc: Ying Han Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/fs/proc/base.c b/fs/proc/base.c index 6e50c8e..34d11ac 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1023,36 +1023,39 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, memset(buffer, 0, sizeof(buffer)); if (count > sizeof(buffer) - 1) count = sizeof(buffer) - 1; - if (copy_from_user(buffer, buf, count)) - return -EFAULT; + if (copy_from_user(buffer, buf, count)) { + err = -EFAULT; + goto out; + } err = strict_strtol(strstrip(buffer), 0, &oom_adjust); if (err) - return -EINVAL; + goto out; if ((oom_adjust < OOM_ADJUST_MIN || oom_adjust > OOM_ADJUST_MAX) && - oom_adjust != OOM_DISABLE) - return -EINVAL; + oom_adjust != OOM_DISABLE) { + err = -EINVAL; + goto out; + } task = get_proc_task(file->f_path.dentry->d_inode); - if (!task) - return -ESRCH; + if (!task) { + err = -ESRCH; + goto out; + } if (!lock_task_sighand(task, &flags)) { - put_task_struct(task); - return -ESRCH; + err = -ESRCH; + goto err_task_struct; } if (oom_adjust < task->signal->oom_adj && !capable(CAP_SYS_RESOURCE)) { - unlock_task_sighand(task, &flags); - put_task_struct(task); - return -EACCES; + err = -EACCES; + goto err_sighand; } task_lock(task); if (!task->mm) { - task_unlock(task); - unlock_task_sighand(task, &flags); - put_task_struct(task); - return -EINVAL; + err = -EINVAL; + goto err_task_lock; } if (oom_adjust != task->signal->oom_adj) { @@ -1080,11 +1083,14 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, else task->signal->oom_score_adj = (oom_adjust * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE; +err_task_lock: task_unlock(task); +err_sighand: unlock_task_sighand(task, &flags); +err_task_struct: put_task_struct(task); - - return count; +out: + return err < 0 ? err : count; } static const struct file_operations proc_oom_adjust_operations = { @@ -1125,36 +1131,39 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf, memset(buffer, 0, sizeof(buffer)); if (count > sizeof(buffer) - 1) count = sizeof(buffer) - 1; - if (copy_from_user(buffer, buf, count)) - return -EFAULT; + if (copy_from_user(buffer, buf, count)) { + err = -EFAULT; + goto out; + } err = strict_strtol(strstrip(buffer), 0, &oom_score_adj); if (err) - return -EINVAL; + goto out; if (oom_score_adj < OOM_SCORE_ADJ_MIN || - oom_score_adj > OOM_SCORE_ADJ_MAX) - return -EINVAL; + oom_score_adj > OOM_SCORE_ADJ_MAX) { + err = -EINVAL; + goto out; + } task = get_proc_task(file->f_path.dentry->d_inode); - if (!task) - return -ESRCH; + if (!task) { + err = -ESRCH; + goto out; + } if (!lock_task_sighand(task, &flags)) { - put_task_struct(task); - return -ESRCH; + err = -ESRCH; + goto err_task_struct; } if (oom_score_adj < task->signal->oom_score_adj && !capable(CAP_SYS_RESOURCE)) { - unlock_task_sighand(task, &flags); - put_task_struct(task); - return -EACCES; + err = -EACCES; + goto err_sighand; } task_lock(task); if (!task->mm) { - task_unlock(task); - unlock_task_sighand(task, &flags); - put_task_struct(task); - return -EINVAL; + err = -EINVAL; + goto err_task_lock; } if (oom_score_adj != task->signal->oom_score_adj) { if (oom_score_adj == OOM_SCORE_ADJ_MIN) @@ -1172,10 +1181,14 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf, else task->signal->oom_adj = (oom_score_adj * OOM_ADJUST_MAX) / OOM_SCORE_ADJ_MAX; +err_task_lock: task_unlock(task); +err_sighand: unlock_task_sighand(task, &flags); +err_task_struct: put_task_struct(task); - return count; +out: + return err < 0 ? err : count; } static const struct file_operations proc_oom_score_adj_operations = { -- cgit v0.10.2