aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2015-08-21 13:42:50 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2015-10-06 14:25:16 -0400
commit3a518b76af7bb411efe6dd090fbf098e29accb2e (patch)
tree784edc06760ddaa84fbdfdcfe3ea52c9fb872fca
parent82e8c565be8a72957570d7da8dd9b441db7bb648 (diff)
rcu_sync: Add CONFIG_PROVE_RCU checks
This commit validates that the caller of rcu_sync_is_idle() holds the corresponding type of RCU read-side lock, but only in kernels built with CONFIG_PROVE_RCU=y. This validation is carried out via a new rcu_sync_ops->held() method that is checked within rcu_sync_is_idle(). Note that although this does add code to the fast path, it only does so in kernels built with CONFIG_PROVE_RCU=y. Suggested-by: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> Signed-off-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Reviewed-by: Josh Triplett <josh@joshtriplett.org>
-rw-r--r--include/linux/rcu_sync.h6
-rw-r--r--kernel/rcu/sync.c20
2 files changed, 26 insertions, 0 deletions
diff --git a/include/linux/rcu_sync.h b/include/linux/rcu_sync.h
index c6d2272c4459..1f2d4fc30b04 100644
--- a/include/linux/rcu_sync.h
+++ b/include/linux/rcu_sync.h
@@ -40,6 +40,8 @@ struct rcu_sync {
40 enum rcu_sync_type gp_type; 40 enum rcu_sync_type gp_type;
41}; 41};
42 42
43extern bool __rcu_sync_is_idle(struct rcu_sync *);
44
43/** 45/**
44 * rcu_sync_is_idle() - Are readers permitted to use their fastpaths? 46 * rcu_sync_is_idle() - Are readers permitted to use their fastpaths?
45 * @rsp: Pointer to rcu_sync structure to use for synchronization 47 * @rsp: Pointer to rcu_sync structure to use for synchronization
@@ -50,7 +52,11 @@ struct rcu_sync {
50 */ 52 */
51static inline bool rcu_sync_is_idle(struct rcu_sync *rsp) 53static inline bool rcu_sync_is_idle(struct rcu_sync *rsp)
52{ 54{
55#ifdef CONFIG_PROVE_RCU
56 return __rcu_sync_is_idle(rsp);
57#else
53 return !rsp->gp_state; /* GP_IDLE */ 58 return !rsp->gp_state; /* GP_IDLE */
59#endif
54} 60}
55 61
56extern void rcu_sync_init(struct rcu_sync *, enum rcu_sync_type); 62extern void rcu_sync_init(struct rcu_sync *, enum rcu_sync_type);
diff --git a/kernel/rcu/sync.c b/kernel/rcu/sync.c
index 5a9aa4c394f1..01c9807a7f73 100644
--- a/kernel/rcu/sync.c
+++ b/kernel/rcu/sync.c
@@ -23,21 +23,33 @@
23#include <linux/rcu_sync.h> 23#include <linux/rcu_sync.h>
24#include <linux/sched.h> 24#include <linux/sched.h>
25 25
26#ifdef CONFIG_PROVE_RCU
27#define __INIT_HELD(func) .held = func,
28#else
29#define __INIT_HELD(func)
30#endif
31
26static const struct { 32static const struct {
27 void (*sync)(void); 33 void (*sync)(void);
28 void (*call)(struct rcu_head *, void (*)(struct rcu_head *)); 34 void (*call)(struct rcu_head *, void (*)(struct rcu_head *));
35#ifdef CONFIG_PROVE_RCU
36 int (*held)(void);
37#endif
29} gp_ops[] = { 38} gp_ops[] = {
30 [RCU_SYNC] = { 39 [RCU_SYNC] = {
31 .sync = synchronize_rcu, 40 .sync = synchronize_rcu,
32 .call = call_rcu, 41 .call = call_rcu,
42 __INIT_HELD(rcu_read_lock_held)
33 }, 43 },
34 [RCU_SCHED_SYNC] = { 44 [RCU_SCHED_SYNC] = {
35 .sync = synchronize_sched, 45 .sync = synchronize_sched,
36 .call = call_rcu_sched, 46 .call = call_rcu_sched,
47 __INIT_HELD(rcu_read_lock_sched_held)
37 }, 48 },
38 [RCU_BH_SYNC] = { 49 [RCU_BH_SYNC] = {
39 .sync = synchronize_rcu_bh, 50 .sync = synchronize_rcu_bh,
40 .call = call_rcu_bh, 51 .call = call_rcu_bh,
52 __INIT_HELD(rcu_read_lock_bh_held)
41 }, 53 },
42}; 54};
43 55
@@ -46,6 +58,14 @@ enum { CB_IDLE = 0, CB_PENDING, CB_REPLAY };
46 58
47#define rss_lock gp_wait.lock 59#define rss_lock gp_wait.lock
48 60
61#ifdef CONFIG_PROVE_RCU
62bool __rcu_sync_is_idle(struct rcu_sync *rsp)
63{
64 WARN_ON(!gp_ops[rsp->gp_type].held());
65 return rsp->gp_state == GP_IDLE;
66}
67#endif
68
49/** 69/**
50 * rcu_sync_init() - Initialize an rcu_sync structure 70 * rcu_sync_init() - Initialize an rcu_sync structure
51 * @rsp: Pointer to rcu_sync structure to be initialized 71 * @rsp: Pointer to rcu_sync structure to be initialized