diff options
author | John Fastabend <john.fastabend@gmail.com> | 2014-09-12 23:04:52 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-09-13 12:30:25 -0400 |
commit | 46e5da40aec256155cfedee96dd21a75da941f2c (patch) | |
tree | cc3986c52025d252c2a063053692595e60c80e13 /net/sched/sch_teql.c | |
parent | d1015645dd535bbf10e52a3ef6d02ee0c3e0b267 (diff) |
net: qdisc: use rcu prefix and silence sparse warnings
Add __rcu notation to qdisc handling by doing this we can make
smatch output more legible. And anyways some of the cases should
be using rcu_dereference() see qdisc_all_tx_empty(),
qdisc_tx_chainging(), and so on.
Also *wake_queue() API is commonly called from driver timer routines
without rcu lock or rtnl lock. So I added rcu_read_lock() blocks
around netif_wake_subqueue and netif_tx_wake_queue.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/sch_teql.c')
-rw-r--r-- | net/sched/sch_teql.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index aaa8d03ed054..5cd291bd00e4 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c | |||
@@ -96,11 +96,14 @@ teql_dequeue(struct Qdisc *sch) | |||
96 | struct teql_sched_data *dat = qdisc_priv(sch); | 96 | struct teql_sched_data *dat = qdisc_priv(sch); |
97 | struct netdev_queue *dat_queue; | 97 | struct netdev_queue *dat_queue; |
98 | struct sk_buff *skb; | 98 | struct sk_buff *skb; |
99 | struct Qdisc *q; | ||
99 | 100 | ||
100 | skb = __skb_dequeue(&dat->q); | 101 | skb = __skb_dequeue(&dat->q); |
101 | dat_queue = netdev_get_tx_queue(dat->m->dev, 0); | 102 | dat_queue = netdev_get_tx_queue(dat->m->dev, 0); |
103 | q = rcu_dereference_bh(dat_queue->qdisc); | ||
104 | |||
102 | if (skb == NULL) { | 105 | if (skb == NULL) { |
103 | struct net_device *m = qdisc_dev(dat_queue->qdisc); | 106 | struct net_device *m = qdisc_dev(q); |
104 | if (m) { | 107 | if (m) { |
105 | dat->m->slaves = sch; | 108 | dat->m->slaves = sch; |
106 | netif_wake_queue(m); | 109 | netif_wake_queue(m); |
@@ -108,7 +111,7 @@ teql_dequeue(struct Qdisc *sch) | |||
108 | } else { | 111 | } else { |
109 | qdisc_bstats_update(sch, skb); | 112 | qdisc_bstats_update(sch, skb); |
110 | } | 113 | } |
111 | sch->q.qlen = dat->q.qlen + dat_queue->qdisc->q.qlen; | 114 | sch->q.qlen = dat->q.qlen + q->q.qlen; |
112 | return skb; | 115 | return skb; |
113 | } | 116 | } |
114 | 117 | ||
@@ -157,9 +160,9 @@ teql_destroy(struct Qdisc *sch) | |||
157 | txq = netdev_get_tx_queue(master->dev, 0); | 160 | txq = netdev_get_tx_queue(master->dev, 0); |
158 | master->slaves = NULL; | 161 | master->slaves = NULL; |
159 | 162 | ||
160 | root_lock = qdisc_root_sleeping_lock(txq->qdisc); | 163 | root_lock = qdisc_root_sleeping_lock(rtnl_dereference(txq->qdisc)); |
161 | spin_lock_bh(root_lock); | 164 | spin_lock_bh(root_lock); |
162 | qdisc_reset(txq->qdisc); | 165 | qdisc_reset(rtnl_dereference(txq->qdisc)); |
163 | spin_unlock_bh(root_lock); | 166 | spin_unlock_bh(root_lock); |
164 | } | 167 | } |
165 | } | 168 | } |
@@ -266,7 +269,7 @@ static inline int teql_resolve(struct sk_buff *skb, | |||
266 | struct dst_entry *dst = skb_dst(skb); | 269 | struct dst_entry *dst = skb_dst(skb); |
267 | int res; | 270 | int res; |
268 | 271 | ||
269 | if (txq->qdisc == &noop_qdisc) | 272 | if (rcu_access_pointer(txq->qdisc) == &noop_qdisc) |
270 | return -ENODEV; | 273 | return -ENODEV; |
271 | 274 | ||
272 | if (!dev->header_ops || !dst) | 275 | if (!dev->header_ops || !dst) |