aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-04 18:15:43 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-04 18:15:43 -0400
commitf2809d61d6cf47c2ed2963ba3b4c59e709144ccb (patch)
tree4cfc2aadc16b52ef4562833ea838b34723e6b3fb /kernel
parentd93ac51c7a129db7a1431d859a3ef45a0b1f3fc5 (diff)
parent8b46f880841aac821af8efa6581bb0e46b8b9845 (diff)
Merge branch 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: rcu: Fix RCU lockdep splat on freezer_fork path rcu: Fix RCU lockdep splat in set_task_cpu on fork path mutex: Don't spin when the owner CPU is offline or other weird cases
Diffstat (limited to 'kernel')
-rw-r--r--kernel/cgroup_freezer.c5
-rw-r--r--kernel/sched.c18
2 files changed, 18 insertions, 5 deletions
diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c
index da5e13975531..e5c0244962b0 100644
--- a/kernel/cgroup_freezer.c
+++ b/kernel/cgroup_freezer.c
@@ -205,9 +205,12 @@ static void freezer_fork(struct cgroup_subsys *ss, struct task_struct *task)
205 * No lock is needed, since the task isn't on tasklist yet, 205 * No lock is needed, since the task isn't on tasklist yet,
206 * so it can't be moved to another cgroup, which means the 206 * so it can't be moved to another cgroup, which means the
207 * freezer won't be removed and will be valid during this 207 * freezer won't be removed and will be valid during this
208 * function call. 208 * function call. Nevertheless, apply RCU read-side critical
209 * section to suppress RCU lockdep false positives.
209 */ 210 */
211 rcu_read_lock();
210 freezer = task_freezer(task); 212 freezer = task_freezer(task);
213 rcu_read_unlock();
211 214
212 /* 215 /*
213 * The root cgroup is non-freezable, so we can skip the 216 * The root cgroup is non-freezable, so we can skip the
diff --git a/kernel/sched.c b/kernel/sched.c
index 6af210a7de70..3c2a54f70ffe 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -323,6 +323,15 @@ static inline struct task_group *task_group(struct task_struct *p)
323/* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */ 323/* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */
324static inline void set_task_rq(struct task_struct *p, unsigned int cpu) 324static inline void set_task_rq(struct task_struct *p, unsigned int cpu)
325{ 325{
326 /*
327 * Strictly speaking this rcu_read_lock() is not needed since the
328 * task_group is tied to the cgroup, which in turn can never go away
329 * as long as there are tasks attached to it.
330 *
331 * However since task_group() uses task_subsys_state() which is an
332 * rcu_dereference() user, this quiets CONFIG_PROVE_RCU.
333 */
334 rcu_read_lock();
326#ifdef CONFIG_FAIR_GROUP_SCHED 335#ifdef CONFIG_FAIR_GROUP_SCHED
327 p->se.cfs_rq = task_group(p)->cfs_rq[cpu]; 336 p->se.cfs_rq = task_group(p)->cfs_rq[cpu];
328 p->se.parent = task_group(p)->se[cpu]; 337 p->se.parent = task_group(p)->se[cpu];
@@ -332,6 +341,7 @@ static inline void set_task_rq(struct task_struct *p, unsigned int cpu)
332 p->rt.rt_rq = task_group(p)->rt_rq[cpu]; 341 p->rt.rt_rq = task_group(p)->rt_rq[cpu];
333 p->rt.parent = task_group(p)->rt_se[cpu]; 342 p->rt.parent = task_group(p)->rt_se[cpu];
334#endif 343#endif
344 rcu_read_unlock();
335} 345}
336 346
337#else 347#else
@@ -3780,7 +3790,7 @@ int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner)
3780 * the mutex owner just released it and exited. 3790 * the mutex owner just released it and exited.
3781 */ 3791 */
3782 if (probe_kernel_address(&owner->cpu, cpu)) 3792 if (probe_kernel_address(&owner->cpu, cpu))
3783 goto out; 3793 return 0;
3784#else 3794#else
3785 cpu = owner->cpu; 3795 cpu = owner->cpu;
3786#endif 3796#endif
@@ -3790,14 +3800,14 @@ int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner)
3790 * the cpu field may no longer be valid. 3800 * the cpu field may no longer be valid.
3791 */ 3801 */
3792 if (cpu >= nr_cpumask_bits) 3802 if (cpu >= nr_cpumask_bits)
3793 goto out; 3803 return 0;
3794 3804
3795 /* 3805 /*
3796 * We need to validate that we can do a 3806 * We need to validate that we can do a
3797 * get_cpu() and that we have the percpu area. 3807 * get_cpu() and that we have the percpu area.
3798 */ 3808 */
3799 if (!cpu_online(cpu)) 3809 if (!cpu_online(cpu))
3800 goto out; 3810 return 0;
3801 3811
3802 rq = cpu_rq(cpu); 3812 rq = cpu_rq(cpu);
3803 3813
@@ -3816,7 +3826,7 @@ int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner)
3816 3826
3817 cpu_relax(); 3827 cpu_relax();
3818 } 3828 }
3819out: 3829
3820 return 1; 3830 return 1;
3821} 3831}
3822#endif 3832#endif