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.c47
1 files changed, 22 insertions, 25 deletions
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index c25465e5607a..ef0efeca6352 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>
@@ -331,7 +332,7 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt)
331 if (!s || tsize != s->tsize || (!tab && tsize > 0)) 332 if (!s || tsize != s->tsize || (!tab && tsize > 0))
332 return ERR_PTR(-EINVAL); 333 return ERR_PTR(-EINVAL);
333 334
334 spin_lock_bh(&qdisc_stab_lock); 335 spin_lock(&qdisc_stab_lock);
335 336
336 list_for_each_entry(stab, &qdisc_stab_list, list) { 337 list_for_each_entry(stab, &qdisc_stab_list, list) {
337 if (memcmp(&stab->szopts, s, sizeof(*s))) 338 if (memcmp(&stab->szopts, s, sizeof(*s)))
@@ -339,11 +340,11 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt)
339 if (tsize > 0 && memcmp(stab->data, tab, tsize * sizeof(u16))) 340 if (tsize > 0 && memcmp(stab->data, tab, tsize * sizeof(u16)))
340 continue; 341 continue;
341 stab->refcnt++; 342 stab->refcnt++;
342 spin_unlock_bh(&qdisc_stab_lock); 343 spin_unlock(&qdisc_stab_lock);
343 return stab; 344 return stab;
344 } 345 }
345 346
346 spin_unlock_bh(&qdisc_stab_lock); 347 spin_unlock(&qdisc_stab_lock);
347 348
348 stab = kmalloc(sizeof(*stab) + tsize * sizeof(u16), GFP_KERNEL); 349 stab = kmalloc(sizeof(*stab) + tsize * sizeof(u16), GFP_KERNEL);
349 if (!stab) 350 if (!stab)
@@ -354,9 +355,9 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt)
354 if (tsize > 0) 355 if (tsize > 0)
355 memcpy(stab->data, tab, tsize * sizeof(u16)); 356 memcpy(stab->data, tab, tsize * sizeof(u16));
356 357
357 spin_lock_bh(&qdisc_stab_lock); 358 spin_lock(&qdisc_stab_lock);
358 list_add_tail(&stab->list, &qdisc_stab_list); 359 list_add_tail(&stab->list, &qdisc_stab_list);
359 spin_unlock_bh(&qdisc_stab_lock); 360 spin_unlock(&qdisc_stab_lock);
360 361
361 return stab; 362 return stab;
362} 363}
@@ -366,14 +367,14 @@ void qdisc_put_stab(struct qdisc_size_table *tab)
366 if (!tab) 367 if (!tab)
367 return; 368 return;
368 369
369 spin_lock_bh(&qdisc_stab_lock); 370 spin_lock(&qdisc_stab_lock);
370 371
371 if (--tab->refcnt == 0) { 372 if (--tab->refcnt == 0) {
372 list_del(&tab->list); 373 list_del(&tab->list);
373 kfree(tab); 374 kfree(tab);
374 } 375 }
375 376
376 spin_unlock_bh(&qdisc_stab_lock); 377 spin_unlock(&qdisc_stab_lock);
377} 378}
378EXPORT_SYMBOL(qdisc_put_stab); 379EXPORT_SYMBOL(qdisc_put_stab);
379 380
@@ -426,7 +427,7 @@ static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer)
426 427
427 wd->qdisc->flags &= ~TCQ_F_THROTTLED; 428 wd->qdisc->flags &= ~TCQ_F_THROTTLED;
428 smp_wmb(); 429 smp_wmb();
429 __netif_schedule(wd->qdisc); 430 __netif_schedule(qdisc_root(wd->qdisc));
430 431
431 return HRTIMER_NORESTART; 432 return HRTIMER_NORESTART;
432} 433}
@@ -637,11 +638,8 @@ static void notify_and_destroy(struct sk_buff *skb, struct nlmsghdr *n, u32 clid
637 if (new || old) 638 if (new || old)
638 qdisc_notify(skb, n, clid, old, new); 639 qdisc_notify(skb, n, clid, old, new);
639 640
640 if (old) { 641 if (old)
641 spin_lock_bh(&old->q.lock);
642 qdisc_destroy(old); 642 qdisc_destroy(old);
643 spin_unlock_bh(&old->q.lock);
644 }
645} 643}
646 644
647/* Graft qdisc "new" to class "classid" of qdisc "parent" or 645/* Graft qdisc "new" to class "classid" of qdisc "parent" or
@@ -707,6 +705,10 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
707 return err; 705 return err;
708} 706}
709 707
708/* lockdep annotation is needed for ingress; egress gets it only for name */
709static struct lock_class_key qdisc_tx_lock;
710static struct lock_class_key qdisc_rx_lock;
711
710/* 712/*
711 Allocate and initialize new qdisc. 713 Allocate and initialize new qdisc.
712 714
@@ -767,6 +769,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
767 if (handle == TC_H_INGRESS) { 769 if (handle == TC_H_INGRESS) {
768 sch->flags |= TCQ_F_INGRESS; 770 sch->flags |= TCQ_F_INGRESS;
769 handle = TC_H_MAKE(TC_H_INGRESS, 0); 771 handle = TC_H_MAKE(TC_H_INGRESS, 0);
772 lockdep_set_class(qdisc_lock(sch), &qdisc_rx_lock);
770 } else { 773 } else {
771 if (handle == 0) { 774 if (handle == 0) {
772 handle = qdisc_alloc_handle(dev); 775 handle = qdisc_alloc_handle(dev);
@@ -774,6 +777,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
774 if (handle == 0) 777 if (handle == 0)
775 goto err_out3; 778 goto err_out3;
776 } 779 }
780 lockdep_set_class(qdisc_lock(sch), &qdisc_tx_lock);
777 } 781 }
778 782
779 sch->handle = handle; 783 sch->handle = handle;
@@ -1084,20 +1088,13 @@ create_n_graft:
1084 } 1088 }
1085 1089
1086graft: 1090graft:
1087 if (1) { 1091 err = qdisc_graft(dev, p, skb, n, clid, q, NULL);
1088 spinlock_t *root_lock; 1092 if (err) {
1089 1093 if (q)
1090 err = qdisc_graft(dev, p, skb, n, clid, q, NULL); 1094 qdisc_destroy(q);
1091 if (err) { 1095 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 } 1096 }
1097
1101 return 0; 1098 return 0;
1102} 1099}
1103 1100