From patchwork Thu Apr 19 10:39:37 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Wenqi Ma X-Patchwork-Id: 153629 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id DC4EFB6EEB for ; Thu, 19 Apr 2012 13:01:44 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753611Ab2DSDBn (ORCPT ); Wed, 18 Apr 2012 23:01:43 -0400 Received: from sjdcsican04.udc.trendmicro.com ([66.180.85.17]:36463 "EHLO sjdciscan04.udc.trendmicro.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752665Ab2DSDBm (ORCPT ); Wed, 18 Apr 2012 23:01:42 -0400 X-Greylist: delayed 375 seconds by postgrey-1.27 at vger.kernel.org; Wed, 18 Apr 2012 23:01:42 EDT Received: from sjdciscan04.udc.trendmicro.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 86DA3328071; Wed, 18 Apr 2012 19:55:25 -0700 (PDT) Received: from sjdcexbh02.us.trendnet.org (unknown [66.180.82.3]) by sjdciscan04.udc.trendmicro.com (Postfix) with SMTP id 7AB5B32806F; Wed, 18 Apr 2012 19:55:25 -0700 (PDT) Received: from ADCEXBH03.tw.trendnet.org ([202.133.236.204]) by sjdcexbh02.us.trendnet.org with Microsoft SMTPSVC(6.0.3790.4675); Wed, 18 Apr 2012 19:55:25 -0700 Received: from CDCEXMAIL02.tw.trendnet.org ([10.64.1.42]) by ADCEXBH03.tw.trendnet.org with Microsoft SMTPSVC(6.0.3790.4675); Thu, 19 Apr 2012 10:55:23 +0800 Received: from localhost.localdomain ([10.64.78.197]) by CDCEXMAIL02.tw.trendnet.org with Microsoft SMTPSVC(6.0.3790.4675); Thu, 19 Apr 2012 10:55:22 +0800 From: Wenqi Ma To: netdev@vger.kernel.org Cc: davem@davemloft.net, haiyangz@microsoft.com, Wenqi Ma Subject: [PATCH] net/hyperv: Adding cancellation to ensure rndis filter is closed Date: Thu, 19 Apr 2012 18:39:37 +0800 Message-Id: <1334831977-5553-1-git-send-email-wenqi_ma@trendmicro.com.cn> X-Mailer: git-send-email 1.7.1 X-OriginalArrivalTime: 19 Apr 2012 02:55:22.0193 (UTC) FILETIME=[DCB97C10:01CD1DD7] Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Although the network interface is down, the RX packets number which could be observed by ifconfig may keep on increasing. This is because the WORK scheduled in netvsc_set_multicast_list() may be executed after netvsc_close(). That means the rndis filter may be re-enabled by do_set_multicast() even if it was closed by netvsc_close(). By canceling possible WORK before close the rndis filter, the issue could be never happened. Signed-off-by: Wenqi Ma Reviewed-by: Wei Yongjun --- drivers/net/hyperv/netvsc_drv.c | 38 ++++++++++++++------------------------ 1 files changed, 14 insertions(+), 24 deletions(-) -- 1.7.1 TREND MICRO EMAIL NOTICE The information contained in this email and any attachments is confidential and may be subject to copyright or other intellectual property protection. If you are not the intended recipient, you are not authorized to use or disclose this information, and we request that you notify us by reply mail or telephone and delete the original message from your mail system.N‹§˛ćěr¸›yúčšŘb˛XŹśÇ§vŘ^–)Ţş{.nÇ+‰ˇ§z×^ž)í…ćčw*jgŹą¨ś‰šŽŠÝ˘j/ęäzšŢ–Šŕ2ŠŢ™¨č­Ú&˘)ߥŤaśÚţřŽGŤéhŽćj:+v‰¨Šwč†ŮĽ Signed-off-by: Haiyang Zhang diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index dd29478..2d59138 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -44,6 +44,7 @@ struct net_device_context { /* point back to our device context */ struct hv_device *device_ctx; struct delayed_work dwork; + struct work_struct work; }; @@ -51,30 +52,22 @@ static int ring_size = 128; module_param(ring_size, int, S_IRUGO); MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)"); -struct set_multicast_work { - struct work_struct work; - struct net_device *net; -}; - static void do_set_multicast(struct work_struct *w) { - struct set_multicast_work *swk = - container_of(w, struct set_multicast_work, work); - struct net_device *net = swk->net; - - struct net_device_context *ndevctx = netdev_priv(net); + struct net_device_context *ndevctx = + container_of(w, struct net_device_context, work); struct netvsc_device *nvdev; struct rndis_device *rdev; nvdev = hv_get_drvdata(ndevctx->device_ctx); - if (nvdev == NULL) - goto out; + if (nvdev == NULL || nvdev->ndev == NULL) + return; rdev = nvdev->extension; if (rdev == NULL) - goto out; + return; - if (net->flags & IFF_PROMISC) + if (nvdev->ndev->flags & IFF_PROMISC) rndis_filter_set_packet_filter(rdev, NDIS_PACKET_TYPE_PROMISCUOUS); else @@ -82,21 +75,13 @@ static void do_set_multicast(struct work_struct *w) NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_ALL_MULTICAST | NDIS_PACKET_TYPE_DIRECTED); - -out: - kfree(w); } static void netvsc_set_multicast_list(struct net_device *net) { - struct set_multicast_work *swk = - kmalloc(sizeof(struct set_multicast_work), GFP_ATOMIC); - if (swk == NULL) - return; + struct net_device_context *net_device_ctx = netdev_priv(net); - swk->net = net; - INIT_WORK(&swk->work, do_set_multicast); - schedule_work(&swk->work); + schedule_work(&net_device_ctx->work); } static int netvsc_open(struct net_device *net) @@ -125,6 +110,8 @@ static int netvsc_close(struct net_device *net) netif_tx_disable(net); + /* Make sure netvsc_set_multicast_list doesn't re-enable filter! */ + cancel_work_sync(&net_device_ctx->work); ret = rndis_filter_close(device_obj); if (ret != 0) netdev_err(net, "unable to close device (ret %d).\n", ret); @@ -335,6 +322,7 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu) nvdev->start_remove = true; cancel_delayed_work_sync(&ndevctx->dwork); + cancel_work_sync(&ndevctx->work); netif_tx_disable(ndev); rndis_filter_device_remove(hdev); @@ -403,6 +391,7 @@ static int netvsc_probe(struct hv_device *dev, net_device_ctx->device_ctx = dev; hv_set_drvdata(dev, net); INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp); + INIT_WORK(&net_device_ctx->work, do_set_multicast); net->netdev_ops = &device_ops; @@ -456,6 +445,7 @@ static int netvsc_remove(struct hv_device *dev) ndev_ctx = netdev_priv(net); cancel_delayed_work_sync(&ndev_ctx->dwork); + cancel_work_sync(&ndev_ctx->work); /* Stop outbound asap */ netif_tx_disable(net);