diff options
author | Peter Zijlstra <peterz@infradead.org> | 2012-06-22 07:36:05 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-07-24 07:58:20 -0400 |
commit | 8323f26ce3425460769605a6aece7a174edaa7d1 (patch) | |
tree | 44daa0dafa49cedc9301efd1417c6c2ac338c1c7 /include/linux/sched.h | |
parent | 88b8dac0a14c511ff41486b83a8c3d688936eec0 (diff) |
sched: Fix race in task_group()
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>
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 bc9952991710..fd9436a3a545 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1245,6 +1245,9 @@ struct task_struct { | |||
1245 | const struct sched_class *sched_class; | 1245 | const struct sched_class *sched_class; |
1246 | struct sched_entity se; | 1246 | struct sched_entity se; |
1247 | struct sched_rt_entity rt; | 1247 | struct sched_rt_entity rt; |
1248 | #ifdef CONFIG_CGROUP_SCHED | ||
1249 | struct task_group *sched_task_group; | ||
1250 | #endif | ||
1248 | 1251 | ||
1249 | #ifdef CONFIG_PREEMPT_NOTIFIERS | 1252 | #ifdef CONFIG_PREEMPT_NOTIFIERS |
1250 | /* list of struct preempt_notifier: */ | 1253 | /* list of struct preempt_notifier: */ |
@@ -2724,7 +2727,7 @@ extern int sched_group_set_rt_period(struct task_group *tg, | |||
2724 | extern long sched_group_rt_period(struct task_group *tg); | 2727 | extern long sched_group_rt_period(struct task_group *tg); |
2725 | extern int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk); | 2728 | extern int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk); |
2726 | #endif | 2729 | #endif |
2727 | #endif | 2730 | #endif /* CONFIG_CGROUP_SCHED */ |
2728 | 2731 | ||
2729 | extern int task_can_switch_user(struct user_struct *up, | 2732 | extern int task_can_switch_user(struct user_struct *up, |
2730 | struct task_struct *tsk); | 2733 | struct task_struct *tsk); |