From: Herbert Xu Date: Fri, 28 Mar 2008 23:25:26 +0000 (-0700) Subject: [NET]: Add preemption point in qdisc_run X-Git-Tag: v2.6.25-rc9~99^2~24 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2ba2506ca7ca62c56edaa334b0fe61eb5eab6ab0;p=linux-2.6 [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 Signed-off-by: David S. Miller --- diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 10b5c0887f..b741618e4d 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -184,10 +184,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); }