From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752149AbdB1DIT (ORCPT ); Mon, 27 Feb 2017 22:08:19 -0500 Received: from a2nlsmtp01-05.prod.iad2.secureserver.net ([198.71.225.49]:36794 "EHLO a2nlsmtp01-05.prod.iad2.secureserver.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751505AbdB1DHa (ORCPT ); Mon, 27 Feb 2017 22:07:30 -0500 x-originating-ip: 107.180.71.197 From: kys@exchange.microsoft.com To: gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, devel@linuxdriverproject.org, olaf@aepfle.de, apw@canonical.com, vkuznets@redhat.com, jasowang@redhat.com, leann.ogasawara@canonical.com Cc: Stephen Hemminger , Stephen Hemminger , "K. Y. Srinivasan" Subject: [PATCH 02/10] vmbus: use rcu for per-cpu channel list Date: Mon, 27 Feb 2017 20:05:25 -0700 Message-Id: <1488251133-32767-2-git-send-email-kys@exchange.microsoft.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1488251083-32718-1-git-send-email-kys@exchange.microsoft.com> References: <1488251083-32718-1-git-send-email-kys@exchange.microsoft.com> Reply-To: kys@microsoft.com X-CMAE-Envelope: MS4wfJu8JvHd9/8PD2+/LPsSqbOCi2AlHpXMcZDFCua1ic7g9stHY5pbpK9JAeiVUsq4d/XdgT/wILiBv401K9BRvZKRuUAjhfhYnMLshQzurLWC0CuuxhMG hqNr5n6Iaqj8R123vsgiq1FtW2JwkJzREscuoRD2EL0iQdehFV+I/KjuOp0qKd4sSq9YRd52YV8DM3yBnQR17Dn+aXpUwGAiVyHK5w9Yd8qMQfn5cxHMuBwj 3guLQTss4JAg+nMMz7kXlR0BYx+WUWTPOKxZkmBYhQKYKs69/lqsg0hqwCfTMmAYah7gKSeje6gdPiYZZjVUvB4Ay+ytlw+dxq8/FrVmBKghiAKPh7I3AZ00 5GD8IX2l+wTay1r16MxFUg0eI7pM04fd4GiB/e9HfGpXP9dimAQddcr2xUzsK+/dp072jRHaeIWgse+EmoNjHi1LHzBhnjQewsn2UALA2Ac06zAbRtdK6l4W fhcIK3u91q4CJwZOeQJUyoQRGpP0TgGUCMDhLax6Qiv07VsTKmL9aQSG3wQ= Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Stephen Hemminger The per-cpu channel list is now referred to in the interrupt routine. This is mostly safe since the host will not normally generate an interrupt when channel is being deleted but if it did then there would be a use after free problem. To solve, this use RCU protection on ther per-cpu list. Signed-off-by: Stephen Hemminger Signed-off-by: K. Y. Srinivasan --- drivers/hv/channel_mgmt.c | 7 ++++--- drivers/hv/vmbus_drv.c | 6 +++++- include/linux/hyperv.h | 7 +++++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index f33465d..d2cfa3e 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -350,7 +350,8 @@ bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, static void free_channel(struct vmbus_channel *channel) { tasklet_kill(&channel->callback_event); - kfree(channel); + + kfree_rcu(channel, rcu); } static void percpu_channel_enq(void *arg) @@ -359,14 +360,14 @@ static void percpu_channel_enq(void *arg) struct hv_per_cpu_context *hv_cpu = this_cpu_ptr(hv_context.cpu_context); - list_add_tail(&channel->percpu_list, &hv_cpu->chan_list); + list_add_tail_rcu(&channel->percpu_list, &hv_cpu->chan_list); } static void percpu_channel_deq(void *arg) { struct vmbus_channel *channel = arg; - list_del(&channel->percpu_list); + list_del_rcu(&channel->percpu_list); } diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index f7f6b91..971ecb7 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -937,8 +937,10 @@ static void vmbus_chan_sched(struct hv_per_cpu_context *hv_cpu) if (relid == 0) continue; + rcu_read_lock(); + /* Find channel based on relid */ - list_for_each_entry(channel, &hv_cpu->chan_list, percpu_list) { + list_for_each_entry_rcu(channel, &hv_cpu->chan_list, percpu_list) { if (channel->offermsg.child_relid != relid) continue; @@ -954,6 +956,8 @@ static void vmbus_chan_sched(struct hv_per_cpu_context *hv_cpu) tasklet_schedule(&channel->callback_event); } } + + rcu_read_unlock(); } } diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 62bbf3c..c4c7ae9 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -845,6 +845,13 @@ struct vmbus_channel { * link up channels based on their CPU affinity. */ struct list_head percpu_list; + + /* + * Defer freeing channel until after all cpu's have + * gone through grace period. + */ + struct rcu_head rcu; + /* * For performance critical channels (storage, networking * etc,), Hyper-V has a mechanism to enhance the throughput -- 1.7.1