aboutsummaryrefslogtreecommitdiffstats
path: root/include/net/sch_generic.h
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2016-06-06 12:37:15 -0400
committerDavid S. Miller <davem@davemloft.net>2016-06-07 19:37:13 -0400
commitf9eb8aea2a1e12fc2f584d1627deeb957435a801 (patch)
treebc3cf06664da45bc0e6ce9b5165dba534ed11751 /include/net/sch_generic.h
parent64151ae36ed93c45654069c8aff2a7f0125075e8 (diff)
net_sched: transform qdisc running bit into a seqcount
Instead of using a single bit (__QDISC___STATE_RUNNING) in sch->__state, use a seqcount. This adds lockdep support, but more importantly it will allow us to sample qdisc/class statistics without having to grab qdisc root lock. Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Cong Wang <xiyou.wangcong@gmail.com> Cc: Jamal Hadi Salim <jhs@mojatatu.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net/sch_generic.h')
-rw-r--r--include/net/sch_generic.h15
1 files changed, 4 insertions, 11 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index a1fd76c22a59..bff8d895ef8a 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -29,13 +29,6 @@ enum qdisc_state_t {
29 __QDISC_STATE_THROTTLED, 29 __QDISC_STATE_THROTTLED,
30}; 30};
31 31
32/*
33 * following bits are only changed while qdisc lock is held
34 */
35enum qdisc___state_t {
36 __QDISC___STATE_RUNNING = 1,
37};
38
39struct qdisc_size_table { 32struct qdisc_size_table {
40 struct rcu_head rcu; 33 struct rcu_head rcu;
41 struct list_head list; 34 struct list_head list;
@@ -93,7 +86,7 @@ struct Qdisc {
93 unsigned long state; 86 unsigned long state;
94 struct sk_buff_head q; 87 struct sk_buff_head q;
95 struct gnet_stats_basic_packed bstats; 88 struct gnet_stats_basic_packed bstats;
96 unsigned int __state; 89 seqcount_t running;
97 struct gnet_stats_queue qstats; 90 struct gnet_stats_queue qstats;
98 struct rcu_head rcu_head; 91 struct rcu_head rcu_head;
99 int padded; 92 int padded;
@@ -104,20 +97,20 @@ struct Qdisc {
104 97
105static inline bool qdisc_is_running(const struct Qdisc *qdisc) 98static inline bool qdisc_is_running(const struct Qdisc *qdisc)
106{ 99{
107 return (qdisc->__state & __QDISC___STATE_RUNNING) ? true : false; 100 return (raw_read_seqcount(&qdisc->running) & 1) ? true : false;
108} 101}
109 102
110static inline bool qdisc_run_begin(struct Qdisc *qdisc) 103static inline bool qdisc_run_begin(struct Qdisc *qdisc)
111{ 104{
112 if (qdisc_is_running(qdisc)) 105 if (qdisc_is_running(qdisc))
113 return false; 106 return false;
114 qdisc->__state |= __QDISC___STATE_RUNNING; 107 write_seqcount_begin(&qdisc->running);
115 return true; 108 return true;
116} 109}
117 110
118static inline void qdisc_run_end(struct Qdisc *qdisc) 111static inline void qdisc_run_end(struct Qdisc *qdisc)
119{ 112{
120 qdisc->__state &= ~__QDISC___STATE_RUNNING; 113 write_seqcount_end(&qdisc->running);
121} 114}
122 115
123static inline bool qdisc_may_bulk(const struct Qdisc *qdisc) 116static inline bool qdisc_may_bulk(const struct Qdisc *qdisc)