Commit db44575f6fd55df6ff67ddd21f7ad5be5a741136

Authored by Alexey Kuznetsov
Committed by David S. Miller
1 parent 1f494c0e04

[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>

Showing 3 changed files with 55 additions and 7 deletions Side-by-side Diff

... ... @@ -290,7 +290,6 @@
290 290  
291 291 dev_hold(dev);
292 292 ipgre_tunnel_link(nt);
293   - /* Do not decrement MOD_USE_COUNT here. */
294 293 return nt;
295 294  
296 295 failed:
297 296  
298 297  
... ... @@ -1277,12 +1276,28 @@
1277 1276 goto out;
1278 1277 }
1279 1278  
1280   -static void ipgre_fini(void)
  1279 +static void __exit ipgre_destroy_tunnels(void)
1281 1280 {
  1281 + int prio;
  1282 +
  1283 + for (prio = 0; prio < 4; prio++) {
  1284 + int h;
  1285 + for (h = 0; h < HASH_SIZE; h++) {
  1286 + struct ip_tunnel *t;
  1287 + while ((t = tunnels[prio][h]) != NULL)
  1288 + unregister_netdevice(t->dev);
  1289 + }
  1290 + }
  1291 +}
  1292 +
  1293 +static void __exit ipgre_fini(void)
  1294 +{
1282 1295 if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0)
1283 1296 printk(KERN_INFO "ipgre close: can't remove protocol\n");
1284 1297  
1285   - unregister_netdev(ipgre_fb_tunnel_dev);
  1298 + rtnl_lock();
  1299 + ipgre_destroy_tunnels();
  1300 + rtnl_unlock();
1286 1301 }
1287 1302  
1288 1303 module_init(ipgre_init);
... ... @@ -255,7 +255,6 @@
255 255  
256 256 dev_hold(dev);
257 257 ipip_tunnel_link(nt);
258   - /* Do not decrement MOD_USE_COUNT here. */
259 258 return nt;
260 259  
261 260 failed:
262 261  
... ... @@ -920,12 +919,29 @@
920 919 goto out;
921 920 }
922 921  
  922 +static void __exit ipip_destroy_tunnels(void)
  923 +{
  924 + int prio;
  925 +
  926 + for (prio = 1; prio < 4; prio++) {
  927 + int h;
  928 + for (h = 0; h < HASH_SIZE; h++) {
  929 + struct ip_tunnel *t;
  930 + while ((t = tunnels[prio][h]) != NULL)
  931 + unregister_netdevice(t->dev);
  932 + }
  933 + }
  934 +}
  935 +
923 936 static void __exit ipip_fini(void)
924 937 {
925 938 if (ipip_unregister() < 0)
926 939 printk(KERN_INFO "ipip close: can't deregister tunnel\n");
927 940  
928   - unregister_netdev(ipip_fb_tunnel_dev);
  941 + rtnl_lock();
  942 + ipip_destroy_tunnels();
  943 + unregister_netdevice(ipip_fb_tunnel_dev);
  944 + rtnl_unlock();
929 945 }
930 946  
931 947 module_init(ipip_init);
... ... @@ -195,7 +195,6 @@
195 195 dev_hold(dev);
196 196  
197 197 ipip6_tunnel_link(nt);
198   - /* Do not decrement MOD_USE_COUNT here. */
199 198 return nt;
200 199  
201 200 failed:
202 201  
... ... @@ -794,10 +793,28 @@
794 793 .err_handler = ipip6_err,
795 794 };
796 795  
  796 +static void __exit sit_destroy_tunnels(void)
  797 +{
  798 + int prio;
  799 +
  800 + for (prio = 1; prio < 4; prio++) {
  801 + int h;
  802 + for (h = 0; h < HASH_SIZE; h++) {
  803 + struct ip_tunnel *t;
  804 + while ((t = tunnels[prio][h]) != NULL)
  805 + unregister_netdevice(t->dev);
  806 + }
  807 + }
  808 +}
  809 +
797 810 void __exit sit_cleanup(void)
798 811 {
799 812 inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
800   - unregister_netdev(ipip6_fb_tunnel_dev);
  813 +
  814 + rtnl_lock();
  815 + sit_destroy_tunnels();
  816 + unregister_netdevice(ipip6_fb_tunnel_dev);
  817 + rtnl_unlock();
801 818 }
802 819  
803 820 int __init sit_init(void)