All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ding Tianhong <dthxman@gmail.com>
To: Nikolay Aleksandrov <nikolay@redhat.com>
Cc: Ding Tianhong <dingtianhong@huawei.com>,
	Jay Vosburgh <fubar@us.ibm.com>,
	Andy Gospodarek <andy@greyhouse.net>,
	"David S. Miller" <davem@davemloft.net>,
	Veaceslav Falico <vfalico@redhat.com>,
	Netdev <netdev@vger.kernel.org>
Subject: Re: [PATCH net-next v2 6/10] bonding: rebuild the lock use for bond_activebackup_arp_mon()
Date: Sat, 09 Nov 2013 22:08:53 +0800	[thread overview]
Message-ID: <527E41F5.4060608@gmail.com> (raw)
In-Reply-To: <527D0AEF.1060802@redhat.com>

于 2013/11/9 0:01, Nikolay Aleksandrov 写道:
> On 11/08/2013 03:08 AM, Ding Tianhong wrote:
>> 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 <fubar@us.ibm.com>
>> Suggested-by: Veaceslav Falico <vfalico@redhat.com>
>> Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
>> ---
>>   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);
> Again, bond_should_notify_peers() is not RCU-safe.

yes.
>>   
>>   	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);
> Generally you might be safe in bond_ab_arp_probe() due to the synchronization
> done by netdev_rx_handler_unregister(), but this code may run after that (and
> after the unlinked slave) but before current_arp_slave is set to NULL and thus
> use it. Now I don't see a direct problem with that, only a complication that can
> bite us later. I vaguely remember that I re-worked the bond_ab_arp_probe() and
> the way current_arp_slave works when doing this transition in my patches.

maybe I miss the patch, pls send me the commit and I will check it again.
>> +	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; \
>> +	 })
>> +
> Honestly, I don't like this, it sure can be re-written in a more
> straight-forward manner.

ok, I will re-write it and make it more comfortable.

Regards.
Ding

>>   #define bond_is_first_slave(bond, pos) (pos == bond_first_slave(bond))
>>   #define bond_is_last_slave(bond, pos) (pos == bond_last_slave(bond))
>>   
>>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

  reply	other threads:[~2013-11-09 14:19 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-11-08  2:08 [PATCH net-next v2 6/10] bonding: rebuild the lock use for bond_activebackup_arp_mon() Ding Tianhong
2013-11-08 16:01 ` Nikolay Aleksandrov
2013-11-09 14:08   ` Ding Tianhong [this message]
2013-11-10  4:08   ` Ding Tianhong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=527E41F5.4060608@gmail.com \
    --to=dthxman@gmail.com \
    --cc=andy@greyhouse.net \
    --cc=davem@davemloft.net \
    --cc=dingtianhong@huawei.com \
    --cc=fubar@us.ibm.com \
    --cc=netdev@vger.kernel.org \
    --cc=nikolay@redhat.com \
    --cc=vfalico@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.