diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2008-04-06 23:41:50 -0700 |
---|---|---|
committer | Chris Wright <chrisw@sous-sol.org> | 2008-04-18 18:53:25 -0700 |
commit | d55db74d5dbb56eb8f4fc874a97af7294a3b3008 (patch) | |
tree | be62df2bbbbb07e200778f1d1510cab37025c456 | |
parent | 43bee598bd747dc6849d3c4f32a3a912200073c0 (diff) | |
download | kernel-common-d55db74d5dbb56eb8f4fc874a97af7294a3b3008.tar.gz kernel-common-d55db74d5dbb56eb8f4fc874a97af7294a3b3008.tar.bz2 kernel-common-d55db74d5dbb56eb8f4fc874a97af7294a3b3008.zip |
NET: Add preemption point in qdisc_run
Upstream commit: 2ba2506ca7ca62c56edaa334b0fe61eb5eab6ab0
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>
Signed-off-by: Chris Wright <chrisw@sous-sol.org>
-rw-r--r-- | net/sched/sch_generic.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index e595e6570ce0..78889556d123 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -178,10 +178,22 @@ static inline int qdisc_restart(struct net_device *dev) void __qdisc_run(struct net_device *dev) { - do { - if (!qdisc_restart(dev)) + unsigned long start_time = jiffies; + + while (qdisc_restart(dev)) { + if (netif_queue_stopped(dev)) + break; + + /* + * 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; - } while (!netif_queue_stopped(dev)); + } + } clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state); } |