summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorPravin B Shelar <pshelar@nicira.com>2013-06-18 04:49:32 +0400
committerDavid S. Miller <davem@davemloft.net>2013-06-20 05:07:40 +0400
commit20fd4d1f04da07d09192ad8ad366a70d5125bfaf (patch)
treea241ed7f086c88361c4b411bee7fb45839fffc69 /net
parentac8025a643a0e0beb81f3f37ca693364c6b77858 (diff)
downloadlinux-20fd4d1f04da07d09192ad8ad366a70d5125bfaf.tar.xz
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>
Diffstat (limited to '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 @@
static const struct gre_protocol __rcu *gre_proto[GREPROTO_MAX] __read_mostly;
-static DEFINE_SPINLOCK(gre_proto_lock);
int gre_add_protocol(const struct gre_protocol *proto, u8 version)
{
if (version >= GREPROTO_MAX)
- goto err_out;
-
- spin_lock(&gre_proto_lock);
- if (gre_proto[version])
- goto err_out_unlock;
-
- RCU_INIT_POINTER(gre_proto[version], proto);
- spin_unlock(&gre_proto_lock);
- return 0;
+ return -EINVAL;
-err_out_unlock:
- spin_unlock(&gre_proto_lock);
-err_out:
- return -1;
+ return (cmpxchg((const struct gre_protocol **)&gre_proto[version], NULL, proto) == NULL) ?
+ 0 : -EBUSY;
}
EXPORT_SYMBOL_GPL(gre_add_protocol);
int gre_del_protocol(const struct gre_protocol *proto, u8 version)
{
+ int ret;
+
if (version >= GREPROTO_MAX)
- goto err_out;
-
- spin_lock(&gre_proto_lock);
- if (rcu_dereference_protected(gre_proto[version],
- lockdep_is_held(&gre_proto_lock)) != proto)
- goto err_out_unlock;
- RCU_INIT_POINTER(gre_proto[version], NULL);
- spin_unlock(&gre_proto_lock);
+ return -EINVAL;
+
+ ret = (cmpxchg((const struct gre_protocol **)&gre_proto[version], proto, NULL) == proto) ?
+ 0 : -EBUSY;
+
+ if (ret)
+ return ret;
+
synchronize_rcu();
return 0;
-
-err_out_unlock:
- spin_unlock(&gre_proto_lock);
-err_out:
- return -1;
}
EXPORT_SYMBOL_GPL(gre_del_protocol);