Message ID | 1300949637.2810.75.camel@edumazet-laptop |
---|---|
State | Accepted, archived |
Delegated to: | David Miller |
Headers | show |
From: Eric Dumazet <eric.dumazet@gmail.com> Date: Thu, 24 Mar 2011 07:53:57 +0100 > [PATCH] net_sched: fix THROTTLED/RUNNING race > > commit fd245a4adb52 (net_sched: move TCQ_F_THROTTLED flag) > added a race. > > qdisc_watchdog() is run from softirq, so special care should be taken or > we can lose one state transition (THROTTLED/RUNNING) > > Prior to fd245a4adb52, we were manipulating q->flags (qdisc->flags &= > ~TCQ_F_THROTTLED;) and this manipulation could only race with > qdisc_warn_nonwc(). > > Since we want to avoid atomic ops in qdisc fast path - it was the > meaning of commit 371121057607e (QDISC_STATE_RUNNING dont need atomic > bit ops) - fix is to move THROTTLE bit into 'state' field, this one > being manipulated with SMP and IRQ safe operations. > > Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Applied, thanks a lot for tracking this down Eric. -- 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
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index a9505b6..b931f02 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -25,6 +25,7 @@ struct qdisc_rate_table { enum qdisc_state_t { __QDISC_STATE_SCHED, __QDISC_STATE_DEACTIVATED, + __QDISC_STATE_THROTTLED, }; /* @@ -32,7 +33,6 @@ enum qdisc_state_t { */ enum qdisc___state_t { __QDISC___STATE_RUNNING = 1, - __QDISC___STATE_THROTTLED = 2, }; struct qdisc_size_table { @@ -106,17 +106,17 @@ static inline void qdisc_run_end(struct Qdisc *qdisc) static inline bool qdisc_is_throttled(const struct Qdisc *qdisc) { - return (qdisc->__state & __QDISC___STATE_THROTTLED) ? true : false; + return test_bit(__QDISC_STATE_THROTTLED, &qdisc->state) ? true : false; } static inline void qdisc_throttled(struct Qdisc *qdisc) { - qdisc->__state |= __QDISC___STATE_THROTTLED; + set_bit(__QDISC_STATE_THROTTLED, &qdisc->state); } static inline void qdisc_unthrottled(struct Qdisc *qdisc) { - qdisc->__state &= ~__QDISC___STATE_THROTTLED; + clear_bit(__QDISC_STATE_THROTTLED, &qdisc->state); } struct Qdisc_class_ops {