diff options
author | Eric Dumazet <edumazet@google.com> | 2016-06-06 12:37:15 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-06-07 19:37:13 -0400 |
commit | f9eb8aea2a1e12fc2f584d1627deeb957435a801 (patch) | |
tree | bc3cf06664da45bc0e6ce9b5165dba534ed11751 /include/net/sch_generic.h | |
parent | 64151ae36ed93c45654069c8aff2a7f0125075e8 (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.h | 15 |
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 | */ | ||
35 | enum qdisc___state_t { | ||
36 | __QDISC___STATE_RUNNING = 1, | ||
37 | }; | ||
38 | |||
39 | struct qdisc_size_table { | 32 | struct 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 | ||
105 | static inline bool qdisc_is_running(const struct Qdisc *qdisc) | 98 | static 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 | ||
110 | static inline bool qdisc_run_begin(struct Qdisc *qdisc) | 103 | static 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 | ||
118 | static inline void qdisc_run_end(struct Qdisc *qdisc) | 111 | static 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 | ||
123 | static inline bool qdisc_may_bulk(const struct Qdisc *qdisc) | 116 | static inline bool qdisc_may_bulk(const struct Qdisc *qdisc) |