summaryrefslogtreecommitdiff
path: root/net/sched/sch_api.c
diff options
context:
space:
mode:
authorJarek Poplawski <jarkao2@gmail.com>2008-08-21 05:11:14 -0700
committerDavid S. Miller <davem@davemloft.net>2008-08-21 05:11:14 -0700
commit2540e0511ea17e25831be543cdf9381e6209950d (patch)
tree31c505b9957d82125cd7e779d83da0d389f9d336 /net/sched/sch_api.c
parent5e739d1752aca4e8f3e794d431503bfca3162df4 (diff)
pkt_sched: Fix qdisc_watchdog() vs. dev_deactivate() race
dev_deactivate() can skip rescheduling of a qdisc by qdisc_watchdog() or other timer calling netif_schedule() after dev_queue_deactivate(). We prevent this checking aliveness before scheduling the timer. Since during deactivation the root qdisc is available only as qdisc_sleeping additional accessor qdisc_root_sleeping() is created. With feedback from Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Jarek Poplawski <jarkao2@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/sch_api.c')
-rw-r--r--net/sched/sch_api.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index ef0efeca6352..45f442d7de47 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -444,6 +444,10 @@ void qdisc_watchdog_schedule(struct qdisc_watchdog *wd, psched_time_t expires)
{
ktime_t time;
+ if (test_bit(__QDISC_STATE_DEACTIVATED,
+ &qdisc_root_sleeping(wd->qdisc)->state))
+ return;
+
wd->qdisc->flags |= TCQ_F_THROTTLED;
time = ktime_set(0, 0);
time = ktime_add_ns(time, PSCHED_US2NS(expires));