The hrtimer callback cbq_undelay() is not serialized against cbq_ovl_delay(). That affects at least q->pmask and q->delay_timer. Lock it proper. Signed-off-by: Thomas Gleixner --- net/sched/sch_cbq.c | 8 ++++++++ 1 file changed, 8 insertions(+) Index: linux-2.6/net/sched/sch_cbq.c =================================================================== --- linux-2.6.orig/net/sched/sch_cbq.c +++ linux-2.6/net/sched/sch_cbq.c @@ -163,6 +163,7 @@ struct cbq_sched_data psched_time_t now_rt; /* Cached real time */ unsigned pmask; + spinlock_t lock; struct hrtimer delay_timer; struct qdisc_watchdog watchdog; /* Watchdog timer, started when CBQ has @@ -503,6 +504,9 @@ static void cbq_ovl_delay(struct cbq_cla cl->undertime = q->now + delay; if (delay > 0) { + unsigned long flags; + + spin_lock_irqsave(&q->lock, flags); sched += delay + cl->penalty; cl->penalized = sched; cl->cpriority = TC_CBQ_MAXPRIO; @@ -518,6 +522,7 @@ static void cbq_ovl_delay(struct cbq_cla hrtimer_restart(&q->delay_timer); cl->delayed = 1; cl->xstats.overactions++; + spin_unlock_irqrestore(&q->lock, flags); return; } delay = 1; @@ -599,6 +604,7 @@ static enum hrtimer_restart cbq_undelay( now = psched_get_time(); + spin_lock(&q->lock); pmask = q->pmask; q->pmask = 0; @@ -623,6 +629,7 @@ static enum hrtimer_restart cbq_undelay( time = ktime_add_ns(time, PSCHED_TICKS2NS(now + delay)); hrtimer_start(&q->delay_timer, time, HRTIMER_MODE_ABS); } + spin_unlock(&q->lock); sch->flags &= ~TCQ_F_THROTTLED; __netif_schedule(qdisc_root(sch)); @@ -1396,6 +1403,7 @@ static int cbq_init(struct Qdisc *sch, s q->link.avpkt = q->link.allot/2; q->link.minidle = -0x7FFFFFFF; + spin_lock_init(&q->lock); qdisc_watchdog_init(&q->watchdog, sch); hrtimer_init(&q->delay_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); q->delay_timer.function = cbq_undelay; -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html