diff options
author | Peter Zijlstra <peterz@infradead.org> | 2012-06-22 13:36:05 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-10-02 10:30:35 -0700 |
commit | e194fab8d7ebe95db5609f1cb6794c2afcc3118f (patch) | |
tree | 2367f196d1cfa94a2078834bee0d4a64734eb884 /include/linux/sched.h | |
parent | 6418cc471b5d8a64ce22d2aa827fcb275e61449c (diff) | |
download | lwn-e194fab8d7ebe95db5609f1cb6794c2afcc3118f.tar.gz lwn-e194fab8d7ebe95db5609f1cb6794c2afcc3118f.zip |
sched: Fix race in task_group()
commit 8323f26ce3425460769605a6aece7a174edaa7d1 upstream.
Stefan reported a crash on a kernel before a3e5d1091c1 ("sched:
Don't call task_group() too many times in set_task_rq()"), he
found the reason to be that the multiple task_group()
invocations in set_task_rq() returned different values.
Looking at all that I found a lack of serialization and plain
wrong comments.
The below tries to fix it using an extra pointer which is
updated under the appropriate scheduler locks. Its not pretty,
but I can't really see another way given how all the cgroup
stuff works.
Reported-and-tested-by: Stefan Bader <stefan.bader@canonical.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1340364965.18025.71.camel@twins
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'include/linux/sched.h')
-rw-r--r-- | include/linux/sched.h | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h index 7b06169d7241..48241aa976c8 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1279,6 +1279,9 @@ struct task_struct { const struct sched_class *sched_class; struct sched_entity se; struct sched_rt_entity rt; +#ifdef CONFIG_CGROUP_SCHED + struct task_group *sched_task_group; +#endif #ifdef CONFIG_PREEMPT_NOTIFIERS /* list of struct preempt_notifier: */ @@ -2744,7 +2747,7 @@ extern int sched_group_set_rt_period(struct task_group *tg, extern long sched_group_rt_period(struct task_group *tg); extern int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk); #endif -#endif +#endif /* CONFIG_CGROUP_SCHED */ extern int task_can_switch_user(struct user_struct *up, struct task_struct *tsk); |