diff mbox

[tip/core/rcu,03/15] rcu: Properly initialize ->boost_tasks on CPU offline

Message ID 1346352988-32444-3-git-send-email-paulmck@linux.vnet.ibm.com
State Accepted
Commit 1e3fd2b38cea41f5386bf23440f2cbdd74cf13d0
Headers show

Commit Message

Paul E. McKenney Aug. 30, 2012, 6:56 p.m. UTC
From: "Paul E. McKenney" <paul.mckenney@linaro.org>

When rcu_preempt_offline_tasks() clears tasks from a leaf rcu_node
structure, it does not NULL out the structure's ->boost_tasks field.
This commit therefore fixes this issue.

Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 kernel/rcutree_plugin.h |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

Comments

Josh Triplett Aug. 31, 2012, 5:56 p.m. UTC | #1
On Thu, Aug 30, 2012 at 11:56:16AM -0700, Paul E. McKenney wrote:
> From: "Paul E. McKenney" <paul.mckenney@linaro.org>
> 
> When rcu_preempt_offline_tasks() clears tasks from a leaf rcu_node
> structure, it does not NULL out the structure's ->boost_tasks field.
> This commit therefore fixes this issue.
> 
> Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org>
> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>

Reviewed-by: Josh Triplett <josh@joshtriplett.org>

> ---
>  kernel/rcutree_plugin.h |    7 ++++---
>  1 files changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
> index 7f3244c..b1b4851 100644
> --- a/kernel/rcutree_plugin.h
> +++ b/kernel/rcutree_plugin.h
> @@ -584,8 +584,11 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
>  		raw_spin_unlock(&rnp_root->lock); /* irqs still disabled */
>  	}
>  
> +	rnp->gp_tasks = NULL;
> +	rnp->exp_tasks = NULL;
>  #ifdef CONFIG_RCU_BOOST
> -	/* In case root is being boosted and leaf is not. */
> +	rnp->boost_tasks = NULL;
> +	/* In case root is being boosted and leaf was not. */
>  	raw_spin_lock(&rnp_root->lock); /* irqs already disabled */
>  	if (rnp_root->boost_tasks != NULL &&
>  	    rnp_root->boost_tasks != rnp_root->gp_tasks)
> @@ -593,8 +596,6 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
>  	raw_spin_unlock(&rnp_root->lock); /* irqs still disabled */
>  #endif /* #ifdef CONFIG_RCU_BOOST */
>  
> -	rnp->gp_tasks = NULL;
> -	rnp->exp_tasks = NULL;
>  	return retval;
>  }
>  
> -- 
> 1.7.8
>
Peter Zijlstra Sept. 6, 2012, 2:40 p.m. UTC | #2
On Thu, 2012-08-30 at 11:56 -0700, Paul E. McKenney wrote:
> When rcu_preempt_offline_tasks() clears tasks from a leaf rcu_node
> structure, it does not NULL out the structure's ->boost_tasks field.
> This commit therefore fixes this issue. 

What would have been the side-effects of this? Would rcu-boosting have
been able to go funny on hotplug, and if so, how?
Paul E. McKenney Sept. 6, 2012, 8:58 p.m. UTC | #3
On Thu, Sep 06, 2012 at 04:40:38PM +0200, Peter Zijlstra wrote:
> On Thu, 2012-08-30 at 11:56 -0700, Paul E. McKenney wrote:
> > When rcu_preempt_offline_tasks() clears tasks from a leaf rcu_node
> > structure, it does not NULL out the structure's ->boost_tasks field.
> > This commit therefore fixes this issue. 
> 
> What would have been the side-effects of this? Would rcu-boosting have
> been able to go funny on hotplug, and if so, how?

In some circumstances, this could prevent any future RCU boosting.
The ->boost_tasks field would be non-NULL, so it wouldn't ever try
boosting again, having been fooled into thinking that the previous
boost attempt was still in progress.

The expected segfault is prevented by the fact that an attempt to
initiate a boost first checks for ->boost_tasks being non-NULL,
and if so, declines to wake up the RCU-boost kthread.

							Thanx, Paul
diff mbox

Patch

diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index 7f3244c..b1b4851 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -584,8 +584,11 @@  static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
 		raw_spin_unlock(&rnp_root->lock); /* irqs still disabled */
 	}
 
+	rnp->gp_tasks = NULL;
+	rnp->exp_tasks = NULL;
 #ifdef CONFIG_RCU_BOOST
-	/* In case root is being boosted and leaf is not. */
+	rnp->boost_tasks = NULL;
+	/* In case root is being boosted and leaf was not. */
 	raw_spin_lock(&rnp_root->lock); /* irqs already disabled */
 	if (rnp_root->boost_tasks != NULL &&
 	    rnp_root->boost_tasks != rnp_root->gp_tasks)
@@ -593,8 +596,6 @@  static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
 	raw_spin_unlock(&rnp_root->lock); /* irqs still disabled */
 #endif /* #ifdef CONFIG_RCU_BOOST */
 
-	rnp->gp_tasks = NULL;
-	rnp->exp_tasks = NULL;
 	return retval;
 }