summaryrefslogtreecommitdiff
path: root/net/ipv6/sit.c
diff options
context:
space:
mode:
authorAlexey Kuznetsov <kuznet@ms2.inr.ac.ru>2005-07-30 17:46:44 -0700
committerDavid S. Miller <davem@davemloft.net>2005-07-30 17:46:44 -0700
commitdb44575f6fd55df6ff67ddd21f7ad5be5a741136 (patch)
tree3282b763dbc363202a328c473c47a8cad954687e /net/ipv6/sit.c
parent1f494c0e040b001cf844280910d04ba7ebdc2898 (diff)
downloadlwn-db44575f6fd55df6ff67ddd21f7ad5be5a741136.tar.gz
lwn-db44575f6fd55df6ff67ddd21f7ad5be5a741136.zip
[NET]: fix oops after tunnel module unload
Tunnel modules used to obtain module refcount each time when some tunnel was created, which meaned that tunnel could be unloaded only after all the tunnels are deleted. Since killing old MOD_*_USE_COUNT macros this protection has gone. It is possible to return it back as module_get/put, but it looks more natural and practically useful to force destruction of all the child tunnels on module unload. Signed-off-by: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/sit.c')
-rw-r--r--net/ipv6/sit.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index b788f55e139b..e553e5b80d6e 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -195,7 +195,6 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int
dev_hold(dev);
ipip6_tunnel_link(nt);
- /* Do not decrement MOD_USE_COUNT here. */
return nt;
failed:
@@ -794,10 +793,28 @@ static struct net_protocol sit_protocol = {
.err_handler = ipip6_err,
};
+static void __exit sit_destroy_tunnels(void)
+{
+ int prio;
+
+ for (prio = 1; prio < 4; prio++) {
+ int h;
+ for (h = 0; h < HASH_SIZE; h++) {
+ struct ip_tunnel *t;
+ while ((t = tunnels[prio][h]) != NULL)
+ unregister_netdevice(t->dev);
+ }
+ }
+}
+
void __exit sit_cleanup(void)
{
inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
- unregister_netdev(ipip6_fb_tunnel_dev);
+
+ rtnl_lock();
+ sit_destroy_tunnels();
+ unregister_netdevice(ipip6_fb_tunnel_dev);
+ rtnl_unlock();
}
int __init sit_init(void)