From patchwork Wed Aug 28 04:20:38 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ding Tianhong X-Patchwork-Id: 270322 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 820A92C009C for ; Wed, 28 Aug 2013 14:21:32 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753328Ab3H1EVS (ORCPT ); Wed, 28 Aug 2013 00:21:18 -0400 Received: from szxga01-in.huawei.com ([119.145.14.64]:5148 "EHLO szxga01-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752764Ab3H1EVQ (ORCPT ); Wed, 28 Aug 2013 00:21:16 -0400 Received: from 172.24.2.119 (EHLO szxeml207-edg.china.huawei.com) ([172.24.2.119]) by szxrg01-dlp.huawei.com (MOS 4.3.4-GA FastPath queued) with ESMTP id BHK01146; Wed, 28 Aug 2013 12:20:54 +0800 (CST) Received: from SZXEML448-HUB.china.huawei.com (10.82.67.191) by szxeml207-edg.china.huawei.com (172.24.2.56) with Microsoft SMTP Server (TLS) id 14.1.323.7; Wed, 28 Aug 2013 12:20:50 +0800 Received: from [127.0.0.1] (10.135.72.199) by szxeml448-hub.china.huawei.com (10.82.67.191) with Microsoft SMTP Server id 14.1.323.7; Wed, 28 Aug 2013 12:20:49 +0800 Message-ID: <521D7A96.9070904@huawei.com> Date: Wed, 28 Aug 2013 12:20:38 +0800 From: Ding Tianhong User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:17.0) Gecko/20130801 Thunderbird/17.0.8 MIME-Version: 1.0 To: Jay Vosburgh , Andy Gospodarek , "David S. Miller" , Nikolay Aleksandrov , Veaceslav Falico , Netdev Subject: [PATCH 1/5] bonding: simplify and use RCU protection for 3ad xmit path 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 commit 278b20837511776dc9d5f6ee1c7fabd5479838bb (bonding: initial RCU conversion) has convert the roundrobin, active-backup, broadcast and xor xmit path to rcu protection, the performance will be better for these mode, so this time, convert xmit path for 3ad mode. Signed-off-by: Ding Tianhong Signed-off-by: Wang Yufen Cc: Nikolay Aleksandrov Cc: Veaceslav Falico --- drivers/net/bonding/bond_3ad.c | 31 +++++++++++++------------------ drivers/net/bonding/bonding.h | 22 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 9010265..52d76a4 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -143,7 +143,7 @@ static inline struct bonding *__get_bond_by_port(struct port *port) */ static inline struct port *__get_first_port(struct bonding *bond) { - struct slave *first_slave = bond_first_slave(bond); + struct slave *first_slave = bond_first_slave_rcu(bond); return first_slave ? &(SLAVE_AD_INFO(first_slave).port) : NULL; } @@ -163,7 +163,7 @@ static inline struct port *__get_next_port(struct port *port) // If there's no bond for this port, or this is the last slave if (bond == NULL) return NULL; - slave_next = bond_next_slave(bond, slave); + slave_next = bond_next_slave_rcu(bond, slave); if (!slave_next || bond_is_first_slave(bond, slave_next)) return NULL; @@ -2417,16 +2417,14 @@ int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info) int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev) { - struct slave *slave, *start_at; + struct slave *slave; struct bonding *bond = netdev_priv(dev); int slave_agg_no; int slaves_in_agg; int agg_id; - int i; struct ad_info ad_info; int res = 1; - read_lock(&bond->lock); if (__bond_3ad_get_active_agg_info(bond, &ad_info)) { pr_debug("%s: Error: __bond_3ad_get_active_agg_info failed\n", dev->name); @@ -2444,13 +2442,16 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev) slave_agg_no = bond->xmit_hash_policy(skb, slaves_in_agg); - bond_for_each_slave(bond, slave) { + bond_for_each_slave_rcu(bond, slave) { struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator; if (agg && (agg->aggregator_identifier == agg_id)) { - slave_agg_no--; - if (slave_agg_no < 0) - break; + if (--slave_agg_no < 0) { + if (SLAVE_IS_OK(slave)) { + res = bond_dev_queue_xmit(bond, skb, slave->dev); + goto out; + } + } } } @@ -2460,23 +2461,17 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev) goto out; } - start_at = slave; - - bond_for_each_slave_from(bond, slave, i, start_at) { - int slave_agg_id = 0; + bond_for_each_slave_rcu(bond, slave) { struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator; - if (agg) - slave_agg_id = agg->aggregator_identifier; - - if (SLAVE_IS_OK(slave) && agg && (slave_agg_id == agg_id)) { + if (SLAVE_IS_OK(slave) && agg && + (agg->aggregator_identifier == agg_id)) { res = bond_dev_queue_xmit(bond, skb, slave->dev); break; } } out: - read_unlock(&bond->lock); if (res) { /* no suitable interface, frame not sent */ kfree_skb(skb); diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 4bf52d5..ecb5d1d 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -74,6 +74,9 @@ /* slave list primitives */ #define bond_to_slave(ptr) list_entry(ptr, struct slave, list) +/* slave list primitives, Caller must hold rcu_read_lock */ +#define bond_to_slave_rcu(ptr) list_entry_rcu(ptr, struct slave, list) + /* IMPORTANT: bond_first/last_slave can return NULL in case of an empty list */ #define bond_first_slave(bond) \ list_first_entry_or_null(&(bond)->slave_list, struct slave, list) @@ -81,6 +84,16 @@ (list_empty(&(bond)->slave_list) ? NULL : \ bond_to_slave((bond)->slave_list.prev)) +/** + * IMPORTANT: bond_first/last_slave_rcu can return NULL in case of an empty list + * Caller must hold rcu_read_lock + */ +#define bond_first_slave_rcu(bond) \ + list_first_or_null_rcu(&(bond)->slave_list, struct slave, list) +#define bond_last_slave_rcu(bond) \ + (list_emptry(&(bond)->slave_list) ? NULL : \ + bond_to_slave_rcu((bond)->slave_list.prev)) + #define bond_is_first_slave(bond, pos) ((pos)->list.prev == &(bond)->slave_list) #define bond_is_last_slave(bond, pos) ((pos)->list.next == &(bond)->slave_list) @@ -93,6 +106,15 @@ (bond_is_first_slave(bond, pos) ? bond_last_slave(bond) : \ bond_to_slave((pos)->list.prev)) +/* Since bond_first/last_slave_rcu can return NULL, these can return NULL too */ +#define bond_next_slave_rcu(bond, pos) \ + (bond_is_last_slave(bond, pos) ? bond_first_slave_rcu(bond) : \ + bond_to_slave_rcu((pos)->list.next)) + +#define bond_prev_slave_rcu(bond, pos) \ + (bond_is_first_slave(bond, pos) ? bond_last_slave_rcu(bond) : \ + bond_to_slave_rcu((pos)->list.prev)) + /** * bond_for_each_slave_from - iterate the slaves list from a starting point * @bond: the bond holding this list.