netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Patrick McHardy <kaber@trash.net>
To: Eric Dumazet <eric.dumazet@gmail.com>
Cc: "David S. Miller" <davem@davemloft.net>,
	Linux Netdev List <netdev@vger.kernel.org>
Subject: Re: [PATCH 4/6] vlan: Optimize multiple unregistration
Date: Thu, 29 Oct 2009 15:23:16 +0100	[thread overview]
Message-ID: <4AE9A554.8030207@trash.net> (raw)
In-Reply-To: <4AE99C88.40403@trash.net>

[-- Attachment #1: Type: text/plain, Size: 1019 bytes --]

Patrick McHardy wrote:
> Eric Dumazet wrote:
>> Patrick McHardy a écrit :
>>>> +{
>>>> +	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));
>>> This shouldn't be necessary since the lower device is already in the
>>> process of being unregistered. If it was necessary, it could cause
>>> crashes since the individual pointers are not set to zero atomically.
>>> Or maybe I'm misunderstanding the purpose entirely :)
>> Very good point indeed, even if in practice memset() use long word transferts
>>
>> I'll make a cleanup patch, or do you want to do it ?
> 
> I can take care of this, patch will follow shortly.

How about this? I moved the code back into vlan_device_event() since
its now only a very minimal change to the original code.

vlan-orig.diff contains the diff between the original code and the
code after this patch for reference.


[-- Attachment #2: vlan.diff --]
[-- Type: text/x-patch, Size: 2891 bytes --]

commit aa8fda37701cb6a452aeb6505c42817ad6e081fc
Author: Patrick McHardy <kaber@trash.net>
Date:   Thu Oct 29 15:13:38 2009 +0100

    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: Patrick McHardy <kaber@trash.net>

diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 511afe7..39f8d01 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -161,10 +161,10 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
 
 	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();
-	}
+
 	unregister_netdevice_queue(dev, head);
 
 	/* 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)
 	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,
 				    struct net_device *vlandev)
 {
@@ -456,6 +428,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
 	struct vlan_group *grp;
 	int i, flgs;
 	struct net_device *vlandev;
+	LIST_HEAD(list);
 
 	if (is_vlan_dev(dev))
 		__vlan_device_event(dev, event);
@@ -553,7 +526,22 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
 		break;
 
 	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;
 	}
 

[-- Attachment #3: vlan-orig.diff --]
[-- Type: text/x-patch, Size: 1399 bytes --]

diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 6b5c9dd..39f8d01 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -159,10 +159,11 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
 	if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
 		ops->ndo_vlan_rx_kill_vid(real_dev, vlan_id);
 
-	vlan_group_set_device(grp, vlan_id, NULL);
 	grp->nr_vlans--;
 
-	synchronize_net();
+	vlan_group_set_device(grp, vlan_id, NULL);
+	if (!grp->killall)
+		synchronize_net();
 
 	unregister_netdevice_queue(dev, head);
 
@@ -427,6 +428,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
 	struct vlan_group *grp;
 	int i, flgs;
 	struct net_device *vlandev;
+	LIST_HEAD(list);
 
 	if (is_vlan_dev(dev))
 		__vlan_device_event(dev, event);
@@ -525,6 +527,8 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
 
 	case NETDEV_UNREGISTER:
 		/* 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)
@@ -535,8 +539,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
 			if (grp->nr_vlans == 1)
 				i = VLAN_GROUP_ARRAY_LEN;
 
-			unregister_vlan_dev(vlandev, NULL);
+			unregister_vlan_dev(vlandev, &list);
 		}
+		unregister_netdevice_many(&list);
 		break;
 	}
 

  reply	other threads:[~2009-10-29 14:23 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-10-27 17:06 [PATCH 4/6] vlan: Optimize multiple unregistration Eric Dumazet
2009-10-28 20:05 ` Patrick McHardy
2009-10-28 20:47   ` Eric Dumazet
2009-10-29 13:45     ` Patrick McHardy
2009-10-29 14:23       ` Patrick McHardy [this message]
2009-10-29 14:30         ` Eric Dumazet
2009-10-29 14:33           ` Patrick McHardy
2009-10-29 14:43             ` Eric Dumazet
2009-10-29 17:25               ` Patrick McHardy
2009-10-30  6:30                 ` Eric Dumazet
2009-10-30  6:43                   ` David Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4AE9A554.8030207@trash.net \
    --to=kaber@trash.net \
    --cc=davem@davemloft.net \
    --cc=eric.dumazet@gmail.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).