aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/dev.c
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2009-11-17 00:59:21 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-18 08:03:11 -0500
commite014debecd3ee3832e6476b3a9c948edfcfd1250 (patch)
tree9b73836a5dc3c1df92b17037a12bbbfaf5f495d3 /net/core/dev.c
parente2ce146848c81af2f6d42e67990191c284bf0c33 (diff)
linkwatch: linkwatch_forget_dev() to speedup device dismantle
Herbert Xu a écrit : > On Tue, Nov 17, 2009 at 04:26:04AM -0800, David Miller wrote: >> Really, the link watch stuff is just due for a redesign. I don't >> think a simple hack is going to cut it this time, sorry Eric :-) > > I have no objections against any redesigns, but since the only > caller of linkwatch_forget_dev runs in process context with the > RTNL, it could also legally emit those events. Thanks guys, here an updated version then, before linkwatch surgery ? In this version, I force the event to be sent synchronously. [PATCH net-next-2.6] linkwatch: linkwatch_forget_dev() to speedup device dismantle time ip link del eth3.103 ; time ip link del eth3.104 ; time ip link del eth3.105 real 0m0.266s user 0m0.000s sys 0m0.001s real 0m0.770s user 0m0.000s sys 0m0.000s real 0m1.022s user 0m0.000s sys 0m0.000s One problem of current schem in vlan dismantle phase is the holding of device done by following chain : vlan_dev_stop() -> netif_carrier_off(dev) -> linkwatch_fire_event(dev) -> dev_hold() ... And __linkwatch_run_queue() runs up to one second later... A generic fix to this problem is to add a linkwatch_forget_dev() method to unlink the device from the list of watched devices. dev->link_watch_next becomes dev->link_watch_list (and use a bit more memory), to be able to unlink device in O(1). After patch : time ip link del eth3.103 ; time ip link del eth3.104 ; time ip link del eth3.105 real 0m0.024s user 0m0.000s sys 0m0.000s real 0m0.032s user 0m0.000s sys 0m0.001s real 0m0.033s user 0m0.000s sys 0m0.000s Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/dev.c')
-rw-r--r--net/core/dev.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index e25fe5d9343b..c128af708ebf 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5085,6 +5085,8 @@ static void netdev_wait_allrefs(struct net_device *dev)
5085{ 5085{
5086 unsigned long rebroadcast_time, warning_time; 5086 unsigned long rebroadcast_time, warning_time;
5087 5087
5088 linkwatch_forget_dev(dev);
5089
5088 rebroadcast_time = warning_time = jiffies; 5090 rebroadcast_time = warning_time = jiffies;
5089 while (atomic_read(&dev->refcnt) != 0) { 5091 while (atomic_read(&dev->refcnt) != 0) {
5090 if (time_after(jiffies, rebroadcast_time + 1 * HZ)) { 5092 if (time_after(jiffies, rebroadcast_time + 1 * HZ)) {
@@ -5311,6 +5313,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
5311 5313
5312 INIT_LIST_HEAD(&dev->napi_list); 5314 INIT_LIST_HEAD(&dev->napi_list);
5313 INIT_LIST_HEAD(&dev->unreg_list); 5315 INIT_LIST_HEAD(&dev->unreg_list);
5316 INIT_LIST_HEAD(&dev->link_watch_list);
5314 dev->priv_flags = IFF_XMIT_DST_RELEASE; 5317 dev->priv_flags = IFF_XMIT_DST_RELEASE;
5315 setup(dev); 5318 setup(dev);
5316 strcpy(dev->name, name); 5319 strcpy(dev->name, name);