Skip to content

Commit fb4fa76

Browse files
nhormandavem330
authored andcommitted
net: Convert netpoll blocking api in bonding driver to be a counter
A while back I made some changes to enable netpoll in the bonding driver. Among them was a per-cpu flag that indicated we were in a path that held locks which could cause the netpoll path to block in during tx, and as such the tx path should queue the frame for later use. This appears to have given rise to a regression. If one of those paths on which we hold the per-cpu flag yields the cpu, its possible for us to come back on a different cpu, leading to us clearing a different flag than we set. This results in odd netpoll drops, and BUG backtraces appearing in the log, as we check to make sure that we only clear set bits, and only set clear bits. I had though briefly about changing the offending paths so that they wouldn't sleep, but looking at my origional work more closely, it doesn't appear that a per-cpu flag is warranted. We alrady gate the checking of this flag on IFF_IN_NETPOLL, so we don't hit this in the normal tx case anyway. And practically speaking, the normal use case for netpoll is to only have one client anyway, so we're not going to erroneously queue netpoll frames when its actually safe to do so. As such, lets just convert that per-cpu flag to an atomic counter. It fixes the rescheduling bugs, is equivalent from a performance perspective and actually eliminates some code in the process. Tested by the reporter and myself, successfully Reported-by: Liang Zheng <[email protected]> CC: Jay Vosburgh <[email protected]> CC: Andy Gospodarek <[email protected]> CC: David S. Miller <[email protected]> Signed-off-by: Neil Horman <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 4e085e7 commit fb4fa76

File tree

2 files changed

+9
-20
lines changed

2 files changed

+9
-20
lines changed

drivers/net/bonding/bond_main.c

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ MODULE_PARM_DESC(resend_igmp, "Number of IGMP membership reports to send on link
171171
/*----------------------------- Global variables ----------------------------*/
172172

173173
#ifdef CONFIG_NET_POLL_CONTROLLER
174-
cpumask_var_t netpoll_block_tx;
174+
atomic_t netpoll_block_tx = ATOMIC_INIT(0);
175175
#endif
176176

177177
static const char * const version =
@@ -5299,13 +5299,6 @@ static int __init bonding_init(void)
52995299
if (res)
53005300
goto out;
53015301

5302-
#ifdef CONFIG_NET_POLL_CONTROLLER
5303-
if (!alloc_cpumask_var(&netpoll_block_tx, GFP_KERNEL)) {
5304-
res = -ENOMEM;
5305-
goto out;
5306-
}
5307-
#endif
5308-
53095302
res = register_pernet_subsys(&bond_net_ops);
53105303
if (res)
53115304
goto out;
@@ -5334,9 +5327,6 @@ static int __init bonding_init(void)
53345327
rtnl_link_unregister(&bond_link_ops);
53355328
err_link:
53365329
unregister_pernet_subsys(&bond_net_ops);
5337-
#ifdef CONFIG_NET_POLL_CONTROLLER
5338-
free_cpumask_var(netpoll_block_tx);
5339-
#endif
53405330
goto out;
53415331

53425332
}
@@ -5353,7 +5343,10 @@ static void __exit bonding_exit(void)
53535343
unregister_pernet_subsys(&bond_net_ops);
53545344

53555345
#ifdef CONFIG_NET_POLL_CONTROLLER
5356-
free_cpumask_var(netpoll_block_tx);
5346+
/*
5347+
* Make sure we don't have an imbalance on our netpoll blocking
5348+
*/
5349+
WARN_ON(atomic_read(&netpoll_block_tx));
53575350
#endif
53585351
}
53595352

drivers/net/bonding/bonding.h

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,26 +119,22 @@
119119

120120

121121
#ifdef CONFIG_NET_POLL_CONTROLLER
122-
extern cpumask_var_t netpoll_block_tx;
122+
extern atomic_t netpoll_block_tx;
123123

124124
static inline void block_netpoll_tx(void)
125125
{
126-
preempt_disable();
127-
BUG_ON(cpumask_test_and_set_cpu(smp_processor_id(),
128-
netpoll_block_tx));
126+
atomic_inc(&netpoll_block_tx);
129127
}
130128

131129
static inline void unblock_netpoll_tx(void)
132130
{
133-
BUG_ON(!cpumask_test_and_clear_cpu(smp_processor_id(),
134-
netpoll_block_tx));
135-
preempt_enable();
131+
atomic_dec(&netpoll_block_tx);
136132
}
137133

138134
static inline int is_netpoll_tx_blocked(struct net_device *dev)
139135
{
140136
if (unlikely(dev->priv_flags & IFF_IN_NETPOLL))
141-
return cpumask_test_cpu(smp_processor_id(), netpoll_block_tx);
137+
return atomic_read(&netpoll_block_tx);
142138
return 0;
143139
}
144140
#else

0 commit comments

Comments
 (0)