aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched')
-rw-r--r--net/sched/cls_api.c2
-rw-r--r--net/sched/sch_api.c47
-rw-r--r--net/sched/sch_cbq.c2
-rw-r--r--net/sched/sch_generic.c68
-rw-r--r--net/sched/sch_htb.c4
-rw-r--r--net/sched/sch_prio.c4
-rw-r--r--net/sched/sch_tbf.c11
7 files changed, 49 insertions, 89 deletions
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index d2b6f54a6261..5cafdd4c8018 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -280,7 +280,7 @@ replay:
280 if (n->nlmsg_type == RTM_DELTFILTER && t->tcm_handle == 0) { 280 if (n->nlmsg_type == RTM_DELTFILTER && t->tcm_handle == 0) {
281 spin_lock_bh(root_lock); 281 spin_lock_bh(root_lock);
282 *back = tp->next; 282 *back = tp->next;
283 spin_lock_bh(root_lock); 283 spin_unlock_bh(root_lock);
284 284
285 tfilter_notify(skb, n, tp, fh, RTM_DELTFILTER); 285 tfilter_notify(skb, n, tp, fh, RTM_DELTFILTER);
286 tcf_destroy(tp); 286 tcf_destroy(tp);
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
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 4e261ce62f48..47ef492c4ff4 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -654,7 +654,7 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer)
654 } 654 }
655 655
656 sch->flags &= ~TCQ_F_THROTTLED; 656 sch->flags &= ~TCQ_F_THROTTLED;
657 __netif_schedule(sch); 657 __netif_schedule(qdisc_root(sch));
658 return HRTIMER_NORESTART; 658 return HRTIMER_NORESTART;
659} 659}
660 660
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 468574682caa..c3ed4d44fc14 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -518,14 +518,17 @@ void qdisc_reset(struct Qdisc *qdisc)
518} 518}
519EXPORT_SYMBOL(qdisc_reset); 519EXPORT_SYMBOL(qdisc_reset);
520 520
521/* this is the rcu callback function to clean up a qdisc when there 521void qdisc_destroy(struct Qdisc *qdisc)
522 * are no further references to it */
523
524static void __qdisc_destroy(struct rcu_head *head)
525{ 522{
526 struct Qdisc *qdisc = container_of(head, struct Qdisc, q_rcu);
527 const struct Qdisc_ops *ops = qdisc->ops; 523 const struct Qdisc_ops *ops = qdisc->ops;
528 524
525 if (qdisc->flags & TCQ_F_BUILTIN ||
526 !atomic_dec_and_test(&qdisc->refcnt))
527 return;
528
529 if (qdisc->parent)
530 list_del(&qdisc->list);
531
529#ifdef CONFIG_NET_SCHED 532#ifdef CONFIG_NET_SCHED
530 qdisc_put_stab(qdisc->stab); 533 qdisc_put_stab(qdisc->stab);
531#endif 534#endif
@@ -542,20 +545,6 @@ static void __qdisc_destroy(struct rcu_head *head)
542 545
543 kfree((char *) qdisc - qdisc->padded); 546 kfree((char *) qdisc - qdisc->padded);
544} 547}
545
546/* Under qdisc_lock(qdisc) and BH! */
547
548void qdisc_destroy(struct Qdisc *qdisc)
549{
550 if (qdisc->flags & TCQ_F_BUILTIN ||
551 !atomic_dec_and_test(&qdisc->refcnt))
552 return;
553
554 if (qdisc->parent)
555 list_del(&qdisc->list);
556
557 call_rcu(&qdisc->q_rcu, __qdisc_destroy);
558}
559EXPORT_SYMBOL(qdisc_destroy); 548EXPORT_SYMBOL(qdisc_destroy);
560 549
561static bool dev_all_qdisc_sleeping_noop(struct net_device *dev) 550static bool dev_all_qdisc_sleeping_noop(struct net_device *dev)
@@ -597,6 +586,9 @@ static void transition_one_qdisc(struct net_device *dev,
597 struct Qdisc *new_qdisc = dev_queue->qdisc_sleeping; 586 struct Qdisc *new_qdisc = dev_queue->qdisc_sleeping;
598 int *need_watchdog_p = _need_watchdog; 587 int *need_watchdog_p = _need_watchdog;
599 588
589 if (!(new_qdisc->flags & TCQ_F_BUILTIN))
590 clear_bit(__QDISC_STATE_DEACTIVATED, &new_qdisc->state);
591
600 rcu_assign_pointer(dev_queue->qdisc, new_qdisc); 592 rcu_assign_pointer(dev_queue->qdisc, new_qdisc);
601 if (need_watchdog_p && new_qdisc != &noqueue_qdisc) 593 if (need_watchdog_p && new_qdisc != &noqueue_qdisc)
602 *need_watchdog_p = 1; 594 *need_watchdog_p = 1;
@@ -640,6 +632,9 @@ static void dev_deactivate_queue(struct net_device *dev,
640 if (qdisc) { 632 if (qdisc) {
641 spin_lock_bh(qdisc_lock(qdisc)); 633 spin_lock_bh(qdisc_lock(qdisc));
642 634
635 if (!(qdisc->flags & TCQ_F_BUILTIN))
636 set_bit(__QDISC_STATE_DEACTIVATED, &qdisc->state);
637
643 dev_queue->qdisc = qdisc_default; 638 dev_queue->qdisc = qdisc_default;
644 qdisc_reset(qdisc); 639 qdisc_reset(qdisc);
645 640
@@ -647,7 +642,7 @@ static void dev_deactivate_queue(struct net_device *dev,
647 } 642 }
648} 643}
649 644
650static bool some_qdisc_is_busy(struct net_device *dev, int lock) 645static bool some_qdisc_is_busy(struct net_device *dev)
651{ 646{
652 unsigned int i; 647 unsigned int i;
653 648
@@ -661,14 +656,12 @@ static bool some_qdisc_is_busy(struct net_device *dev, int lock)
661 q = dev_queue->qdisc_sleeping; 656 q = dev_queue->qdisc_sleeping;
662 root_lock = qdisc_lock(q); 657 root_lock = qdisc_lock(q);
663 658
664 if (lock) 659 spin_lock_bh(root_lock);
665 spin_lock_bh(root_lock);
666 660
667 val = (test_bit(__QDISC_STATE_RUNNING, &q->state) || 661 val = (test_bit(__QDISC_STATE_RUNNING, &q->state) ||
668 test_bit(__QDISC_STATE_SCHED, &q->state)); 662 test_bit(__QDISC_STATE_SCHED, &q->state));
669 663
670 if (lock) 664 spin_unlock_bh(root_lock);
671 spin_unlock_bh(root_lock);
672 665
673 if (val) 666 if (val)
674 return true; 667 return true;
@@ -678,8 +671,6 @@ static bool some_qdisc_is_busy(struct net_device *dev, int lock)
678 671
679void dev_deactivate(struct net_device *dev) 672void dev_deactivate(struct net_device *dev)
680{ 673{
681 bool running;
682
683 netdev_for_each_tx_queue(dev, dev_deactivate_queue, &noop_qdisc); 674 netdev_for_each_tx_queue(dev, dev_deactivate_queue, &noop_qdisc);
684 dev_deactivate_queue(dev, &dev->rx_queue, &noop_qdisc); 675 dev_deactivate_queue(dev, &dev->rx_queue, &noop_qdisc);
685 676
@@ -689,25 +680,8 @@ void dev_deactivate(struct net_device *dev)
689 synchronize_rcu(); 680 synchronize_rcu();
690 681
691 /* Wait for outstanding qdisc_run calls. */ 682 /* Wait for outstanding qdisc_run calls. */
692 do { 683 while (some_qdisc_is_busy(dev))
693 while (some_qdisc_is_busy(dev, 0)) 684 yield();
694 yield();
695
696 /*
697 * Double-check inside queue lock to ensure that all effects
698 * of the queue run are visible when we return.
699 */
700 running = some_qdisc_is_busy(dev, 1);
701
702 /*
703 * The running flag should never be set at this point because
704 * we've already set dev->qdisc to noop_qdisc *inside* the same
705 * pair of spin locks. That is, if any qdisc_run starts after
706 * our initial test it should see the noop_qdisc and then
707 * clear the RUNNING bit before dropping the queue lock. So
708 * if it is set here then we've found a bug.
709 */
710 } while (WARN_ON_ONCE(running));
711} 685}
712 686
713static void dev_init_scheduler_queue(struct net_device *dev, 687static void dev_init_scheduler_queue(struct net_device *dev,
@@ -736,14 +710,10 @@ static void shutdown_scheduler_queue(struct net_device *dev,
736 struct Qdisc *qdisc_default = _qdisc_default; 710 struct Qdisc *qdisc_default = _qdisc_default;
737 711
738 if (qdisc) { 712 if (qdisc) {
739 spinlock_t *root_lock = qdisc_lock(qdisc);
740
741 dev_queue->qdisc = qdisc_default; 713 dev_queue->qdisc = qdisc_default;
742 dev_queue->qdisc_sleeping = qdisc_default; 714 dev_queue->qdisc_sleeping = qdisc_default;
743 715
744 spin_lock_bh(root_lock);
745 qdisc_destroy(qdisc); 716 qdisc_destroy(qdisc);
746 spin_unlock_bh(root_lock);
747 } 717 }
748} 718}
749 719
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 6febd245e62b..0df0df202ed0 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -577,7 +577,7 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
577 sch->qstats.drops++; 577 sch->qstats.drops++;
578 cl->qstats.drops++; 578 cl->qstats.drops++;
579 } 579 }
580 return NET_XMIT_DROP; 580 return ret;
581 } else { 581 } else {
582 cl->bstats.packets += 582 cl->bstats.packets +=
583 skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1; 583 skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1;
@@ -623,7 +623,7 @@ static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch)
623 sch->qstats.drops++; 623 sch->qstats.drops++;
624 cl->qstats.drops++; 624 cl->qstats.drops++;
625 } 625 }
626 return NET_XMIT_DROP; 626 return ret;
627 } else 627 } else
628 htb_activate(q, cl); 628 htb_activate(q, cl);
629 629
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index eac197610edf..a6697c686c7f 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -113,11 +113,11 @@ prio_requeue(struct sk_buff *skb, struct Qdisc* sch)
113 if ((ret = qdisc->ops->requeue(skb, qdisc)) == NET_XMIT_SUCCESS) { 113 if ((ret = qdisc->ops->requeue(skb, qdisc)) == NET_XMIT_SUCCESS) {
114 sch->q.qlen++; 114 sch->q.qlen++;
115 sch->qstats.requeues++; 115 sch->qstats.requeues++;
116 return 0; 116 return NET_XMIT_SUCCESS;
117 } 117 }
118 if (net_xmit_drop_count(ret)) 118 if (net_xmit_drop_count(ret))
119 sch->qstats.drops++; 119 sch->qstats.drops++;
120 return NET_XMIT_DROP; 120 return ret;
121} 121}
122 122
123 123
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index 7d3b7ff3bf07..94c61598b86a 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -123,15 +123,8 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch)
123 struct tbf_sched_data *q = qdisc_priv(sch); 123 struct tbf_sched_data *q = qdisc_priv(sch);
124 int ret; 124 int ret;
125 125
126 if (qdisc_pkt_len(skb) > q->max_size) { 126 if (qdisc_pkt_len(skb) > q->max_size)
127 sch->qstats.drops++; 127 return qdisc_reshape_fail(skb, sch);
128#ifdef CONFIG_NET_CLS_ACT
129 if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch))
130#endif
131 kfree_skb(skb);
132
133 return NET_XMIT_DROP;
134 }
135 128
136 ret = qdisc_enqueue(skb, q->qdisc); 129 ret = qdisc_enqueue(skb, q->qdisc);
137 if (ret != 0) { 130 if (ret != 0) {