From patchwork Tue May 19 23:24:52 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Baptiste Covolato X-Patchwork-Id: 474091 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 35074140077 for ; Wed, 20 May 2015 09:25:29 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=arista.com header.i=@arista.com header.b=OfBpVLwR; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751418AbbESXZY (ORCPT ); Tue, 19 May 2015 19:25:24 -0400 Received: from mail-pd0-f171.google.com ([209.85.192.171]:35236 "EHLO mail-pd0-f171.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751281AbbESXZU (ORCPT ); Tue, 19 May 2015 19:25:20 -0400 Received: by pdea3 with SMTP id a3so44649829pde.2 for ; Tue, 19 May 2015 16:25:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=arista.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=rHwxIdubrsxQuIWWmvaDIUtmZXrPP++FSO63qui91vI=; b=OfBpVLwREPVupCcMunqnUD6FbIh/dPgAE9IZ+3R0YGpc6moHpPYeBibY8KecA9xO/i IDuGm9DhmjY/Tpqg16BPz92w7GO9DgFB58lDH6uaevllp9pWS7oQXg/T25J0P7liu/eg 7XMeu95N9ABzW/JPG34coqfXCc5fTqYdq5xRE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=rHwxIdubrsxQuIWWmvaDIUtmZXrPP++FSO63qui91vI=; b=aB3NXiiKpnvGoVvcsMMUSXD1nhcroql4dgPr7c4N7iFMZeWFC8mPGsNp4B6VM6aB8P CaUCH2XU9umwwGwz70y4v+LSH2vMR4Zd2hCuGLQJmdwtvCL/90BsGkfnfNJpOKLum6vE CIGbNREAz0cBWv8dRtgxglms34w8vfPDY5fqIAXIXMJIhYCmau5F5qCmsg3FEdntHM26 YvA3ALMZHujh0qPRH7ZRkk7c0qdq5LOqkWKW2PjL06gIdr9KRf/PMBF0FSjB8nqADuVu 2PIKtviQqCFummBKWF5QMz7K1O/YvHO10Z6wuaLJM/fm9uI6Y9pQOjm65HFffjRZfRyv o2lg== X-Gm-Message-State: ALoCoQmN/cFVTcIGG5Zxikz1A6kNEw3PXdkYjxkdCjH7nh5veq+eWPibBEkKG2Q5EbHX96Gnz8/N X-Received: by 10.68.219.101 with SMTP id pn5mr58784545pbc.77.1432077919795; Tue, 19 May 2015 16:25:19 -0700 (PDT) Received: from localhost.localdomain ([12.154.11.242]) by mx.google.com with ESMTPSA id eo3sm14079962pbd.66.2015.05.19.16.25.18 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 19 May 2015 16:25:19 -0700 (PDT) From: Baptiste Covolato To: "David S. Miller" , netdev@vger.kernel.org Cc: Francesco Ruggeri , Eric Mowat , Adrien Schildknecht Subject: [PATCH net-next 2/3] net: Inline netdev_wait_allrefs inside netdev_run_todo Date: Tue, 19 May 2015 16:24:52 -0700 Message-Id: <1432077893-4431-3-git-send-email-baptiste@arista.com> X-Mailer: git-send-email 2.4.1 In-Reply-To: <1432077893-4431-1-git-send-email-baptiste@arista.com> References: <1432077893-4431-1-git-send-email-baptiste@arista.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Make netdev_wait_allrefs part of netdev_run_todo Signed-off-by: Baptiste Covolato Signed-off-by: Francesco Ruggeri --- net/core/dev.c | 110 ++++++++++++++++++++++++--------------------------------- 1 file changed, 47 insertions(+), 63 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index db59d18..9b0814b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -6671,68 +6671,6 @@ int netdev_refcnt_read(const struct net_device *dev) } EXPORT_SYMBOL(netdev_refcnt_read); -/** - * netdev_wait_allrefs - wait until all references are gone. - * @dev: target net_device - * - * This is called when unregistering network devices. - * - * Any protocol or device that holds a reference should register - * for netdevice notification, and cleanup and put back the - * reference if they receive an UNREGISTER event. - * We can get stuck here if buggy protocols don't correctly - * call dev_put. - */ -static void netdev_wait_allrefs(struct net_device *dev) -{ - unsigned long rebroadcast_time, warning_time; - int refcnt; - - linkwatch_forget_dev(dev); - - rebroadcast_time = warning_time = jiffies; - refcnt = netdev_refcnt_read(dev); - - while (refcnt != 0) { - if (time_after(jiffies, rebroadcast_time + 1 * HZ)) { - rtnl_lock(); - - /* Rebroadcast unregister notification */ - call_netdevice_notifiers(NETDEV_UNREGISTER, dev); - - __rtnl_unlock(); - rcu_barrier(); - rtnl_lock(); - - call_netdevice_notifiers(NETDEV_UNREGISTER_FINAL, dev); - if (test_bit(__LINK_STATE_LINKWATCH_PENDING, - &dev->state)) { - /* We must not have linkwatch events - * pending on unregister. If this - * happens, we simply run the queue - * unscheduled, resulting in a noop - * for this device. - */ - linkwatch_run_queue(); - } - - __rtnl_unlock(); - - rebroadcast_time = jiffies; - } - - msleep(250); - - refcnt = netdev_refcnt_read(dev); - - if (time_after(jiffies, warning_time + 10 * HZ)) { - pr_emerg("unregister_netdevice: waiting for %s to become free. Usage count = %d\n", - dev->name, refcnt); - warning_time = jiffies; - } - } -} - /* The sequence is: * * rtnl_lock(); @@ -6760,6 +6698,7 @@ static void netdev_wait_allrefs(struct net_device *dev) void netdev_run_todo(void) { struct list_head list; + unsigned long rebroadcast_time, warning_time; /* Snapshot list, allow later requests */ list_replace_init(&net_todo_list, &list); @@ -6772,6 +6711,7 @@ void netdev_run_todo(void) rcu_barrier(); while (!list_empty(&list)) { + int refcnt; struct net_device *dev = list_first_entry(&list, struct net_device, todo_list); list_del(&dev->todo_list); @@ -6791,7 +6731,51 @@ void netdev_run_todo(void) on_each_cpu(flush_backlog, NULL, 1); - netdev_wait_allrefs(dev); + linkwatch_forget_dev(dev); + + rebroadcast_time = warning_time = jiffies; + refcnt = netdev_refcnt_read(dev); + + while (refcnt != 0) { + if (time_after(jiffies, rebroadcast_time + 1 * HZ)) { + rtnl_lock(); + + /* Rebroadcast unregister notification */ + call_netdevice_notifiers(NETDEV_UNREGISTER, + dev); + + __rtnl_unlock(); + rcu_barrier(); + rtnl_lock(); + + call_netdevice_notifiers( + NETDEV_UNREGISTER_FINAL, dev); + if (test_bit(__LINK_STATE_LINKWATCH_PENDING, + &dev->state)) { + /* We must not have linkwatch events + * pending on unregister. If this + * happens, we simply run the queue + * unscheduled, resulting in a noop + * for this device. + */ + linkwatch_run_queue(); + } + + __rtnl_unlock(); + + rebroadcast_time = jiffies; + } + + msleep(250); + + refcnt = netdev_refcnt_read(dev); + + if (time_after(jiffies, warning_time + 10 * HZ)) { + pr_emerg("unregister_netdevice: waiting for %s to become free. Usage count = %d\n", + dev->name, refcnt); + warning_time = jiffies; + } + } /* paranoia */ BUG_ON(netdev_refcnt_read(dev));