Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5fe1d75f authored by Oleg Nesterov's avatar Oleg Nesterov Committed by Linus Torvalds
Browse files

[PATCH] do_sched_setscheduler(): don't take tasklist_lock



Use rcu locks instead. sched_setscheduler() now takes ->siglock
before reading ->signal->rlim[].

Signed-off-by: default avatarOleg Nesterov <oleg@tv-sign.ru>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent c9472e0f
Loading
Loading
Loading
Loading
+18 −10
Original line number Diff line number Diff line
@@ -4080,6 +4080,8 @@ static void __setscheduler(struct task_struct *p, int policy, int prio)
 * @p: the task in question.
 * @policy: new policy.
 * @param: structure containing the new RT priority.
 *
 * NOTE: the task may be already dead
 */
int sched_setscheduler(struct task_struct *p, int policy,
		       struct sched_param *param)
@@ -4115,19 +4117,26 @@ int sched_setscheduler(struct task_struct *p, int policy,
	 * Allow unprivileged RT tasks to decrease priority:
	 */
	if (!capable(CAP_SYS_NICE)) {
		unsigned long rlim_rtprio;
		unsigned long flags;

		if (!lock_task_sighand(p, &flags))
			return -ESRCH;
		rlim_rtprio = p->signal->rlim[RLIMIT_RTPRIO].rlim_cur;
		unlock_task_sighand(p, &flags);

		/*
		 * can't change policy, except between SCHED_NORMAL
		 * and SCHED_BATCH:
		 */
		if (((policy != SCHED_NORMAL && p->policy != SCHED_BATCH) &&
			(policy != SCHED_BATCH && p->policy != SCHED_NORMAL)) &&
				!p->signal->rlim[RLIMIT_RTPRIO].rlim_cur)
				!rlim_rtprio)
			return -EPERM;
		/* can't increase priority */
		if ((policy != SCHED_NORMAL && policy != SCHED_BATCH) &&
		    param->sched_priority > p->rt_priority &&
		    param->sched_priority >
				p->signal->rlim[RLIMIT_RTPRIO].rlim_cur)
		    param->sched_priority > rlim_rtprio)
			return -EPERM;
		/* can't change other user's priorities */
		if ((current->euid != p->euid) &&
@@ -4193,14 +4202,13 @@ do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param)
		return -EINVAL;
	if (copy_from_user(&lparam, param, sizeof(struct sched_param)))
		return -EFAULT;
	read_lock_irq(&tasklist_lock);

	rcu_read_lock();
	retval = -ESRCH;
	p = find_process_by_pid(pid);
	if (!p) {
		read_unlock_irq(&tasklist_lock);
		return -ESRCH;
	}
	if (p != NULL)
		retval = sched_setscheduler(p, policy, &lparam);
	read_unlock_irq(&tasklist_lock);
	rcu_read_unlock();

	return retval;
}