Skip to contentSkip to conversation

Fix more lockdep-RCU splats

PATCH In review Paul E. McKenney 2 participants 6 messages Jun 15, 2010 – Jun 16, 2010

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover Fix more lockdep-RCU splats

Hello!

Three patches to fix RCU-lockdep splats in wake_affine and idr_get_next().

Thanx, Paul

 b/kernel/sched_fair.c |    2 ++
 b/lib/idr.c           |    4 ++--
 kernel/sched_fair.c   |    2 +-
 3 files changed, 5 insertions(+), 3 deletions(-)
#1 lore raw

PATCH 1/3 rcu: fix lockdep splat in wake_affine()

From: Daniel J Blueman <[email protected]>

With 2.6.35-rc1 and your patch in the context below, we still see "include/linux/cgroup.h:534 invoked rcu_dereference_check() without protection!", so need this additional patch:

Acquire read-side RCU lock around task_group() calls, addressing "include/linux/cgroup.h:534 invoked rcu_dereference_check() without protection!" warning.

---
 kernel/sched_fair.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
kernel/sched_fair.c +2 -0
index eed35ed..ca56133 100644
@@ -1240,6 +1240,7 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync)
 	 * effect of the currently running task from the load
 	 * of the current CPU:
 	 */
+	rcu_read_lock();
 	if (sync) {
 		tg = task_group(current);
 		weight = current->se.load.weight;
@@ -1249,6 +1250,7 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync)
 	}
 
 	tg = task_group(p);
+	rcu_read_unlock();
 	weight = p->se.load.weight;
 
 	/*
Signature · 1 line
1.7.0.6
#2 lore raw

Re: [PATCH tip/core/urgent 1/3] rcu: fix lockdep splat in wake_affine()

Quoted 9 lines · Paul E. McKenney

From: Daniel J Blueman <[email protected]>

With 2.6.35-rc1 and your patch in the context below, we still see "include/linux/cgroup.h:534 invoked rcu_dereference_check() without protection!", so need this additional patch:

Acquire read-side RCU lock around task_group() calls, addressing "include/linux/cgroup.h:534 invoked rcu_dereference_check() without protection!" warning.

Uhm,. this is all just slapping in rcu_read_lock() to make the warning go away, without explanation of what and why.

Its not obvious what the races is, nor how its handled.

Quoted 26 lines
---
 kernel/sched_fair.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
kernel/sched_fair.c +2 -0
index eed35ed..ca56133 100644
@@ -1240,6 +1240,7 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync)
 	 * effect of the currently running task from the load
 	 * of the current CPU:
 	 */
+	rcu_read_lock();
 	if (sync) {
 		tg = task_group(current);
 		weight = current->se.load.weight;
@@ -1249,6 +1250,7 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync)
 	}
 
 	tg = task_group(p);
+	rcu_read_unlock();
 	weight = p->se.load.weight;
 
 	/*
#3 lore raw

Re: [PATCH tip/core/urgent 1/3] rcu: fix lockdep splat in wake_affine()

Quoted 7 lines · Peter Zijlstra
Quoted 6 lines · Paul E. McKenney

From: Daniel J Blueman <[email protected]>

With 2.6.35-rc1 and your patch in the context below, we still see "include/linux/cgroup.h:534 invoked rcu_dereference_check() without protection!", so need this additional patch:

Quoted 8 lines
Quoted 3 lines

Acquire read-side RCU lock around task_group() calls, addressing "include/linux/cgroup.h:534 invoked rcu_dereference_check() without protection!" warning.

Uhm,. this is all just slapping in rcu_read_lock() to make the warning go away, without explanation of what and why.

Its not obvious what the races is, nor how its handled.

Please let me know if my explanation in a recent email covers this. If so, I will add it to the commit log. If not, well, back to the drawing board, I guess. ;-)

Thanx, Paul

Quoted 28 lines
Quoted 26 lines
---
 kernel/sched_fair.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
kernel/sched_fair.c +2 -0
index eed35ed..ca56133 100644
@@ -1240,6 +1240,7 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync)
 	 * effect of the currently running task from the load
 	 * of the current CPU:
 	 */
+	rcu_read_lock();
 	if (sync) {
 		tg = task_group(current);
 		weight = current->se.load.weight;
@@ -1249,6 +1250,7 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync)
 	}
 
 	tg = task_group(p);
+	rcu_read_unlock();
 	weight = p->se.load.weight;
 
 	/*
#4 lore raw

PATCH 2/3 rcu: fix scope of wake_affine()'s new RCU read-side critical section

In reply to Paul E. McKenney

The RCU read-side critical section needs to cover all uses of the pointer returned by task_group().

---
 kernel/sched_fair.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
kernel/sched_fair.c +1 -1
index ca56133..a878b53 100644
@@ -1250,7 +1250,6 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync)
 	}
 
 	tg = task_group(p);
-	rcu_read_unlock();
 	weight = p->se.load.weight;
 
 	/*
@@ -1277,6 +1276,7 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync)
 		balanced = this_eff_load <= prev_eff_load;
 	} else
 		balanced = true;
+	rcu_read_unlock();
 
 	/*
 	 * If the currently running task will sleep within
Signature · 1 line
1.7.0.6
#5 lore raw

PATCH 3/3 idr: fix RCU lockdep splat in idr_get_next()

In reply to Paul E. McKenney

Convert to rcu_dereference_raw() given that many callers may have many different locking models.

---
 lib/idr.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
lib/idr.c +2 -2
index c1a2069..7f1a4f0 100644
@@ -602,7 +602,7 @@ void *idr_get_next(struct idr *idp, int *nextidp)
 	/* find first ent */
 	n = idp->layers * IDR_BITS;
 	max = 1 << n;
-	p = rcu_dereference(idp->top);
+	p = rcu_dereference_raw(idp->top);
 	if (!p)
 		return NULL;
 
@@ -610,7 +610,7 @@ void *idr_get_next(struct idr *idp, int *nextidp)
 		while (n > 0 && p) {
 			n -= IDR_BITS;
 			*paa++ = p;
-			p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]);
+			p = rcu_dereference_raw(p->ary[(id >> n) & IDR_MASK]);
 		}
 
 		if (p) {
Signature · 1 line
1.7.0.6