aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPravin B Shelar <pshelar@nicira.com>2013-06-17 20:49:32 -0400
committerDavid S. Miller <davem@davemloft.net>2013-06-19 21:07:40 -0400
commit20fd4d1f04da07d09192ad8ad366a70d5125bfaf (patch)
treea241ed7f086c88361c4b411bee7fb45839fffc69
parentac8025a643a0e0beb81f3f37ca693364c6b77858 (diff)
gre: Simplify gre protocol registration locking.
Use cmpxchg() for atomic protocol registration which saves code and data space. Signed-off-by: Pravin B Shelar <pshelar@nicira.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv4/gre.c40
1 files changed, 13 insertions, 27 deletions
diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c
index b2e805af9b87..1e294d510ac3 100644
--- a/net/ipv4/gre.c
+++ b/net/ipv4/gre.c
@@ -26,46 +26,32 @@
26 26
27 27
28static const struct gre_protocol __rcu *gre_proto[GREPROTO_MAX] __read_mostly; 28static const struct gre_protocol __rcu *gre_proto[GREPROTO_MAX] __read_mostly;
29static DEFINE_SPINLOCK(gre_proto_lock);
30 29
31int gre_add_protocol(const struct gre_protocol *proto, u8 version) 30int gre_add_protocol(const struct gre_protocol *proto, u8 version)
32{ 31{
33 if (version >= GREPROTO_MAX) 32 if (version >= GREPROTO_MAX)
34 goto err_out; 33 return -EINVAL;
35
36 spin_lock(&gre_proto_lock);
37 if (gre_proto[version])
38 goto err_out_unlock;
39
40 RCU_INIT_POINTER(gre_proto[version], proto);
41 spin_unlock(&gre_proto_lock);
42 return 0;
43 34
44err_out_unlock: 35 return (cmpxchg((const struct gre_protocol **)&gre_proto[version], NULL, proto) == NULL) ?
45 spin_unlock(&gre_proto_lock); 36 0 : -EBUSY;
46err_out:
47 return -1;
48} 37}
49EXPORT_SYMBOL_GPL(gre_add_protocol); 38EXPORT_SYMBOL_GPL(gre_add_protocol);
50 39
51int gre_del_protocol(const struct gre_protocol *proto, u8 version) 40int gre_del_protocol(const struct gre_protocol *proto, u8 version)
52{ 41{
42 int ret;
43
53 if (version >= GREPROTO_MAX) 44 if (version >= GREPROTO_MAX)
54 goto err_out; 45 return -EINVAL;
55 46
56 spin_lock(&gre_proto_lock); 47 ret = (cmpxchg((const struct gre_protocol **)&gre_proto[version], proto, NULL) == proto) ?
57 if (rcu_dereference_protected(gre_proto[version], 48 0 : -EBUSY;
58 lockdep_is_held(&gre_proto_lock)) != proto) 49
59 goto err_out_unlock; 50 if (ret)
60 RCU_INIT_POINTER(gre_proto[version], NULL); 51 return ret;
61 spin_unlock(&gre_proto_lock); 52
62 synchronize_rcu(); 53 synchronize_rcu();
63 return 0; 54 return 0;
64
65err_out_unlock:
66 spin_unlock(&gre_proto_lock);
67err_out:
68 return -1;
69} 55}
70EXPORT_SYMBOL_GPL(gre_del_protocol); 56EXPORT_SYMBOL_GPL(gre_del_protocol);
71 57