sn->n_tunnels--;
if (sn->n_tunnels)
goto out;
-#ifdef HAVE_NF_REGISTER_NET_HOOK
- nf_unregister_net_hook(net, &nf_hook_ops);
-#else
- nf_unregister_hook(&nf_hook_ops);
-#endif
-
out:
n_tunnels--;
if (n_tunnels)
struct net *net = stt_dev->net;
list_del_rcu(&stt_dev->up_next);
+ synchronize_net();
tcp_sock_release(stt_dev->sock);
stt_dev->sock = NULL;
stt_cleanup(net);
struct net_device *dev, *aux;
LIST_HEAD(list);
+#ifdef HAVE_NF_REGISTER_NET_HOOK
+ /* Ideally this should be done from stt_stop(), But on some kernels
+ * nf-unreg operation needs RTNL-lock, which can cause deallock.
+ * So it is done from here. */
+ if (!list_empty(&nf_hook_ops.list))
+ nf_unregister_net_hook(net, &nf_hook_ops);
+#endif
+
rtnl_lock();
/* gather any stt devices that were moved into this ns */
if (rc)
goto out2;
+ INIT_LIST_HEAD(&nf_hook_ops.list);
pr_info("STT tunneling driver\n");
return 0;
out2:
void stt_cleanup_module(void)
{
+#ifndef HAVE_NF_REGISTER_NET_HOOK
+ if (!list_empty(&nf_hook_ops.list))
+ nf_unregister_hook(&nf_hook_ops);
+#endif
rtnl_link_unregister(&stt_link_ops);
unregister_pernet_subsys(&stt_net_ops);
}