Commit db44575f authored by Alexey Kuznetsov's avatar Alexey Kuznetsov Committed by David S. Miller

[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: default avatarAlexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1f494c0e
...@@ -290,7 +290,6 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int ...@@ -290,7 +290,6 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int
dev_hold(dev); dev_hold(dev);
ipgre_tunnel_link(nt); ipgre_tunnel_link(nt);
/* Do not decrement MOD_USE_COUNT here. */
return nt; return nt;
failed: failed:
...@@ -1277,12 +1276,28 @@ static int __init ipgre_init(void) ...@@ -1277,12 +1276,28 @@ static int __init ipgre_init(void)
goto out; goto out;
} }
static void ipgre_fini(void) static void __exit ipgre_destroy_tunnels(void)
{
int prio;
for (prio = 0; 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);
}
}
}
static void __exit ipgre_fini(void)
{ {
if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0)
printk(KERN_INFO "ipgre close: can't remove protocol\n"); printk(KERN_INFO "ipgre close: can't remove protocol\n");
unregister_netdev(ipgre_fb_tunnel_dev); rtnl_lock();
ipgre_destroy_tunnels();
rtnl_unlock();
} }
module_init(ipgre_init); module_init(ipgre_init);
......
...@@ -255,7 +255,6 @@ static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int c ...@@ -255,7 +255,6 @@ static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int c
dev_hold(dev); dev_hold(dev);
ipip_tunnel_link(nt); ipip_tunnel_link(nt);
/* Do not decrement MOD_USE_COUNT here. */
return nt; return nt;
failed: failed:
...@@ -920,12 +919,29 @@ static int __init ipip_init(void) ...@@ -920,12 +919,29 @@ static int __init ipip_init(void)
goto out; goto out;
} }
static void __exit ipip_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);
}
}
}
static void __exit ipip_fini(void) static void __exit ipip_fini(void)
{ {
if (ipip_unregister() < 0) if (ipip_unregister() < 0)
printk(KERN_INFO "ipip close: can't deregister tunnel\n"); printk(KERN_INFO "ipip close: can't deregister tunnel\n");
unregister_netdev(ipip_fb_tunnel_dev); rtnl_lock();
ipip_destroy_tunnels();
unregister_netdevice(ipip_fb_tunnel_dev);
rtnl_unlock();
} }
module_init(ipip_init); module_init(ipip_init);
......
...@@ -195,7 +195,6 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int ...@@ -195,7 +195,6 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int
dev_hold(dev); dev_hold(dev);
ipip6_tunnel_link(nt); ipip6_tunnel_link(nt);
/* Do not decrement MOD_USE_COUNT here. */
return nt; return nt;
failed: failed:
...@@ -794,10 +793,28 @@ static struct net_protocol sit_protocol = { ...@@ -794,10 +793,28 @@ static struct net_protocol sit_protocol = {
.err_handler = ipip6_err, .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) void __exit sit_cleanup(void)
{ {
inet_del_protocol(&sit_protocol, IPPROTO_IPV6); 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) int __init sit_init(void)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment