aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLai Jiangshan <laijs@cn.fujitsu.com>2014-11-18 03:30:01 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2015-01-06 14:02:52 -0500
commitabaf3f9d275b8d856ae5e47531e40c0bfeac012b (patch)
tree017561fdbffe2f3e840d6af7c5a7bbcf015c70c9
parent3ba4d0e09bf965297e97adf195e0ea246cfe5c74 (diff)
rcu: Revert "Allow post-unlock reference for rt_mutex" to avoid priority-inversion
The patch dfeb9765ce3c ("Allow post-unlock reference for rt_mutex") ensured rcu-boost safe even the rt_mutex has post-unlock reference. But rt_mutex allowing post-unlock reference is definitely a bug and it was fixed by the commit 27e35715df54 ("rtmutex: Plug slow unlock race"). This fix made the previous patch (dfeb9765ce3c) useless. And even worse, the priority-inversion introduced by the the previous patch still exists. rcu_read_unlock_special() { rt_mutex_unlock(&rnp->boost_mtx); /* Priority-Inversion: * the current task had been deboosted and preempted as a low * priority task immediately, it could wait long before reschedule in, * and the rcu-booster also waits on this low priority task and sleeps. * This priority-inversion makes rcu-booster can't work * as expected. */ complete(&rnp->boost_completion); } Just revert the patch to avoid it. Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-rw-r--r--kernel/rcu/tree.h5
-rw-r--r--kernel/rcu/tree_plugin.h8
2 files changed, 1 insertions, 12 deletions
diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h
index 883ebc8e2b6e..95356477d560 100644
--- a/kernel/rcu/tree.h
+++ b/kernel/rcu/tree.h
@@ -172,11 +172,6 @@ struct rcu_node {
172 /* queued on this rcu_node structure that */ 172 /* queued on this rcu_node structure that */
173 /* are blocking the current grace period, */ 173 /* are blocking the current grace period, */
174 /* there can be no such task. */ 174 /* there can be no such task. */
175 struct completion boost_completion;
176 /* Used to ensure that the rt_mutex used */
177 /* to carry out the boosting is fully */
178 /* released with no future boostee accesses */
179 /* before that rt_mutex is re-initialized. */
180 struct rt_mutex boost_mtx; 175 struct rt_mutex boost_mtx;
181 /* Used only for the priority-boosting */ 176 /* Used only for the priority-boosting */
182 /* side effect, not as a lock. */ 177 /* side effect, not as a lock. */
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index 1fac68220999..625e26040e6b 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -429,10 +429,8 @@ void rcu_read_unlock_special(struct task_struct *t)
429 429
430#ifdef CONFIG_RCU_BOOST 430#ifdef CONFIG_RCU_BOOST
431 /* Unboost if we were boosted. */ 431 /* Unboost if we were boosted. */
432 if (drop_boost_mutex) { 432 if (drop_boost_mutex)
433 rt_mutex_unlock(&rnp->boost_mtx); 433 rt_mutex_unlock(&rnp->boost_mtx);
434 complete(&rnp->boost_completion);
435 }
436#endif /* #ifdef CONFIG_RCU_BOOST */ 434#endif /* #ifdef CONFIG_RCU_BOOST */
437 435
438 /* 436 /*
@@ -1081,15 +1079,11 @@ static int rcu_boost(struct rcu_node *rnp)
1081 */ 1079 */
1082 t = container_of(tb, struct task_struct, rcu_node_entry); 1080 t = container_of(tb, struct task_struct, rcu_node_entry);
1083 rt_mutex_init_proxy_locked(&rnp->boost_mtx, t); 1081 rt_mutex_init_proxy_locked(&rnp->boost_mtx, t);
1084 init_completion(&rnp->boost_completion);
1085 raw_spin_unlock_irqrestore(&rnp->lock, flags); 1082 raw_spin_unlock_irqrestore(&rnp->lock, flags);
1086 /* Lock only for side effect: boosts task t's priority. */ 1083 /* Lock only for side effect: boosts task t's priority. */
1087 rt_mutex_lock(&rnp->boost_mtx); 1084 rt_mutex_lock(&rnp->boost_mtx);
1088 rt_mutex_unlock(&rnp->boost_mtx); /* Then keep lockdep happy. */ 1085 rt_mutex_unlock(&rnp->boost_mtx); /* Then keep lockdep happy. */
1089 1086
1090 /* Wait for boostee to be done w/boost_mtx before reinitializing. */
1091 wait_for_completion(&rnp->boost_completion);
1092
1093 return ACCESS_ONCE(rnp->exp_tasks) != NULL || 1087 return ACCESS_ONCE(rnp->exp_tasks) != NULL ||
1094 ACCESS_ONCE(rnp->boost_tasks) != NULL; 1088 ACCESS_ONCE(rnp->boost_tasks) != NULL;
1095} 1089}