ipmr.c uses unregister_netdevice() to remove DVMRP tunnel devices
created in ipmr_new_tunnel().
This is fine because currently ip_tunnel_uninit() also calls
ip_tunnel_del() to unlink the device from the hash table.
However, we will move ip_tunnel_del() from ip_tunnel_uninit() to
ip_tunnel_dellink().
Removing DVMRP tunnel devices by unregister_netdevice() would leave
them in the hash table.
Let's call ->dellink for DVMRP tunnel devices.
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
---
v2: Correct commit message
---
net/ipv4/ipmr.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index b9c544d48c45..f9ecacfb092d 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -479,6 +479,7 @@ static struct net_device *ipmr_new_tunnel(struct net *net, struct vifctl *v)
{
struct net_device *tunnel_dev, *new_dev;
struct ip_tunnel_parm_kern p = { };
+ LIST_HEAD(dev_kill_list);
int err;
tunnel_dev = __dev_get_by_name(net, "tunl0");@@ -520,7 +521,8 @@ static struct net_device *ipmr_new_tunnel(struct net *net, struct vifctl *v)
return new_dev;
out_unregister:
- unregister_netdevice(new_dev);
+ new_dev->rtnl_link_ops->dellink(new_dev, &dev_kill_list);
+ unregister_netdevice_many(&dev_kill_list);
out:
return ERR_PTR(-ENOBUFS);
}
@@ -733,8 +735,12 @@ static int vif_delete(struct mr_table *mrt, int vifi, int notify,
ip_rt_multicast_event(in_dev);
}
- if (v->flags & (VIFF_TUNNEL | VIFF_REGISTER) && !notify)
- unregister_netdevice_queue(dev, head);
+ if (!notify) {
+ if (v->flags & VIFF_TUNNEL)
+ dev->rtnl_link_ops->dellink(dev, head);
+ else if (v->flags & VIFF_REGISTER)
+ unregister_netdevice_queue(dev, head);
+ }
netdev_put(dev, &v->dev_tracker);
return 0;--
2.55.0.1007.g17ff1f9808-goog