Skip to content

Commit 3ce82b1

Browse files
hao022gregkh
authored andcommitted
net: bonding: fix possible peer notify event loss or dup issue
commit 10843e1 upstream. If the send_peer_notif counter and the peer event notify are not synchronized. It may cause problems such as the loss or dup of peer notify event. Before this patch: - If should_notify_peers is true and the lock for send_peer_notif-- fails, peer event may be sent again in next mii_monitor loop, because should_notify_peers is still true. - If should_notify_peers is true and the lock for send_peer_notif-- succeeded, but the lock for peer event fails, the peer event will be lost. This patch locks the RTNL for send_peer_notif, events, and commit simultaneously. Fixes: 07a4dde ("bonding: add an option to specify a delay between peer notifications") Cc: Jay Vosburgh <[email protected]> Cc: Andrew Lunn <[email protected]> Cc: Eric Dumazet <[email protected]> Cc: Jakub Kicinski <[email protected]> Cc: Paolo Abeni <[email protected]> Cc: Hangbin Liu <[email protected]> Cc: Nikolay Aleksandrov <[email protected]> Cc: Vincent Bernat <[email protected]> Cc: <[email protected]> Signed-off-by: Tonghao Zhang <[email protected]> Acked-by: Jay Vosburgh <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 3f307a9 commit 3ce82b1

File tree

1 file changed

+18
-22
lines changed

1 file changed

+18
-22
lines changed

drivers/net/bonding/bond_main.c

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2951,7 +2951,7 @@ static void bond_mii_monitor(struct work_struct *work)
29512951
{
29522952
struct bonding *bond = container_of(work, struct bonding,
29532953
mii_work.work);
2954-
bool should_notify_peers = false;
2954+
bool should_notify_peers;
29552955
bool commit;
29562956
unsigned long delay;
29572957
struct slave *slave;
@@ -2963,44 +2963,40 @@ static void bond_mii_monitor(struct work_struct *work)
29632963
goto re_arm;
29642964

29652965
rcu_read_lock();
2966+
29662967
should_notify_peers = bond_should_notify_peers(bond);
29672968
commit = !!bond_miimon_inspect(bond);
2968-
if (bond->send_peer_notif) {
2969-
rcu_read_unlock();
2970-
if (rtnl_trylock()) {
2971-
bond->send_peer_notif--;
2972-
rtnl_unlock();
2973-
}
2974-
} else {
2975-
rcu_read_unlock();
2976-
}
29772969

2978-
if (commit) {
2970+
rcu_read_unlock();
2971+
2972+
if (commit || bond->send_peer_notif) {
29792973
/* Race avoidance with bond_close cancel of workqueue */
29802974
if (!rtnl_trylock()) {
29812975
delay = 1;
2982-
should_notify_peers = false;
29832976
goto re_arm;
29842977
}
29852978

2986-
bond_for_each_slave(bond, slave, iter) {
2987-
bond_commit_link_state(slave, BOND_SLAVE_NOTIFY_LATER);
2979+
if (commit) {
2980+
bond_for_each_slave(bond, slave, iter) {
2981+
bond_commit_link_state(slave,
2982+
BOND_SLAVE_NOTIFY_LATER);
2983+
}
2984+
bond_miimon_commit(bond);
2985+
}
2986+
2987+
if (bond->send_peer_notif) {
2988+
bond->send_peer_notif--;
2989+
if (should_notify_peers)
2990+
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS,
2991+
bond->dev);
29882992
}
2989-
bond_miimon_commit(bond);
29902993

29912994
rtnl_unlock(); /* might sleep, hold no other locks */
29922995
}
29932996

29942997
re_arm:
29952998
if (bond->params.miimon)
29962999
queue_delayed_work(bond->wq, &bond->mii_work, delay);
2997-
2998-
if (should_notify_peers) {
2999-
if (!rtnl_trylock())
3000-
return;
3001-
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, bond->dev);
3002-
rtnl_unlock();
3003-
}
30043000
}
30053001

30063002
static int bond_upper_dev_walk(struct net_device *upper,

0 commit comments

Comments
 (0)