Commit 226bd341 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

net: use batched device unregister in veth and macvlan

veth devices dont use the batched device unregisters yet.

Since veth are a pair of devices, it makes sense to use a batch of two
unregisters, this roughly divides dismantle time by two.

Fix this by changing dellink() callers to always provide a non NULL
head. (Idea from Michał Mirosław)

This patch also handles macvlan case : We now dismantle all macvlans on
top of a lower dev at once.
Reported-by: default avatarAlex Bligh <alex@alex.org.uk>
Signed-off-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Cc: Michał Mirosław <mirqus@gmail.com>
Cc: Jesse Gross <jesse@nicira.com>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Ben Greear <greearb@candelatech.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7ef73bca
...@@ -785,6 +785,7 @@ static int macvlan_device_event(struct notifier_block *unused, ...@@ -785,6 +785,7 @@ static int macvlan_device_event(struct notifier_block *unused,
struct net_device *dev = ptr; struct net_device *dev = ptr;
struct macvlan_dev *vlan, *next; struct macvlan_dev *vlan, *next;
struct macvlan_port *port; struct macvlan_port *port;
LIST_HEAD(list_kill);
if (!macvlan_port_exists(dev)) if (!macvlan_port_exists(dev))
return NOTIFY_DONE; return NOTIFY_DONE;
...@@ -810,7 +811,9 @@ static int macvlan_device_event(struct notifier_block *unused, ...@@ -810,7 +811,9 @@ static int macvlan_device_event(struct notifier_block *unused,
break; break;
list_for_each_entry_safe(vlan, next, &port->vlans, list) list_for_each_entry_safe(vlan, next, &port->vlans, list)
vlan->dev->rtnl_link_ops->dellink(vlan->dev, NULL); vlan->dev->rtnl_link_ops->dellink(vlan->dev, &list_kill);
unregister_netdevice_many(&list_kill);
list_del(&list_kill);
break; break;
case NETDEV_PRE_TYPE_CHANGE: case NETDEV_PRE_TYPE_CHANGE:
/* Forbid underlaying device to change its type. */ /* Forbid underlaying device to change its type. */
......
...@@ -1501,6 +1501,7 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -1501,6 +1501,7 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
char ifname[IFNAMSIZ]; char ifname[IFNAMSIZ];
struct nlattr *tb[IFLA_MAX+1]; struct nlattr *tb[IFLA_MAX+1];
int err; int err;
LIST_HEAD(list_kill);
err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
if (err < 0) if (err < 0)
...@@ -1524,7 +1525,9 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -1524,7 +1525,9 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
if (!ops) if (!ops)
return -EOPNOTSUPP; return -EOPNOTSUPP;
ops->dellink(dev, NULL); ops->dellink(dev, &list_kill);
unregister_netdevice_many(&list_kill);
list_del(&list_kill);
return 0; return 0;
} }
......
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