Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752076AbdCBM4m (ORCPT ); Thu, 2 Mar 2017 07:56:42 -0500 Received: from mail-co1nam03on0120.outbound.protection.outlook.com ([104.47.40.120]:58688 "EHLO NAM03-CO1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1750915AbdCBM4i (ORCPT ); Thu, 2 Mar 2017 07:56:38 -0500 From: Dexuan Cui To: "gregkh@linuxfoundation.org" , "Stephen Hemminger" , KY Srinivasan , Haiyang Zhang , "driverdev-devel@linuxdriverproject.org" CC: "linux-kernel@vger.kernel.org" Subject: [PATCH] vmbus: remove hv_event_tasklet_disable/enable Thread-Topic: [PATCH] vmbus: remove hv_event_tasklet_disable/enable Thread-Index: AdKTUJgIQmRE4IPAQUOnBPPQVJ5F0w== Date: Thu, 2 Mar 2017 12:32:55 +0000 Message-ID: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: linuxfoundation.org; dkim=none (message not signed) header.d=none;linuxfoundation.org; dmarc=none action=none header.from=microsoft.com; x-originating-ip: [167.220.255.28] x-ms-office365-filtering-correlation-id: 8d5cd35f-fa55-475d-6710-08d4616840de x-ms-office365-filtering-ht: Tenant x-microsoft-antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001)(48565401081);SRVR:MWHPR03MB2493; x-microsoft-exchange-diagnostics: 1;MWHPR03MB2493;7:jo74u/sXACGRHjquVRyWO9NMcAd1ZxhyCTnjzyvLEryROK4MMI8omcg7CGDcw7cF2T0YzB/EzdI2m/RMY5OLSRsAYCqETA2h0/c88xOKnt5g9qQIgxHhtaxL0PXYlyxkQL8IDSedEpa6YwigaFS2EtD8TP+i2xh+qtzg8YTK0k/Xhqvh8RQ/afXREgTcaP8G8oQEg52DmmrXM3c8pC6ugf98bDZs/sNAL9ilubPInaubGQq7OlNNEZdxNALwgd2dWQyN9aKy6KVLyG2B0UDnIQGyPEH4Uh0Qz7/V8Wx8oMVlRED6DnTfcAzucErgF32yIKBIV5FxA6+bfcPcCBbGk+0lNUrJGPV/7vHkswdamkA=;23:efrj1ZhQQazT8Cdc0tPNkGF5vFKS1y/8p0+gcf8H7QKNmmPQIdRKdev4hKSpjBy9xFCkM2AhkC890mMK88qVEq04irEyQoSXDbf5OzRdkD4qUxbG+oSIozx8gIsqmN2xXQYiAg+l+fEwTDp8cLKgrQ== x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:; x-exchange-antispam-report-cfa-test: BCL:0;PCL:0;RULEID:(61425038)(6040375)(601004)(2401047)(8121501046)(5005006)(10201501046)(3002001)(6055026)(61426038)(61427038)(6041248)(20161123555025)(20161123560025)(20161123562025)(20161123564025)(20161123558025)(6072148);SRVR:MWHPR03MB2493;BCL:0;PCL:0;RULEID:;SRVR:MWHPR03MB2493; x-forefront-prvs: 023495660C x-forefront-antispam-report: SFV:NSPM;SFS:(10019020)(6009001)(7916002)(39850400002)(39860400002)(39450400003)(39840400002)(39410400002)(6116002)(575784001)(2501003)(54356999)(2421001)(2906002)(77096006)(92566002)(86612001)(2900100001)(102836003)(33656002)(86362001)(66066001)(53936002)(3846002)(9686003)(99286003)(6436002)(3280700002)(3660700001)(38730400002)(189998001)(8936002)(6506006)(5005710100001)(81166006)(55016002)(74316002)(8676002)(7696004)(8990500004)(5660300001)(122556002)(10290500002)(25786008)(50986999)(305945005)(7736002)(4326008);DIR:OUT;SFP:1102;SCL:1;SRVR:MWHPR03MB2493;H:MWHPR03MB2669.namprd03.prod.outlook.com;FPR:;SPF:None;MLV:sfv;LANG:en; spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 X-MS-Exchange-CrossTenant-originalarrivaltime: 02 Mar 2017 12:32:55.5750 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 72f988bf-86f1-41af-91ab-2d7cd011db47 X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR03MB2493 X-OriginatorOrg: microsoft.com Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from quoted-printable to 8bit by mail.home.local id v22CuuRn022165 Content-Length: 5640 Lines: 160 With the recent introduction of per-channel tasklet, we need to update the way we handle the 3 concurrency issues: 1. hv_process_channel_removal -> percpu_channel_deq vs. vmbus_chan_sched -> list_for_each_entry(..., percpu_list); 2. vmbus_process_offer -> percpu_channel_enq/deq vs. vmbus_chan_sched. 3. vmbus_close_internal vs. the per-channel tasklet vmbus_on_event; The first 2 issues can be handled by Stephen's recent patch "vmbus: use rcu for per-cpu channel list", and the third issue can be handled by calling tasklet_disable in vmbus_close_internal here. We don't need the original hv_event_tasklet_disable/enable since we now use per-channel tasklet instead of the previous per-CPU tasklet, and actually we must remove them due to the side effect now: vmbus_process_offer -> hv_event_tasklet_enable -> tasklet_schedule will start the per-channel callback prematurely, cauing NULL dereferencing (the channel may haven't been properly configured to run the callback yet). Fixes: 631e63a9f346 ("vmbus: change to per channel tasklet") Signed-off-by: Dexuan Cui Cc: "K. Y. Srinivasan" Cc: Haiyang Zhang Cc: Stephen Hemminger --- Stephen Hemminger's patch ("vmbus: use rcu for per-cpu channel list") was posted to the community last month, but it hasn't been in char-misc yet, as far as I know. drivers/hv/channel.c | 12 ++++-------- drivers/hv/channel_mgmt.c | 19 ------------------- include/linux/hyperv.h | 3 --- 3 files changed, 4 insertions(+), 30 deletions(-) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index bd0d198..57b2958 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -530,15 +530,13 @@ static int vmbus_close_internal(struct vmbus_channel *channel) int ret; /* - * vmbus_on_event(), running in the tasklet, can race + * vmbus_on_event(), running in the per-channel tasklet, can race * with vmbus_close_internal() in the case of SMP guest, e.g., when * the former is accessing channel->inbound.ring_buffer, the latter - * could be freeing the ring_buffer pages. - * - * To resolve the race, we can serialize them by disabling the - * tasklet when the latter is running here. + * could be freeing the ring_buffer pages, so here we must stop it + * first. */ - hv_event_tasklet_disable(channel); + tasklet_disable(&channel->callback_event); /* * In case a device driver's probe() fails (e.g., @@ -605,8 +603,6 @@ static int vmbus_close_internal(struct vmbus_channel *channel) get_order(channel->ringbuffer_pagecount * PAGE_SIZE)); out: - hv_event_tasklet_enable(channel); - return ret; } diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index d2cfa3e..bf846d0 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -382,19 +382,6 @@ static void vmbus_release_relid(u32 relid) true); } -void hv_event_tasklet_disable(struct vmbus_channel *channel) -{ - tasklet_disable(&channel->callback_event); -} - -void hv_event_tasklet_enable(struct vmbus_channel *channel) -{ - tasklet_enable(&channel->callback_event); - - /* In case there is any pending event */ - tasklet_schedule(&channel->callback_event); -} - void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) { unsigned long flags; @@ -403,7 +390,6 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) BUG_ON(!channel->rescind); BUG_ON(!mutex_is_locked(&vmbus_connection.channel_mutex)); - hv_event_tasklet_disable(channel); if (channel->target_cpu != get_cpu()) { put_cpu(); smp_call_function_single(channel->target_cpu, @@ -412,7 +398,6 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) percpu_channel_deq(channel); put_cpu(); } - hv_event_tasklet_enable(channel); if (channel->primary_channel == NULL) { list_del(&channel->listentry); @@ -506,7 +491,6 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) init_vp_index(newchannel, dev_type); - hv_event_tasklet_disable(newchannel); if (newchannel->target_cpu != get_cpu()) { put_cpu(); smp_call_function_single(newchannel->target_cpu, @@ -516,7 +500,6 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) percpu_channel_enq(newchannel); put_cpu(); } - hv_event_tasklet_enable(newchannel); /* * This state is used to indicate a successful open @@ -566,7 +549,6 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) list_del(&newchannel->listentry); mutex_unlock(&vmbus_connection.channel_mutex); - hv_event_tasklet_disable(newchannel); if (newchannel->target_cpu != get_cpu()) { put_cpu(); smp_call_function_single(newchannel->target_cpu, @@ -575,7 +557,6 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) percpu_channel_deq(newchannel); put_cpu(); } - hv_event_tasklet_enable(newchannel); vmbus_release_relid(newchannel->offermsg.child_relid); diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index c4c7ae9..970771a 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -1437,9 +1437,6 @@ extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, u8 *buf, const int *srv_version, int srv_vercnt, int *nego_fw_version, int *nego_srv_version); -void hv_event_tasklet_disable(struct vmbus_channel *channel); -void hv_event_tasklet_enable(struct vmbus_channel *channel); - void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid); void vmbus_setevent(struct vmbus_channel *channel); -- 2.7.4