diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 1187bfc8a09d..e4c51ca47301 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;