From patchwork Fri Nov 8 02:08:04 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ding Tianhong X-Patchwork-Id: 289562 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 C49AF2C00C4 for ; Fri, 8 Nov 2013 13:09:03 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756546Ab3KHCI7 (ORCPT ); Thu, 7 Nov 2013 21:08:59 -0500 Received: from szxga01-in.huawei.com ([119.145.14.64]:26448 "EHLO szxga01-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756539Ab3KHCI5 (ORCPT ); Thu, 7 Nov 2013 21:08:57 -0500 Received: from 172.24.2.119 (EHLO szxeml207-edg.china.huawei.com) ([172.24.2.119]) by szxrg01-dlp.huawei.com (MOS 4.3.7-GA FastPath queued) with ESMTP id BMG78752; Fri, 08 Nov 2013 10:08:09 +0800 (CST) Received: from SZXEML409-HUB.china.huawei.com (10.82.67.136) by szxeml207-edg.china.huawei.com (172.24.2.56) with Microsoft SMTP Server (TLS) id 14.3.158.1; Fri, 8 Nov 2013 10:08:05 +0800 Received: from [127.0.0.1] (10.135.72.199) by szxeml409-hub.china.huawei.com (10.82.67.136) with Microsoft SMTP Server id 14.3.158.1; Fri, 8 Nov 2013 10:08:05 +0800 Message-ID: <527C4784.1030402@huawei.com> Date: Fri, 8 Nov 2013 10:08:04 +0800 From: Ding Tianhong User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:24.0) Gecko/20100101 Thunderbird/24.0.1 MIME-Version: 1.0 To: Jay Vosburgh , Andy Gospodarek , "David S. Miller" , Nikolay Aleksandrov , Veaceslav Falico , Netdev Subject: [PATCH net-next v2 6/10] bonding: rebuild the lock use for bond_activebackup_arp_mon() X-Originating-IP: [10.135.72.199] X-CFilter-Loop: Reflected Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The bond_activebackup_arp_mon() use the bond lock for read to protect the slave list, it is no effect, and the RTNL is only called for bond_ab_arp_commit() and peer notify, for the performance better, use RCU instead of the bond lock, because the bond slave list need to called in RCU, add a new bond_first_slave_rcu() to get the first slave in RCU protection. When bond_ab_arp_inspect() and should_notify_peers is true, the RTNL will called twice, it is a loss of performance, so make the two RTNL together to avoid performance loss. Suggested-by: Jay Vosburgh Suggested-by: Veaceslav Falico Signed-off-by: Ding Tianhong --- drivers/net/bonding/bond_main.c | 35 +++++++++++++++++++---------------- drivers/net/bonding/bonding.h | 7 +++++++ 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 759dcd0..b48ca55 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2524,7 +2524,7 @@ static int bond_ab_arp_inspect(struct bonding *bond) struct slave *slave; int commit = 0; - bond_for_each_slave(bond, slave, iter) { + bond_for_each_slave_rcu(bond, slave, iter) { slave->new_link = BOND_LINK_NOCHANGE; last_rx = slave_last_rx(bond, slave); @@ -2586,7 +2586,7 @@ static int bond_ab_arp_inspect(struct bonding *bond) * Called to commit link state changes noted by inspection step of * active-backup mode ARP monitor. * - * Called with RTNL and bond->lock for read. + * Called with RTNL hold. */ static void bond_ab_arp_commit(struct bonding *bond) { @@ -2661,7 +2661,7 @@ do_failover: /* * Send ARP probes for active-backup mode ARP monitor. * - * Called with bond->lock held for read. + * Called with rcu_read_lock hold. */ static void bond_ab_arp_probe(struct bonding *bond) { @@ -2690,14 +2690,14 @@ static void bond_ab_arp_probe(struct bonding *bond) */ if (!bond->current_arp_slave) { - bond->current_arp_slave = bond_first_slave(bond); + bond->current_arp_slave = bond_first_slave_rcu(bond); if (!bond->current_arp_slave) return; } bond_set_slave_inactive_flags(bond->current_arp_slave); - bond_for_each_slave(bond, slave, iter) { + bond_for_each_slave_rcu(bond, slave, iter) { if (!found && !before && IS_UP(slave->dev)) before = slave; @@ -2745,43 +2745,46 @@ void bond_activebackup_arp_mon(struct work_struct *work) bool should_notify_peers = false; int delta_in_ticks; - read_lock(&bond->lock); - delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval); - if (!bond_has_slaves(bond)) + rcu_read_lock(); + + if (!bond_has_slaves_rcu(bond)) { + rcu_read_unlock(); goto re_arm; + } should_notify_peers = bond_should_notify_peers(bond); if (bond_ab_arp_inspect(bond)) { - read_unlock(&bond->lock); + rcu_read_unlock(); /* Race avoidance with bond_close flush of workqueue */ if (!rtnl_trylock()) { - read_lock(&bond->lock); delta_in_ticks = 1; should_notify_peers = false; goto re_arm; } - read_lock(&bond->lock); - bond_ab_arp_commit(bond); - read_unlock(&bond->lock); + if (should_notify_peers) { + call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, + bond->dev); + should_notify_peers = false; + } + rtnl_unlock(); - read_lock(&bond->lock); + rcu_read_lock(); } bond_ab_arp_probe(bond); + rcu_read_unlock(); re_arm: if (bond->params.arp_interval) queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks); - read_unlock(&bond->lock); - if (should_notify_peers) { if (!rtnl_trylock()) return; diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index deb9738..90b745c 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -97,6 +97,13 @@ netdev_adjacent_get_private(bond_slave_list(bond)->prev) : \ NULL) +#define bond_first_slave_rcu(bond) \ + ({struct list_head *__ptr = (bond_slave_list(bond)); \ + struct list_head *__next = ACCESS_ONCE(__ptr->next); \ + likely(__ptr != __next) ? \ + netdev_adjacent_get_private_rcu(__next) : NULL; \ + }) + #define bond_is_first_slave(bond, pos) (pos == bond_first_slave(bond)) #define bond_is_last_slave(bond, pos) (pos == bond_last_slave(bond))