Message ID | 4A5C402A.7090906@trash.net |
---|---|
State | RFC, archived |
Delegated to: | David Miller |
Headers | show |
On Tue, 2009-07-14 at 10:22 +0200, Patrick McHardy wrote: > > That's my understanding what HRTIMER_SOFTIRQ is used for. I think > simply grabbing the root lock in cbq_undelay() should be fine. Its not, and its going away soon (again) :-) The current use of HRTIMER_SOFTIRQ is for when we enqueue a hrtimer with an expiration time in the past. The current implementation tries to run the timer instantly, however we cannot do it from the context calling hrtimer_start(), since that might be holding locks the timer callback also wants to hold, resulting in deadlocks. Instead we queue the timer to the softirq, and kick the softirq. Which leads to another problem in that we cannot always kick the softirq (esp from within the scheduler). We're going to change hrtimer_start() to return -ETIME instead of trying to run the timer in-place, leaving the callers to figure it out. The basic patch is done, but I still need to audit all the hrtimer users in the kernel. -- 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
From: Patrick McHardy <kaber@trash.net> Date: Tue, 14 Jul 2009 10:22:02 +0200 > That's my understanding what HRTIMER_SOFTIRQ is used for. I think > simply grabbing the root lock in cbq_undelay() should be fine. > > Compile-tested only. Unfortunately, as Peter and Thomas explained, this is not the case. -- 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
commit a790fb8873f1cbe8b9cb48cb368851e30d3ec172 Author: Patrick McHardy <kaber@trash.net> Date: Tue Jul 14 10:19:47 2009 +0200 net-sched: sch_cbq: fix locking in cbq_undelay() 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. Based on patch by Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Patrick McHardy <kaber@trash.net> diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 23a1676..7c659c6 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -593,12 +593,16 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer) struct cbq_sched_data *q = container_of(timer, struct cbq_sched_data, delay_timer); struct Qdisc *sch = q->watchdog.qdisc; + spinlock_t *root_lock; psched_time_t now; psched_tdiff_t delay = 0; unsigned pmask; now = psched_get_time(); + root_lock = qdisc_lock(qdisc_root(sch)); + spin_lock(root_lock); + pmask = q->pmask; q->pmask = 0; @@ -615,6 +619,7 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer) delay = tmp; } } + spin_unlock(root_lock); if (delay) { ktime_t time;