From patchwork Fri Mar 3 20:23:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Igor Druzhinin X-Patchwork-Id: 9603477 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 1CF5160453 for ; Fri, 3 Mar 2017 20:25:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ED21027F81 for ; Fri, 3 Mar 2017 20:25:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CF56A283EE; Fri, 3 Mar 2017 20:25:43 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id D104C27F81 for ; Fri, 3 Mar 2017 20:25:41 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cjtjQ-00086h-2I; Fri, 03 Mar 2017 20:23:16 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cjtjP-00086b-Ez for xen-devel@lists.xenproject.org; Fri, 03 Mar 2017 20:23:15 +0000 Received: from [85.158.137.68] by server-8.bemta-3.messagelabs.com id 93/F0-00609-2B0D9B85; Fri, 03 Mar 2017 20:23:14 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrOLMWRWlGSWpSXmKPExsXitHRDpO7GCzs jDFbeMrf4vmUykwOjx+EPV1gCGKNYM/OS8isSWDN2bzzAWvBJteJPyy/mBsZ78l2MnBwSAv4S bz4sZwKx2QQMJE5tWsQCYosI2Elc2nyAHcRmFiiRaDu5nhXEFhbwkZj04ihQDQcHi4CKxI2jH iBhXgFPiU/XPjJBjFSQmPLwPTOILSSgJnG0axcLRI2gxMmZT1ggRkpIHHzxgnkCI/csJKlZSF ILGJlWMaoXpxaVpRbpGuslFWWmZ5TkJmbm6BoaGOvlphYXJ6an5iQmFesl5+duYgQGAgMQ7GB s/uJ0iFGSg0lJlPe46Y4IIb6k/JTKjMTijPii0pzU4kOMMhwcShK8WV5AOcGi1PTUirTMHGBI wqQlOHiURHi3g6R5iwsSc4sz0yFSpxh1OebM3v2GSYglLz8vVUqc1wWkSACkKKM0D24ELD4uM cpKCfMyAh0lxFOQWpSbWYIq/4pRnINRSZh3KsgUnsy8ErhNr4COYAI64oXKVpAjShIRUlINjL w/Di5bb6s7OyBotXyA706z7kNP3IW2WJzc8D1xm80Hi9nawQ+nvlGvEdUtt5PS/PO8J2lq2A+ zp6zTkj3E6pUrZmYtS3ALDnaQeFMw6e9py3PPP+9T875kL1/tmH/vTW8zU+XK2gJd9WknD2ne e+PwgLPPYvK6O769+31bF8zo1P9neHyHlxJLcUaioRZzUXEiAGn5TpGKAgAA X-Env-Sender: prvs=228c22c4c=igor.druzhinin@citrix.com X-Msg-Ref: server-11.tower-31.messagelabs.com!1488572592!57611018!1 X-Originating-IP: [66.165.176.89] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n, received_headers: No Received headers X-StarScan-Received: X-StarScan-Version: 9.2.3; banners=-,-,- X-VirusChecked: Checked Received: (qmail 27165 invoked from network); 3 Mar 2017 20:23:13 -0000 Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89) by server-11.tower-31.messagelabs.com with RC4-SHA encrypted SMTP; 3 Mar 2017 20:23:13 -0000 X-IronPort-AV: E=Sophos;i="5.35,238,1484006400"; d="scan'208";a="411321603" From: Igor Druzhinin To: , Date: Fri, 3 Mar 2017 20:23:07 +0000 Message-ID: <1488572587-91220-1-git-send-email-igor.druzhinin@citrix.com> X-Mailer: git-send-email 1.8.3.1 MIME-Version: 1.0 Cc: jgross@suse.com, Igor Druzhinin , paul.durrant@citrix.com, wei.liu2@citrix.com Subject: [Xen-devel] [PATCH net v2] xen-netback: fix race condition on XenBus disconnect X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP In some cases during XenBus disconnect event handling and subsequent queue resource release there may be some TX handlers active on other processors. Use RCU in order to synchronize with them. Signed-off-by: Igor Druzhinin --- v2: * Add protection for xenvif_get_ethtool_stats * Additional comments and fixes --- drivers/net/xen-netback/interface.c | 29 ++++++++++++++++++++++------- drivers/net/xen-netback/netback.c | 2 +- drivers/net/xen-netback/xenbus.c | 20 ++++++++++---------- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index a2d32676..266b7cd 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -164,13 +164,17 @@ static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct xenvif *vif = netdev_priv(dev); struct xenvif_queue *queue = NULL; - unsigned int num_queues = vif->num_queues; + unsigned int num_queues; u16 index; struct xenvif_rx_cb *cb; BUG_ON(skb->dev != dev); - /* Drop the packet if queues are not set up */ + /* Drop the packet if queues are not set up. + * This handler should be called inside an RCU read section + * so we don't need to enter it here explicitly. + */ + num_queues = rcu_dereference(vif)->num_queues; if (num_queues < 1) goto drop; @@ -221,18 +225,21 @@ static struct net_device_stats *xenvif_get_stats(struct net_device *dev) { struct xenvif *vif = netdev_priv(dev); struct xenvif_queue *queue = NULL; + unsigned int num_queues; u64 rx_bytes = 0; u64 rx_packets = 0; u64 tx_bytes = 0; u64 tx_packets = 0; unsigned int index; - spin_lock(&vif->lock); - if (vif->queues == NULL) + rcu_read_lock(); + + num_queues = rcu_dereference(vif)->num_queues; + if (num_queues < 1) goto out; /* Aggregate tx and rx stats from each queue */ - for (index = 0; index < vif->num_queues; ++index) { + for (index = 0; index < num_queues; ++index) { queue = &vif->queues[index]; rx_bytes += queue->stats.rx_bytes; rx_packets += queue->stats.rx_packets; @@ -241,7 +248,7 @@ static struct net_device_stats *xenvif_get_stats(struct net_device *dev) } out: - spin_unlock(&vif->lock); + rcu_read_unlock(); vif->dev->stats.rx_bytes = rx_bytes; vif->dev->stats.rx_packets = rx_packets; @@ -377,10 +384,16 @@ static void xenvif_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 * data) { struct xenvif *vif = netdev_priv(dev); - unsigned int num_queues = vif->num_queues; + unsigned int num_queues; int i; unsigned int queue_index; + rcu_read_lock(); + + num_queues = rcu_dereference(vif)->num_queues; + if (num_queues < 1) + goto out; + for (i = 0; i < ARRAY_SIZE(xenvif_stats); i++) { unsigned long accum = 0; for (queue_index = 0; queue_index < num_queues; ++queue_index) { @@ -389,6 +402,8 @@ static void xenvif_get_ethtool_stats(struct net_device *dev, } data[i] = accum; } +out: + rcu_read_unlock(); } static void xenvif_get_strings(struct net_device *dev, u32 stringset, u8 * data) diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index f9bcf4a..62fa74d 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -214,7 +214,7 @@ static void xenvif_fatal_tx_err(struct xenvif *vif) netdev_err(vif->dev, "fatal error; disabling device\n"); vif->disabled = true; /* Disable the vif from queue 0's kthread */ - if (vif->queues) + if (vif->num_queues > 0) xenvif_kick_thread(&vif->queues[0]); } diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index d2d7cd9..a56d3ea 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -495,26 +495,26 @@ static void backend_disconnect(struct backend_info *be) struct xenvif *vif = be->vif; if (vif) { + unsigned int num_queues = vif->num_queues; unsigned int queue_index; - struct xenvif_queue *queues; xen_unregister_watchers(vif); #ifdef CONFIG_DEBUG_FS xenvif_debugfs_delif(vif); #endif /* CONFIG_DEBUG_FS */ xenvif_disconnect_data(vif); - for (queue_index = 0; - queue_index < vif->num_queues; - ++queue_index) - xenvif_deinit_queue(&vif->queues[queue_index]); - spin_lock(&vif->lock); - queues = vif->queues; + /* At this point some of the handlers may still be active + * so we need to have additional synchronization here. + */ vif->num_queues = 0; - vif->queues = NULL; - spin_unlock(&vif->lock); + synchronize_net(); - vfree(queues); + for (queue_index = 0; queue_index < num_queues; ++queue_index) + xenvif_deinit_queue(&vif->queues[queue_index]); + + vfree(vif->queues); + vif->queues = NULL; xenvif_disconnect_ctrl(vif); }