aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/sch_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched/sch_api.c')
-rw-r--r--net/sched/sch_api.c95
1 files changed, 65 insertions, 30 deletions
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index c25465e5607a..e7fb9e0d21b4 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -27,6 +27,7 @@
27#include <linux/kmod.h> 27#include <linux/kmod.h>
28#include <linux/list.h> 28#include <linux/list.h>
29#include <linux/hrtimer.h> 29#include <linux/hrtimer.h>
30#include <linux/lockdep.h>
30 31
31#include <net/net_namespace.h> 32#include <net/net_namespace.h>
32#include <net/sock.h> 33#include <net/sock.h>
@@ -198,19 +199,53 @@ struct Qdisc *qdisc_match_from_root(struct Qdisc *root, u32 handle)
198 return NULL; 199 return NULL;
199} 200}
200 201
202/*
203 * This lock is needed until some qdiscs stop calling qdisc_tree_decrease_qlen()
204 * without rtnl_lock(); currently hfsc_dequeue(), netem_dequeue(), tbf_dequeue()
205 */
206static DEFINE_SPINLOCK(qdisc_list_lock);
207
208static void qdisc_list_add(struct Qdisc *q)
209{
210 if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS)) {
211 spin_lock_bh(&qdisc_list_lock);
212 list_add_tail(&q->list, &qdisc_root_sleeping(q)->list);
213 spin_unlock_bh(&qdisc_list_lock);
214 }
215}
216
217void qdisc_list_del(struct Qdisc *q)
218{
219 if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS)) {
220 spin_lock_bh(&qdisc_list_lock);
221 list_del(&q->list);
222 spin_unlock_bh(&qdisc_list_lock);
223 }
224}
225EXPORT_SYMBOL(qdisc_list_del);
226
201struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) 227struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
202{ 228{
203 unsigned int i; 229 unsigned int i;
230 struct Qdisc *q;
231
232 spin_lock_bh(&qdisc_list_lock);
204 233
205 for (i = 0; i < dev->num_tx_queues; i++) { 234 for (i = 0; i < dev->num_tx_queues; i++) {
206 struct netdev_queue *txq = netdev_get_tx_queue(dev, i); 235 struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
207 struct Qdisc *q, *txq_root = txq->qdisc_sleeping; 236 struct Qdisc *txq_root = txq->qdisc_sleeping;
208 237
209 q = qdisc_match_from_root(txq_root, handle); 238 q = qdisc_match_from_root(txq_root, handle);
210 if (q) 239 if (q)
211 return q; 240 goto unlock;
212 } 241 }
213 return qdisc_match_from_root(dev->rx_queue.qdisc_sleeping, handle); 242
243 q = qdisc_match_from_root(dev->rx_queue.qdisc_sleeping, handle);
244
245unlock:
246 spin_unlock_bh(&qdisc_list_lock);
247
248 return q;
214} 249}
215 250
216static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid) 251static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid)
@@ -331,7 +366,7 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt)
331 if (!s || tsize != s->tsize || (!tab && tsize > 0)) 366 if (!s || tsize != s->tsize || (!tab && tsize > 0))
332 return ERR_PTR(-EINVAL); 367 return ERR_PTR(-EINVAL);
333 368
334 spin_lock_bh(&qdisc_stab_lock); 369 spin_lock(&qdisc_stab_lock);
335 370
336 list_for_each_entry(stab, &qdisc_stab_list, list) { 371 list_for_each_entry(stab, &qdisc_stab_list, list) {
337 if (memcmp(&stab->szopts, s, sizeof(*s))) 372 if (memcmp(&stab->szopts, s, sizeof(*s)))
@@ -339,11 +374,11 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt)
339 if (tsize > 0 && memcmp(stab->data, tab, tsize * sizeof(u16))) 374 if (tsize > 0 && memcmp(stab->data, tab, tsize * sizeof(u16)))
340 continue; 375 continue;
341 stab->refcnt++; 376 stab->refcnt++;
342 spin_unlock_bh(&qdisc_stab_lock); 377 spin_unlock(&qdisc_stab_lock);
343 return stab; 378 return stab;
344 } 379 }
345 380
346 spin_unlock_bh(&qdisc_stab_lock); 381 spin_unlock(&qdisc_stab_lock);
347 382
348 stab = kmalloc(sizeof(*stab) + tsize * sizeof(u16), GFP_KERNEL); 383 stab = kmalloc(sizeof(*stab) + tsize * sizeof(u16), GFP_KERNEL);
349 if (!stab) 384 if (!stab)
@@ -354,9 +389,9 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt)
354 if (tsize > 0) 389 if (tsize > 0)
355 memcpy(stab->data, tab, tsize * sizeof(u16)); 390 memcpy(stab->data, tab, tsize * sizeof(u16));
356 391
357 spin_lock_bh(&qdisc_stab_lock); 392 spin_lock(&qdisc_stab_lock);
358 list_add_tail(&stab->list, &qdisc_stab_list); 393 list_add_tail(&stab->list, &qdisc_stab_list);
359 spin_unlock_bh(&qdisc_stab_lock); 394 spin_unlock(&qdisc_stab_lock);
360 395
361 return stab; 396 return stab;
362} 397}
@@ -366,14 +401,14 @@ void qdisc_put_stab(struct qdisc_size_table *tab)
366 if (!tab) 401 if (!tab)
367 return; 402 return;
368 403
369 spin_lock_bh(&qdisc_stab_lock); 404 spin_lock(&qdisc_stab_lock);
370 405
371 if (--tab->refcnt == 0) { 406 if (--tab->refcnt == 0) {
372 list_del(&tab->list); 407 list_del(&tab->list);
373 kfree(tab); 408 kfree(tab);
374 } 409 }
375 410
376 spin_unlock_bh(&qdisc_stab_lock); 411 spin_unlock(&qdisc_stab_lock);
377} 412}
378EXPORT_SYMBOL(qdisc_put_stab); 413EXPORT_SYMBOL(qdisc_put_stab);
379 414
@@ -426,7 +461,7 @@ static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer)
426 461
427 wd->qdisc->flags &= ~TCQ_F_THROTTLED; 462 wd->qdisc->flags &= ~TCQ_F_THROTTLED;
428 smp_wmb(); 463 smp_wmb();
429 __netif_schedule(wd->qdisc); 464 __netif_schedule(qdisc_root(wd->qdisc));
430 465
431 return HRTIMER_NORESTART; 466 return HRTIMER_NORESTART;
432} 467}
@@ -443,6 +478,10 @@ void qdisc_watchdog_schedule(struct qdisc_watchdog *wd, psched_time_t expires)
443{ 478{
444 ktime_t time; 479 ktime_t time;
445 480
481 if (test_bit(__QDISC_STATE_DEACTIVATED,
482 &qdisc_root_sleeping(wd->qdisc)->state))
483 return;
484
446 wd->qdisc->flags |= TCQ_F_THROTTLED; 485 wd->qdisc->flags |= TCQ_F_THROTTLED;
447 time = ktime_set(0, 0); 486 time = ktime_set(0, 0);
448 time = ktime_add_ns(time, PSCHED_US2NS(expires)); 487 time = ktime_add_ns(time, PSCHED_US2NS(expires));
@@ -637,11 +676,8 @@ static void notify_and_destroy(struct sk_buff *skb, struct nlmsghdr *n, u32 clid
637 if (new || old) 676 if (new || old)
638 qdisc_notify(skb, n, clid, old, new); 677 qdisc_notify(skb, n, clid, old, new);
639 678
640 if (old) { 679 if (old)
641 spin_lock_bh(&old->q.lock);
642 qdisc_destroy(old); 680 qdisc_destroy(old);
643 spin_unlock_bh(&old->q.lock);
644 }
645} 681}
646 682
647/* Graft qdisc "new" to class "classid" of qdisc "parent" or 683/* Graft qdisc "new" to class "classid" of qdisc "parent" or
@@ -707,6 +743,10 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
707 return err; 743 return err;
708} 744}
709 745
746/* lockdep annotation is needed for ingress; egress gets it only for name */
747static struct lock_class_key qdisc_tx_lock;
748static struct lock_class_key qdisc_rx_lock;
749
710/* 750/*
711 Allocate and initialize new qdisc. 751 Allocate and initialize new qdisc.
712 752
@@ -767,6 +807,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
767 if (handle == TC_H_INGRESS) { 807 if (handle == TC_H_INGRESS) {
768 sch->flags |= TCQ_F_INGRESS; 808 sch->flags |= TCQ_F_INGRESS;
769 handle = TC_H_MAKE(TC_H_INGRESS, 0); 809 handle = TC_H_MAKE(TC_H_INGRESS, 0);
810 lockdep_set_class(qdisc_lock(sch), &qdisc_rx_lock);
770 } else { 811 } else {
771 if (handle == 0) { 812 if (handle == 0) {
772 handle = qdisc_alloc_handle(dev); 813 handle = qdisc_alloc_handle(dev);
@@ -774,6 +815,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
774 if (handle == 0) 815 if (handle == 0)
775 goto err_out3; 816 goto err_out3;
776 } 817 }
818 lockdep_set_class(qdisc_lock(sch), &qdisc_tx_lock);
777 } 819 }
778 820
779 sch->handle = handle; 821 sch->handle = handle;
@@ -802,8 +844,8 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
802 goto err_out3; 844 goto err_out3;
803 } 845 }
804 } 846 }
805 if ((parent != TC_H_ROOT) && !(sch->flags & TCQ_F_INGRESS)) 847
806 list_add_tail(&sch->list, &dev_queue->qdisc_sleeping->list); 848 qdisc_list_add(sch);
807 849
808 return sch; 850 return sch;
809 } 851 }
@@ -1084,20 +1126,13 @@ create_n_graft:
1084 } 1126 }
1085 1127
1086graft: 1128graft:
1087 if (1) { 1129 err = qdisc_graft(dev, p, skb, n, clid, q, NULL);
1088 spinlock_t *root_lock; 1130 if (err) {
1089 1131 if (q)
1090 err = qdisc_graft(dev, p, skb, n, clid, q, NULL); 1132 qdisc_destroy(q);
1091 if (err) { 1133 return err;
1092 if (q) {
1093 root_lock = qdisc_root_lock(q);
1094 spin_lock_bh(root_lock);
1095 qdisc_destroy(q);
1096 spin_unlock_bh(root_lock);
1097 }
1098 return err;
1099 }
1100 } 1134 }
1135
1101 return 0; 1136 return 0;
1102} 1137}
1103 1138