[NET]: Add preemption point in qdisc_run
The qdisc_run loop is currently unbounded and runs entirely in a softirq. This is bad as it may create an unbounded softirq run. This patch fixes this by calling need_resched and breaking out if necessary. It also adds a break out if the jiffies value changes since that would indicate we've been transmitting for too long which starves other softirqs. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
32aced7509
commit
2ba2506ca7
@ -184,10 +184,22 @@ static inline int qdisc_restart(struct net_device *dev)
|
|||||||
|
|
||||||
void __qdisc_run(struct net_device *dev)
|
void __qdisc_run(struct net_device *dev)
|
||||||
{
|
{
|
||||||
do {
|
unsigned long start_time = jiffies;
|
||||||
if (!qdisc_restart(dev))
|
|
||||||
|
while (qdisc_restart(dev)) {
|
||||||
|
if (netif_queue_stopped(dev))
|
||||||
break;
|
break;
|
||||||
} while (!netif_queue_stopped(dev));
|
|
||||||
|
/*
|
||||||
|
* Postpone processing if
|
||||||
|
* 1. another process needs the CPU;
|
||||||
|
* 2. we've been doing it for too long.
|
||||||
|
*/
|
||||||
|
if (need_resched() || jiffies != start_time) {
|
||||||
|
netif_schedule(dev);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state);
|
clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user