From: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
This patch adds variants of rcu_dereference() that handle situations
where the RCU-protected data structure cannot change, perhaps due to
our holding the update-side lock, or where the RCU-protected pointer is
only to be fetched, not dereferenced.
The new rcu_access_pointer() primitive is for the case where the pointer
is be fetch and not dereferenced. This primitive may be used without
protection, RCU or otherwise, due to the fact that it uses ACCESS_ONCE().
The new rcu_dereference_protect() primitive is for the case where updates
are prevented, for example, due to holding the update-side lock. This
primitive does neither ACCESS_ONCE() nor smp_read_barrier_depends(), so
can only be used when updates are somehow prevented.
Suggested-by: David Howells <dhowells@redhat.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Signed-off-by: David Howells <dhowells@redhat.com>
---
include/linux/rcupdate.h | 34 ++++++++++++++++++++++++++++++++++
1 files changed, 34 insertions(+), 0 deletions(-)
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 872a98e..a1b14b6 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -209,9 +209,43 @@ static inline int rcu_read_lock_sched_held(void)
rcu_dereference_raw(p); \
})
+/**
+ * rcu_access_pointer - fetch RCU pointer with no dereferencing
+ *
+ * Return the value of the specified RCU-protected pointer, but omit the
+ * smp_read_barrier_depends() and keep the ACCESS_ONCE(). This is useful
+ * when the value of this pointer is accessed, but the pointer is not
+ * dereferenced, for example, when testing an RCU-protected pointer against
+ * NULL. This may also be used in cases where update-side locks prevent
+ * the value of the pointer from changing, but rcu_dereference_protect()
+ * is a lighter-weight primitive for this use case.
+ */
+#define rcu_access_pointer(p) \
+ ({ \
+ ACCESS_ONCE(p); \
+ })
+
+/**
+ * ...This is not the version Paul posted. Removing checks just to shutup warnings ? All the point is to get lockdep assistance, and you throw it away. We want to explicit the condition, so that RCU users can explicitly state what protects their data. --
What Eric said!!! ;-) Thanx, Paul --
You've missed the point.
For rcu_access_pointer(), _nothing_ protects the data, not only that, we don't
care: we're only checking the pointer.
For rcu_dereference_protect[ed](), I don't see that the check helps. You
don't need to be holding the RCU lock to call it, but you do need to hold all
the requisite locks required to exclude others modifying it. That's a
precondition for calling this function, so is there any point in testing it
again?
For instance, consider the following pseudocode:
do_something(struct foo *p)
{
struct bar *b;
spin_lock(&foo->lock);
b = rcu_dereference_protected(
foo->bar, lockdep_is_held(&foo->lock));
do_something_to_bar(b);
spin_unlock(&foo->lock);
}
is there any need for the condition? Does lockdep_is_held() have any side
effects beyond those listed in the Documentation directory or on its attached
banner comments?
Furthermore, I think the condition in rcu_dereference_check() may well be
misused. For instance, Paul suggested:
cred = rcu_dereference_check(delegation->cred,
delegation->inode == NULL);
but if 'c' is supposed to be the locks that protect the data, is this a valid
check?
David
--
How can you state this ?
Thats pretty simple, "always true" is a fine condition.
If you dont see how the check can help, why dont you unset
Yes, this is what is needed to help to catch when a condition is not
met.
Of course, on trivial code like this one, its pretty obvious condition
will be always true.
In many cases, smp_processor_id() checks are obvious too, yet we perform
them. It can help us sometimes, because many developers forget the
'c' is not a lock. Its a condition.
You as the author of this code, decide of the condition to check.
You therefore can answer yourself to this question.
Example of non trivial check :
static void __sk_free(struct sock *sk)
{
...
filter = rcu_dereference_check(sk->sk_filter,
atomic_read(&sk->sk_wmem_alloc) == 0);
...
}
In this check, there is no lock held.
commit a898def29e4119bc01ebe7ca97423181f4c0ea2d
Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Date: Mon Feb 22 17:04:49 2010 -0800
net: Add checking to rcu_dereference() primitives
Update rcu_dereference() primitives to use new lockdep-based
checking. The rcu_dereference() in __in6_dev_get() may be
protected either by rcu_read_lock() or RTNL, per Eric Dumazet.
The rcu_dereference() in __sk_free() is protected by the fact
that it is never reached if an update could change it. Check
for this by using rcu_dereference_check() to verify that the
struct sock's ->sk_wmem_alloc counter is zero.
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: laijs@cn.fujitsu.com
Cc: dipankar@in.ibm.com
Cc: mathieu.desnoyers@polymtl.ca
Cc: josh@joshtriplett.org
Cc: dvhltc@us.ibm.com
Cc: niv@us.ibm.com
Cc: peterz@infradead.org
Cc: rostedt@goodmis.org
Cc: Valdis.Kletnieks@vt.edu
Cc: dhowells@redhat.com
...If the condition for rcu_access_pointer() is always "always true", then it's redundant, right? rcu_access_pointer() is for checking the pointer only, not checking the payload that pointer might point to. So, what condition are you supposed to be checking? Sorry, I meant the state of the relevant locking context. what is the value of sk->sk_wmem_alloc to the lock context of sk->sk_filter? Why would lockdep be interested in sk_wmem_alloc? Surely, the assertion that the value of sk->sk_filter is related to sk_wmem_alloc being 0 is independent of the need to dereference sk_filter for RCU purposes. So why are these being combined? Why not: ASSERT(atomic_read(&sk->sk_wmem_alloc) == 0); filter = rcu_dereference(sk->sk_filter); This is much clearer, and you're not combining an unrelated assertion with the RCU dereference. David --
1) Because we want the check being done only when CONFIG_PROVE_RCU is set. 2) Because rcu_dereference() default condition is : 'Am I owning rcu_read_lock() or equivalent'. In this context, I am _not_ owning rcu lock, so we will trigger a warning. So this is best done as is :) I personally find this very clear and clean, this is why I acked Paul patch :) If we were 100% sure testing sk_wmem_alloc is not necessary, we would have put : filter = rcu_dereference_check(sk->sk_filter, 1); --
Because when sk->sk_filter is eventually written by some thread, this thread _must_ own a reference on the socket, that is sk_wmem_alloc > 0 So when reading sk->sk_filter, the general condition is : - We own the rcu lock - But on the particular case of __sk_free(), we owned the very last reference to sk (we are going to kfree it), so nobody can possibly change sk->sk_filter under us. --
