Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

t Merge branch 'a-series-of-minor-optimizations-of-the-bonding-module'

Tonghao Zhang says:

====================
A series of minor optimizations of the bonding module

These patches mainly target the peer notify mechanism of the bonding module.
Including updates of peer notify, lock races, etc. For more information, please
refer to the patch.

Cc: Jay Vosburgh <jv@jvosburgh.net>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Andrew Lunn <andrew+netdev@lunn.ch>
Cc: Nikolay Aleksandrov <razor@blackwall.org>
Cc: Hangbin Liu <liuhangbin@gmail.com>
Cc: Jason Xing <kerneljasonxing@gmail.com>
====================

Link: https://patch.msgid.link/cover.1768709239.git.tonghao@bamaicloud.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+76 -48
+2 -5
drivers/net/bonding/bond_3ad.c
··· 1017 1017 { 1018 1018 struct bonding *bond = port->slave->bond; 1019 1019 1020 - if (bond->params.broadcast_neighbor && rtnl_trylock()) { 1021 - bond->send_peer_notif = bond->params.num_peer_notif * 1022 - max(1, bond->params.peer_notif_delay); 1023 - rtnl_unlock(); 1024 - } 1020 + if (bond->params.broadcast_neighbor) 1021 + bond_peer_notify_work_rearm(bond, 0); 1025 1022 } 1026 1023 1027 1024 /**
+72 -43
drivers/net/bonding/bond_main.c
··· 1195 1195 return true; 1196 1196 } 1197 1197 1198 + /* Use this to update send_peer_notif when RTNL may be held in other places. */ 1199 + void bond_peer_notify_work_rearm(struct bonding *bond, unsigned long delay) 1200 + { 1201 + queue_delayed_work(bond->wq, &bond->peer_notify_work, delay); 1202 + } 1203 + 1204 + /* Peer notify update handler. Holds only RTNL */ 1205 + static void bond_peer_notify_reset(struct bonding *bond) 1206 + { 1207 + WRITE_ONCE(bond->send_peer_notif, 1208 + bond->params.num_peer_notif * 1209 + max(1, bond->params.peer_notif_delay)); 1210 + } 1211 + 1212 + static void bond_peer_notify_handler(struct work_struct *work) 1213 + { 1214 + struct bonding *bond = container_of(work, struct bonding, 1215 + peer_notify_work.work); 1216 + 1217 + if (!rtnl_trylock()) { 1218 + bond_peer_notify_work_rearm(bond, 1); 1219 + return; 1220 + } 1221 + 1222 + bond_peer_notify_reset(bond); 1223 + 1224 + rtnl_unlock(); 1225 + } 1226 + 1227 + /* Peer notify events post. Holds only RTNL */ 1228 + static void bond_peer_notify_may_events(struct bonding *bond, bool force) 1229 + { 1230 + bool notified = false; 1231 + 1232 + if (bond_should_notify_peers(bond)) { 1233 + notified = true; 1234 + call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, bond->dev); 1235 + } 1236 + 1237 + if (notified || force) 1238 + bond->send_peer_notif--; 1239 + } 1240 + 1198 1241 /** 1199 1242 * bond_change_active_slave - change the active slave into the specified one 1200 1243 * @bond: our bonding struct ··· 1313 1270 BOND_SLAVE_NOTIFY_NOW); 1314 1271 1315 1272 if (new_active) { 1316 - bool should_notify_peers = false; 1317 - 1318 1273 bond_set_slave_active_flags(new_active, 1319 1274 BOND_SLAVE_NOTIFY_NOW); 1320 1275 ··· 1320 1279 bond_do_fail_over_mac(bond, new_active, 1321 1280 old_active); 1322 1281 1323 - if (netif_running(bond->dev)) { 1324 - bond->send_peer_notif = 1325 - bond->params.num_peer_notif * 1326 - max(1, bond->params.peer_notif_delay); 1327 - should_notify_peers = 1328 - bond_should_notify_peers(bond); 1329 - } 1330 - 1331 1282 call_netdevice_notifiers(NETDEV_BONDING_FAILOVER, bond->dev); 1332 - if (should_notify_peers) { 1333 - bond->send_peer_notif--; 1334 - call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, 1335 - bond->dev); 1283 + 1284 + if (netif_running(bond->dev)) { 1285 + bond_peer_notify_reset(bond); 1286 + bond_peer_notify_may_events(bond, false); 1336 1287 } 1337 1288 } 1338 1289 } ··· 2817 2784 { 2818 2785 struct bonding *bond = container_of(work, struct bonding, 2819 2786 mii_work.work); 2820 - bool should_notify_peers; 2821 - bool commit; 2822 - unsigned long delay; 2823 - struct slave *slave; 2824 2787 struct list_head *iter; 2788 + struct slave *slave; 2789 + unsigned long delay; 2790 + bool commit; 2825 2791 2826 2792 delay = msecs_to_jiffies(bond->params.miimon); 2827 2793 ··· 2829 2797 2830 2798 rcu_read_lock(); 2831 2799 2832 - should_notify_peers = bond_should_notify_peers(bond); 2833 2800 commit = !!bond_miimon_inspect(bond); 2834 2801 2835 2802 rcu_read_unlock(); 2836 2803 2837 - if (commit || bond->send_peer_notif) { 2804 + if (commit || READ_ONCE(bond->send_peer_notif)) { 2838 2805 /* Race avoidance with bond_close cancel of workqueue */ 2839 2806 if (!rtnl_trylock()) { 2840 2807 delay = 1; ··· 2848 2817 bond_miimon_commit(bond); 2849 2818 } 2850 2819 2851 - if (bond->send_peer_notif) { 2852 - bond->send_peer_notif--; 2853 - if (should_notify_peers) 2854 - call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, 2855 - bond->dev); 2856 - } 2820 + if (bond->send_peer_notif) 2821 + bond_peer_notify_may_events(bond, true); 2857 2822 2858 2823 rtnl_unlock(); /* might sleep, hold no other locks */ 2859 2824 } ··· 3760 3733 3761 3734 static void bond_activebackup_arp_mon(struct bonding *bond) 3762 3735 { 3763 - bool should_notify_peers = false; 3764 - bool should_notify_rtnl = false; 3736 + bool should_notify_rtnl; 3765 3737 int delta_in_ticks; 3766 3738 3767 3739 delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval); ··· 3770 3744 3771 3745 rcu_read_lock(); 3772 3746 3773 - should_notify_peers = bond_should_notify_peers(bond); 3774 - 3775 3747 if (bond_ab_arp_inspect(bond)) { 3776 3748 rcu_read_unlock(); 3777 3749 3778 3750 /* Race avoidance with bond_close flush of workqueue */ 3779 3751 if (!rtnl_trylock()) { 3780 3752 delta_in_ticks = 1; 3781 - should_notify_peers = false; 3782 3753 goto re_arm; 3783 3754 } 3784 3755 ··· 3788 3765 should_notify_rtnl = bond_ab_arp_probe(bond); 3789 3766 rcu_read_unlock(); 3790 3767 3791 - re_arm: 3792 - if (bond->params.arp_interval) 3793 - queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks); 3794 - 3795 - if (should_notify_peers || should_notify_rtnl) { 3796 - if (!rtnl_trylock()) 3797 - return; 3798 - 3799 - if (should_notify_peers) { 3800 - bond->send_peer_notif--; 3801 - call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, 3802 - bond->dev); 3768 + if (READ_ONCE(bond->send_peer_notif) || should_notify_rtnl) { 3769 + if (!rtnl_trylock()) { 3770 + delta_in_ticks = 1; 3771 + goto re_arm; 3803 3772 } 3773 + 3774 + if (bond->send_peer_notif) 3775 + bond_peer_notify_may_events(bond, true); 3776 + 3804 3777 if (should_notify_rtnl) { 3805 3778 bond_slave_state_notify(bond); 3806 3779 bond_slave_link_notify(bond); ··· 3804 3785 3805 3786 rtnl_unlock(); 3806 3787 } 3788 + 3789 + re_arm: 3790 + if (bond->params.arp_interval) 3791 + queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks); 3807 3792 } 3808 3793 3809 3794 static void bond_arp_monitor(struct work_struct *work) ··· 4236 4213 4237 4214 void bond_work_init_all(struct bonding *bond) 4238 4215 { 4216 + /* ndo_stop, bond_close() will try to flush the work under 4217 + * the rtnl lock. The workqueue must not block on rtnl lock 4218 + * to avoid deadlock. 4219 + */ 4239 4220 INIT_DELAYED_WORK(&bond->mcast_work, 4240 4221 bond_resend_igmp_join_requests_delayed); 4241 4222 INIT_DELAYED_WORK(&bond->alb_work, bond_alb_monitor); ··· 4247 4220 INIT_DELAYED_WORK(&bond->arp_work, bond_arp_monitor); 4248 4221 INIT_DELAYED_WORK(&bond->ad_work, bond_3ad_state_machine_handler); 4249 4222 INIT_DELAYED_WORK(&bond->slave_arr_work, bond_slave_arr_handler); 4223 + INIT_DELAYED_WORK(&bond->peer_notify_work, bond_peer_notify_handler); 4250 4224 } 4251 4225 4252 4226 void bond_work_cancel_all(struct bonding *bond) ··· 4258 4230 cancel_delayed_work_sync(&bond->ad_work); 4259 4231 cancel_delayed_work_sync(&bond->mcast_work); 4260 4232 cancel_delayed_work_sync(&bond->slave_arr_work); 4233 + cancel_delayed_work_sync(&bond->peer_notify_work); 4261 4234 } 4262 4235 4263 4236 static int bond_open(struct net_device *bond_dev)
+2
include/net/bonding.h
··· 254 254 struct delayed_work ad_work; 255 255 struct delayed_work mcast_work; 256 256 struct delayed_work slave_arr_work; 257 + struct delayed_work peer_notify_work; 257 258 #ifdef CONFIG_DEBUG_FS 258 259 /* debugging support via debugfs */ 259 260 struct dentry *debug_dir; ··· 710 709 int level); 711 710 int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave); 712 711 void bond_slave_arr_work_rearm(struct bonding *bond, unsigned long delay); 712 + void bond_peer_notify_work_rearm(struct bonding *bond, unsigned long delay); 713 713 void bond_work_init_all(struct bonding *bond); 714 714 void bond_work_cancel_all(struct bonding *bond); 715 715