diff options
author | Pravin B Shelar <pshelar@nicira.com> | 2013-06-17 20:49:32 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-06-19 21:07:40 -0400 |
commit | 20fd4d1f04da07d09192ad8ad366a70d5125bfaf (patch) | |
tree | a241ed7f086c88361c4b411bee7fb45839fffc69 | |
parent | ac8025a643a0e0beb81f3f37ca693364c6b77858 (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.c | 40 |
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 | ||
28 | static const struct gre_protocol __rcu *gre_proto[GREPROTO_MAX] __read_mostly; | 28 | static const struct gre_protocol __rcu *gre_proto[GREPROTO_MAX] __read_mostly; |
29 | static DEFINE_SPINLOCK(gre_proto_lock); | ||
30 | 29 | ||
31 | int gre_add_protocol(const struct gre_protocol *proto, u8 version) | 30 | int 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 | ||
44 | err_out_unlock: | 35 | return (cmpxchg((const struct gre_protocol **)&gre_proto[version], NULL, proto) == NULL) ? |
45 | spin_unlock(&gre_proto_lock); | 36 | 0 : -EBUSY; |
46 | err_out: | ||
47 | return -1; | ||
48 | } | 37 | } |
49 | EXPORT_SYMBOL_GPL(gre_add_protocol); | 38 | EXPORT_SYMBOL_GPL(gre_add_protocol); |
50 | 39 | ||
51 | int gre_del_protocol(const struct gre_protocol *proto, u8 version) | 40 | int 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 | |||
65 | err_out_unlock: | ||
66 | spin_unlock(&gre_proto_lock); | ||
67 | err_out: | ||
68 | return -1; | ||
69 | } | 55 | } |
70 | EXPORT_SYMBOL_GPL(gre_del_protocol); | 56 | EXPORT_SYMBOL_GPL(gre_del_protocol); |
71 | 57 | ||