From patchwork Mon May 14 22:32:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Hemminger X-Patchwork-Id: 913327 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=networkplumber.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=networkplumber-org.20150623.gappssmtp.com header.i=@networkplumber-org.20150623.gappssmtp.com header.b="BgaOutk3"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40lFpp4plWz9s0q for ; Tue, 15 May 2018 08:33:38 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752432AbeENWdg (ORCPT ); Mon, 14 May 2018 18:33:36 -0400 Received: from mail-pl0-f68.google.com ([209.85.160.68]:35067 "EHLO mail-pl0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752286AbeENWcz (ORCPT ); Mon, 14 May 2018 18:32:55 -0400 Received: by mail-pl0-f68.google.com with SMTP id i5-v6so8177783plt.2 for ; Mon, 14 May 2018 15:32:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ClVs8AE3PTo6BSRVvuuygx+37ejPaSoZNBMOyxqnwuw=; b=BgaOutk3a5tY5H44DDPLzN6ex8Y1G34RranB34nmP3/tPfxF9Or+81sKeDs2YtE5FQ A4r0E1pyt505kTee0+f04UL2Sq2SBsgGGM2yOpZGRtNwZsgY2GApZddY9WjvRqwYp0/P IJAD4BB49ggw22euaknOeZCyFPn/AgokC4Bllbl45amrksVGDxkX7supu9tKEipMlFBO xhlTp273heXZA2Z6/vlK51bL12UDQGhaCk31ltng8B8OQFxY5NADHbqt1sVmJ6lZGP17 ozgMm04i1BzfEUF1FJYZJuYDcdoxnWInSDVgtvSSijNep26c5iNvP2McRJnzECYRh1uG 5hgw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ClVs8AE3PTo6BSRVvuuygx+37ejPaSoZNBMOyxqnwuw=; b=oXuV1UhrUF8Cl6QHd989NLbAq3htEPDwshhjMPUh06HIAgXeLzTnDuh60uoXlgdzNw iZyPooWAtNBTKCgtJCHhuwieamFCYht/PDEuEgYKSNR+j2EolopaU5u2Hfj5a7LWqfWs lObvAnTXtX33Y+f47FAEsx2iludYlzABK0BoRUvJ0l6IBgh8/dK6RjUXu2RIhQSL/kcy IhWRRh/gGp9+dRu7nPVPjgKBMWAEBflB/jHXLrrFkjoW4b0Hb496c9mDB3OuvN5+VCBh 22TdF2yCM3whr1z/D6FS31KT4AhbMs/X2HbvPIMjL3CIuftVM8qkpkdtrqJnSi6y8aN1 FWyw== X-Gm-Message-State: ALKqPwf9xyGYFrYDGEfm6qJ3TD++lAK6uEni7vLVOfk0JvCmiao4Qds+ bB6I9kuGMJ8rZ4aLEp5YtLZrVwnSR9w= X-Google-Smtp-Source: AB8JxZrOLPR7d/Y+cmoPnm/niqfEKMGhGWmho9bt86x44RmuZNwBeXCSQJHn/dLxpQVcSwEG5vlnXw== X-Received: by 2002:a17:902:1347:: with SMTP id r7-v6mr11513013ple.62.1526337174745; Mon, 14 May 2018 15:32:54 -0700 (PDT) Received: from xeon-e3.lan (204-195-35-107.wavecable.com. [204.195.35.107]) by smtp.gmail.com with ESMTPSA id y29-v6sm23827830pff.42.2018.05.14.15.32.53 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 14 May 2018 15:32:53 -0700 (PDT) From: Stephen Hemminger X-Google-Original-From: Stephen Hemminger To: davem@davemloft.net Cc: netdev@vger.kernel.org, Stephen Hemminger , Stephen Hemminger Subject: [PATCH net-stable 17/24] hv_netvsc: use RCU to fix concurrent rx and queue changes Date: Mon, 14 May 2018 15:32:16 -0700 Message-Id: <20180514223223.25433-18-sthemmin@microsoft.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180514223223.25433-1-sthemmin@microsoft.com> References: <20180514223223.25433-1-sthemmin@microsoft.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Stephen Hemminger commit 02400fcee2542ee334a2394e0d9f6efd969fe782 upstream The receive processing may continue to happen while the internal network device state is in RCU grace period. The internal RNDIS structure is associated with the internal netvsc_device structure; both have the same RCU lifetime. Defer freeing all associated parts until after grace period. Fixes: 0cf737808ae7 ("hv_netvsc: netvsc_teardown_gpadl() split") Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/hyperv/netvsc.c | 17 ++++---------- drivers/net/hyperv/rndis_filter.c | 39 ++++++++++++++----------------- 2 files changed, 22 insertions(+), 34 deletions(-) diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index a8789dc4fc9b..03328a60377e 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -89,6 +89,11 @@ static void free_netvsc_device(struct rcu_head *head) = container_of(head, struct netvsc_device, rcu); int i; + kfree(nvdev->extension); + vfree(nvdev->recv_buf); + vfree(nvdev->send_buf); + kfree(nvdev->send_section_map); + for (i = 0; i < VRSS_CHANNEL_MAX; i++) vfree(nvdev->chan_table[i].mrc.slots); @@ -210,12 +215,6 @@ static void netvsc_teardown_gpadl(struct hv_device *device, net_device->recv_buf_gpadl_handle = 0; } - if (net_device->recv_buf) { - /* Free up the receive buffer */ - vfree(net_device->recv_buf); - net_device->recv_buf = NULL; - } - if (net_device->send_buf_gpadl_handle) { ret = vmbus_teardown_gpadl(device->channel, net_device->send_buf_gpadl_handle); @@ -230,12 +229,6 @@ static void netvsc_teardown_gpadl(struct hv_device *device, } net_device->send_buf_gpadl_handle = 0; } - if (net_device->send_buf) { - /* Free up the send buffer */ - vfree(net_device->send_buf); - net_device->send_buf = NULL; - } - kfree(net_device->send_section_map); } int netvsc_alloc_recv_comp_ring(struct netvsc_device *net_device, u32 q_idx) diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index 5a312b2d5a7b..056499014a1f 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -266,13 +266,23 @@ static void rndis_set_link_state(struct rndis_device *rdev, } } -static void rndis_filter_receive_response(struct rndis_device *dev, - struct rndis_message *resp) +static void rndis_filter_receive_response(struct net_device *ndev, + struct netvsc_device *nvdev, + const struct rndis_message *resp) { + struct rndis_device *dev = nvdev->extension; struct rndis_request *request = NULL; bool found = false; unsigned long flags; - struct net_device *ndev = dev->ndev; + + /* This should never happen, it means control message + * response received after device removed. + */ + if (dev->state == RNDIS_DEV_UNINITIALIZED) { + netdev_err(ndev, + "got rndis message uninitialized\n"); + return; + } spin_lock_irqsave(&dev->request_lock, flags); list_for_each_entry(request, &dev->req_list, list_ent) { @@ -353,7 +363,7 @@ static inline void *rndis_get_ppi(struct rndis_packet *rpkt, u32 type) } static int rndis_filter_receive_data(struct net_device *ndev, - struct rndis_device *dev, + struct netvsc_device *nvdev, struct rndis_message *msg, struct vmbus_channel *channel, void *data, u32 data_buflen) @@ -373,7 +383,7 @@ static int rndis_filter_receive_data(struct net_device *ndev, * should be the data packet size plus the trailer padding size */ if (unlikely(data_buflen < rndis_pkt->data_len)) { - netdev_err(dev->ndev, "rndis message buffer " + netdev_err(ndev, "rndis message buffer " "overflow detected (got %u, min %u)" "...dropping this message!\n", data_buflen, rndis_pkt->data_len); @@ -401,34 +411,20 @@ int rndis_filter_receive(struct net_device *ndev, void *data, u32 buflen) { struct net_device_context *net_device_ctx = netdev_priv(ndev); - struct rndis_device *rndis_dev = net_dev->extension; struct rndis_message *rndis_msg = data; - /* Make sure the rndis device state is initialized */ - if (unlikely(!rndis_dev)) { - netif_err(net_device_ctx, rx_err, ndev, - "got rndis message but no rndis device!\n"); - return NVSP_STAT_FAIL; - } - - if (unlikely(rndis_dev->state == RNDIS_DEV_UNINITIALIZED)) { - netif_err(net_device_ctx, rx_err, ndev, - "got rndis message uninitialized\n"); - return NVSP_STAT_FAIL; - } - if (netif_msg_rx_status(net_device_ctx)) dump_rndis_message(dev, rndis_msg); switch (rndis_msg->ndis_msg_type) { case RNDIS_MSG_PACKET: - return rndis_filter_receive_data(ndev, rndis_dev, rndis_msg, + return rndis_filter_receive_data(ndev, net_dev, rndis_msg, channel, data, buflen); case RNDIS_MSG_INIT_C: case RNDIS_MSG_QUERY_C: case RNDIS_MSG_SET_C: /* completion msgs */ - rndis_filter_receive_response(rndis_dev, rndis_msg); + rndis_filter_receive_response(ndev, net_dev, rndis_msg); break; case RNDIS_MSG_INDICATE: @@ -1349,7 +1345,6 @@ void rndis_filter_device_remove(struct hv_device *dev, net_dev->extension = NULL; netvsc_device_remove(dev); - kfree(rndis_dev); } int rndis_filter_open(struct netvsc_device *nvdev)