提交 29906f6a 编写于 作者: P Patrick McHardy 提交者: David S. Miller

vlan: cleanup multiple unregistrations

The temporary copy of the VLAN group is not neccessary since the lower device
is already in the process of being unregistered, if it was neccessary the
memset of the global group would introduce a race condition.

With this removed, the changes to the original code are only a few lines, so
remove the new function and move the code back into vlan_device_event().
Signed-off-by: NPatrick McHardy <kaber@trash.net>
Acked-by: NEric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 f0816ce3
...@@ -161,10 +161,10 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) ...@@ -161,10 +161,10 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
grp->nr_vlans--; grp->nr_vlans--;
if (!grp->killall) { vlan_group_set_device(grp, vlan_id, NULL);
vlan_group_set_device(grp, vlan_id, NULL); if (!grp->killall)
synchronize_net(); synchronize_net();
}
unregister_netdevice_queue(dev, head); unregister_netdevice_queue(dev, head);
/* If the group is now empty, kill off the group. */ /* If the group is now empty, kill off the group. */
...@@ -184,34 +184,6 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) ...@@ -184,34 +184,6 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
dev_put(real_dev); dev_put(real_dev);
} }
void unregister_vlan_dev_alls(struct vlan_group *grp)
{
LIST_HEAD(list);
int i;
struct net_device *vlandev;
struct vlan_group save;
memcpy(&save, grp, sizeof(save));
memset(&grp->vlan_devices_arrays, 0, sizeof(grp->vlan_devices_arrays));
grp->killall = 1;
synchronize_net();
/* Delete all VLANs for this dev. */
for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
vlandev = vlan_group_get_device(&save, i);
if (!vlandev)
continue;
unregister_vlan_dev(vlandev, &list);
if (grp->nr_vlans == 0)
break;
}
unregister_netdevice_many(&list);
for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++)
kfree(save.vlan_devices_arrays[i]);
}
static void vlan_transfer_operstate(const struct net_device *dev, static void vlan_transfer_operstate(const struct net_device *dev,
struct net_device *vlandev) struct net_device *vlandev)
{ {
...@@ -456,6 +428,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, ...@@ -456,6 +428,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
struct vlan_group *grp; struct vlan_group *grp;
int i, flgs; int i, flgs;
struct net_device *vlandev; struct net_device *vlandev;
LIST_HEAD(list);
if (is_vlan_dev(dev)) if (is_vlan_dev(dev))
__vlan_device_event(dev, event); __vlan_device_event(dev, event);
...@@ -553,7 +526,22 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, ...@@ -553,7 +526,22 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
break; break;
case NETDEV_UNREGISTER: case NETDEV_UNREGISTER:
unregister_vlan_dev_alls(grp); /* Delete all VLANs for this dev. */
grp->killall = 1;
for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
vlandev = vlan_group_get_device(grp, i);
if (!vlandev)
continue;
/* unregistration of last vlan destroys group, abort
* afterwards */
if (grp->nr_vlans == 1)
i = VLAN_GROUP_ARRAY_LEN;
unregister_vlan_dev(vlandev, &list);
}
unregister_netdevice_many(&list);
break; break;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册