From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933402AbdKGAJm (ORCPT ); Mon, 6 Nov 2017 19:09:42 -0500 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:52550 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932769AbdKFXy3 (ORCPT ); Mon, 6 Nov 2017 18:54:29 -0500 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "Stephen Hemminger" , "stephen hemminger" , "David S. Miller" Date: Mon, 06 Nov 2017 23:03:02 +0000 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) Subject: [PATCH 3.16 142/294] netvsc: fix deadlock betwen link status and removal In-Reply-To: X-SA-Exim-Connect-IP: 2a02:8011:400e:2:6f00:88c8:c921:d332 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.16.50-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: stephen hemminger commit 9b4e946ce14e20d7addbfb7d9139e604f9fda107 upstream. There is a deadlock possible when canceling the link status delayed work queue. The removal process is run with RTNL held, and the link status callback is acquring RTNL. Resolve the issue by using trylock and rescheduling. If cancel is in process, that block it from happening. Fixes: 122a5f6410f4 ("staging: hv: use delayed_work for netvsc_send_garp()") Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller [bwh: Backported to 3.16: - Move assignment of ndev_ctx before this new use - LINKCHANGE_INT is not defined; substitute its upstream definition] Signed-off-by: Ben Hutchings --- --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -777,9 +777,14 @@ static void netvsc_link_change(struct wo struct rndis_device *rdev; bool notify; - rtnl_lock(); - ndev_ctx = container_of(w, struct net_device_context, dwork.work); + + /* if changes are happening, comeback later */ + if (!rtnl_trylock()) { + schedule_delayed_work(&ndev_ctx->dwork, 2 * HZ); + return; + } + net_device = hv_get_drvdata(ndev_ctx->device_ctx); rdev = net_device->extension; net = net_device->ndev;