Skip to content

Commit 10843e1

Browse files
hao022Paolo Abeni
authored andcommitted
net: bonding: fix possible peer notify event loss or dup issue
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]>
1 parent c0178ee commit 10843e1

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
@@ -2874,7 +2874,7 @@ static void bond_mii_monitor(struct work_struct *work)
28742874
{
28752875
struct bonding *bond = container_of(work, struct bonding,
28762876
mii_work.work);
2877-
bool should_notify_peers = false;
2877+
bool should_notify_peers;
28782878
bool commit;
28792879
unsigned long delay;
28802880
struct slave *slave;
@@ -2886,44 +2886,40 @@ static void bond_mii_monitor(struct work_struct *work)
28862886
goto re_arm;
28872887

28882888
rcu_read_lock();
2889+
28892890
should_notify_peers = bond_should_notify_peers(bond);
28902891
commit = !!bond_miimon_inspect(bond);
2891-
if (bond->send_peer_notif) {
2892-
rcu_read_unlock();
2893-
if (rtnl_trylock()) {
2894-
bond->send_peer_notif--;
2895-
rtnl_unlock();
2896-
}
2897-
} else {
2898-
rcu_read_unlock();
2899-
}
29002892

2901-
if (commit) {
2893+
rcu_read_unlock();
2894+
2895+
if (commit || bond->send_peer_notif) {
29022896
/* Race avoidance with bond_close cancel of workqueue */
29032897
if (!rtnl_trylock()) {
29042898
delay = 1;
2905-
should_notify_peers = false;
29062899
goto re_arm;
29072900
}
29082901

2909-
bond_for_each_slave(bond, slave, iter) {
2910-
bond_commit_link_state(slave, BOND_SLAVE_NOTIFY_LATER);
2902+
if (commit) {
2903+
bond_for_each_slave(bond, slave, iter) {
2904+
bond_commit_link_state(slave,
2905+
BOND_SLAVE_NOTIFY_LATER);
2906+
}
2907+
bond_miimon_commit(bond);
2908+
}
2909+
2910+
if (bond->send_peer_notif) {
2911+
bond->send_peer_notif--;
2912+
if (should_notify_peers)
2913+
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS,
2914+
bond->dev);
29112915
}
2912-
bond_miimon_commit(bond);
29132916

29142917
rtnl_unlock(); /* might sleep, hold no other locks */
29152918
}
29162919

29172920
re_arm:
29182921
if (bond->params.miimon)
29192922
queue_delayed_work(bond->wq, &bond->mii_work, delay);
2920-
2921-
if (should_notify_peers) {
2922-
if (!rtnl_trylock())
2923-
return;
2924-
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, bond->dev);
2925-
rtnl_unlock();
2926-
}
29272923
}
29282924

29292925
static int bond_upper_dev_walk(struct net_device *upper,

0 commit comments

Comments
 (0)