| From 4d5fa1e3dc647e5870189acd8a010dc1be2b9761 Mon Sep 17 00:00:00 2001 |
| From: Neeraj Upadhyay <neeraju@codeaurora.org> |
| Date: Mon, 11 Mar 2019 17:28:03 +0530 |
| Subject: rcu: Do a single rhp->func read in rcu_head_after_call_rcu() |
| |
| [ Upstream commit b699cce1604e828f19c39845252626eb78cdf38a ] |
| |
| The rcu_head_after_call_rcu() function reads the rhp->func pointer twice, |
| which can result in a false-positive WARN_ON_ONCE() if the callback |
| were passed to call_rcu() between the two reads. Although racing |
| rcu_head_after_call_rcu() with call_rcu() is to be a dubious use case |
| (the return value is not reliable in that case), intermittent and |
| irreproducible warnings are also quite dubious. This commit therefore |
| uses a single READ_ONCE() to pick up the value of rhp->func once, then |
| tests that value twice, thus guaranteeing consistent processing within |
| rcu_head_after_call_rcu()(). |
| |
| Neverthless, racing rcu_head_after_call_rcu() with call_rcu() is still |
| a dubious use case. |
| |
| Signed-off-by: Neeraj Upadhyay <neeraju@codeaurora.org> |
| [ paulmck: Add blank line after declaration per checkpatch.pl. ] |
| Signed-off-by: Paul E. McKenney <paulmck@linux.ibm.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| include/linux/rcupdate.h | 6 ++++-- |
| 1 file changed, 4 insertions(+), 2 deletions(-) |
| |
| diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h |
| index 6cdb1db776cf9..922bb68488133 100644 |
| --- a/include/linux/rcupdate.h |
| +++ b/include/linux/rcupdate.h |
| @@ -878,9 +878,11 @@ static inline void rcu_head_init(struct rcu_head *rhp) |
| static inline bool |
| rcu_head_after_call_rcu(struct rcu_head *rhp, rcu_callback_t f) |
| { |
| - if (READ_ONCE(rhp->func) == f) |
| + rcu_callback_t func = READ_ONCE(rhp->func); |
| + |
| + if (func == f) |
| return true; |
| - WARN_ON_ONCE(READ_ONCE(rhp->func) != (rcu_callback_t)~0L); |
| + WARN_ON_ONCE(func != (rcu_callback_t)~0L); |
| return false; |
| } |
| |
| -- |
| 2.20.1 |
| |