You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
net: Fix high overhead of vlan sub-device teardown.
When a networking device is taken down that has a non-trivial number of VLAN devices configured under it, we eat a full synchronize_net() for every such VLAN device. This is because of the call chain: NETDEV_DOWN notifier --> vlan_device_event() --> dev_change_flags() --> __dev_change_flags() --> __dev_close() --> __dev_close_many() --> dev_deactivate_many() --> synchronize_net() This is kind of rediculous because we already have infrastructure for batching doing operation X to a list of net devices so that we only incur one sync. So make use of that by exporting dev_close_many() and adjusting it's interfaace so that the caller can fully manage the batch list. Use this in vlan_device_event() and all the overhead goes away. Reported-by: Salam Noureddine <noureddine@arista.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
+14
-4
@@ -413,7 +413,10 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
|
||||
vlan_transfer_features(dev, vlandev);
|
||||
break;
|
||||
|
||||
case NETDEV_DOWN:
|
||||
case NETDEV_DOWN: {
|
||||
struct net_device *tmp;
|
||||
LIST_HEAD(close_list);
|
||||
|
||||
if (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
|
||||
vlan_vid_del(dev, htons(ETH_P_8021Q), 0);
|
||||
|
||||
@@ -425,11 +428,18 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
|
||||
|
||||
vlan = vlan_dev_priv(vlandev);
|
||||
if (!(vlan->flags & VLAN_FLAG_LOOSE_BINDING))
|
||||
dev_change_flags(vlandev, flgs & ~IFF_UP);
|
||||
netif_stacked_transfer_operstate(dev, vlandev);
|
||||
list_add(&vlandev->close_list, &close_list);
|
||||
}
|
||||
break;
|
||||
|
||||
dev_close_many(&close_list, false);
|
||||
|
||||
list_for_each_entry_safe(vlandev, tmp, &close_list, close_list) {
|
||||
netif_stacked_transfer_operstate(dev, vlandev);
|
||||
list_del_init(&vlandev->close_list);
|
||||
}
|
||||
list_del(&close_list);
|
||||
break;
|
||||
}
|
||||
case NETDEV_UP:
|
||||
/* Put all VLANs for this dev in the up state too. */
|
||||
vlan_group_for_each_dev(grp, i, vlandev) {
|
||||
|
||||
Reference in New Issue
Block a user