summaryrefslogtreecommitdiff
path: root/net/core/lwtunnel.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/lwtunnel.c')
-rw-r--r--net/core/lwtunnel.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c
index 2f6db386624e..afa64f086d87 100644
--- a/net/core/lwtunnel.c
+++ b/net/core/lwtunnel.c
@@ -66,6 +66,15 @@ EXPORT_SYMBOL(lwtunnel_state_alloc);
static const struct lwtunnel_encap_ops __rcu *
lwtun_encaps[LWTUNNEL_ENCAP_MAX + 1] __read_mostly;
+void lwtstate_free(struct lwtunnel_state *lws)
+{
+ const struct lwtunnel_encap_ops *ops = lwtun_encaps[lws->type];
+
+ kfree(lws);
+ module_put(ops->owner);
+}
+EXPORT_SYMBOL(lwtstate_free);
+
int lwtunnel_encap_add_ops(const struct lwtunnel_encap_ops *ops,
unsigned int num)
{
@@ -111,8 +120,11 @@ int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
ret = -EOPNOTSUPP;
rcu_read_lock();
ops = rcu_dereference(lwtun_encaps[encap_type]);
- if (likely(ops && ops->build_state))
+ if (likely(ops && ops->build_state && try_module_get(ops->owner))) {
ret = ops->build_state(dev, encap, family, cfg, lws);
+ if (ret)
+ module_put(ops->owner);
+ }
rcu_read_unlock();
return ret;