mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
ip6_gre: Clear ign->fb_tunnel_dev in ip6gre_exit_rtnl_net().
ip6gre_dellink() ignores itn->fb_tunnel_dev, so the per-netns fallback tunnel device cannot be removed by userspace. This also makes default_device_exit_batch() impossible to remove the device since it calls ->dellink(). So, ip6gre_exit_rtnl_net() has to iterate devices in the dying netns and call unregister_netdevice_queue() directly, and ip6gre_tunnel_unlink() must be called at ->ndo_uninit(). For per-netns device unregistration, we want to check if the device is being removed in ->dellink(), for which we must call ip6gre_tunnel_unlink() before unregister_netdevice_queue(). As a prep, let's set itn->fb_tunnel_dev to NULL and remove remove for_each_netdev_safe() in ip6gre_exit_rtnl_net(). Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260916230353.367014-4-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
3b2813cc6b
commit
28328796e0
|
|
@ -374,8 +374,6 @@ static void ip6gre_tunnel_uninit(struct net_device *dev)
|
|||
|
||||
ip6gre_tunnel_unlink_md(ign, t);
|
||||
ip6gre_tunnel_unlink(ign, t);
|
||||
if (ign->fb_tunnel_dev == dev)
|
||||
WRITE_ONCE(ign->fb_tunnel_dev, NULL);
|
||||
dst_cache_reset(&t->dst_cache);
|
||||
netdev_put(dev, &t->dev_tracker);
|
||||
}
|
||||
|
|
@ -1552,29 +1550,20 @@ static void __net_exit ip6gre_exit_rtnl_net(struct net *net,
|
|||
struct list_head *dev_kill_list)
|
||||
{
|
||||
struct ip6gre_net *ign = net_generic(net, ip6gre_net_id);
|
||||
struct net_device *dev, *aux;
|
||||
int prio;
|
||||
|
||||
for_each_netdev_safe(net, dev, aux)
|
||||
if (dev->rtnl_link_ops == &ip6gre_link_ops ||
|
||||
dev->rtnl_link_ops == &ip6gre_tap_ops ||
|
||||
dev->rtnl_link_ops == &ip6erspan_tap_ops)
|
||||
unregister_netdevice_queue(dev, dev_kill_list);
|
||||
WRITE_ONCE(ign->fb_tunnel_dev, NULL);
|
||||
|
||||
for (prio = 0; prio < 4; prio++) {
|
||||
int h;
|
||||
|
||||
for (h = 0; h < IP6_GRE_HASH_SIZE; h++) {
|
||||
struct hlist_head *head = &ign->tunnels[prio][h];
|
||||
struct hlist_node *tmp;
|
||||
struct ip6_tnl *t;
|
||||
|
||||
hlist_for_each_entry(t, head, hash_node) {
|
||||
/* If dev is in the same netns, it has already
|
||||
* been added to the list by the previous loop.
|
||||
*/
|
||||
if (!net_eq(dev_net(t->dev), net))
|
||||
unregister_netdevice_queue(t->dev, dev_kill_list);
|
||||
}
|
||||
hlist_for_each_entry_safe(t, tmp, head, hash_node)
|
||||
unregister_netdevice_queue(t->dev, dev_kill_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user