aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/sch_htb.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched/sch_htb.c')
-rw-r--r--net/sched/sch_htb.c49
1 files changed, 34 insertions, 15 deletions
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 2f0f0b04d3fb..88cd02626621 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -35,6 +35,7 @@
35#include <linux/list.h> 35#include <linux/list.h>
36#include <linux/compiler.h> 36#include <linux/compiler.h>
37#include <linux/rbtree.h> 37#include <linux/rbtree.h>
38#include <linux/workqueue.h>
38#include <net/netlink.h> 39#include <net/netlink.h>
39#include <net/pkt_sched.h> 40#include <net/pkt_sched.h>
40 41
@@ -114,8 +115,6 @@ struct htb_class {
114 struct tcf_proto *filter_list; 115 struct tcf_proto *filter_list;
115 int filter_cnt; 116 int filter_cnt;
116 117
117 int warned; /* only one warning about non work conserving .. */
118
119 /* token bucket parameters */ 118 /* token bucket parameters */
120 struct qdisc_rate_table *rate; /* rate table of the class itself */ 119 struct qdisc_rate_table *rate; /* rate table of the class itself */
121 struct qdisc_rate_table *ceil; /* ceiling rate (limits borrows too) */ 120 struct qdisc_rate_table *ceil; /* ceiling rate (limits borrows too) */
@@ -155,6 +154,10 @@ struct htb_sched {
155 int direct_qlen; /* max qlen of above */ 154 int direct_qlen; /* max qlen of above */
156 155
157 long direct_pkts; 156 long direct_pkts;
157
158#define HTB_WARN_TOOMANYEVENTS 0x1
159 unsigned int warned; /* only one warning */
160 struct work_struct work;
158}; 161};
159 162
160/* find class in global hash table using given handle */ 163/* find class in global hash table using given handle */
@@ -658,7 +661,7 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,
658 * htb_do_events - make mode changes to classes at the level 661 * htb_do_events - make mode changes to classes at the level
659 * 662 *
660 * Scans event queue for pending events and applies them. Returns time of 663 * Scans event queue for pending events and applies them. Returns time of
661 * next pending event (0 for no event in pq). 664 * next pending event (0 for no event in pq, q->now for too many events).
662 * Note: Applied are events whose have cl->pq_key <= q->now. 665 * Note: Applied are events whose have cl->pq_key <= q->now.
663 */ 666 */
664static psched_time_t htb_do_events(struct htb_sched *q, int level, 667static psched_time_t htb_do_events(struct htb_sched *q, int level,
@@ -686,8 +689,14 @@ static psched_time_t htb_do_events(struct htb_sched *q, int level,
686 if (cl->cmode != HTB_CAN_SEND) 689 if (cl->cmode != HTB_CAN_SEND)
687 htb_add_to_wait_tree(q, cl, diff); 690 htb_add_to_wait_tree(q, cl, diff);
688 } 691 }
689 /* too much load - let's continue on next jiffie (including above) */ 692
690 return q->now + 2 * PSCHED_TICKS_PER_SEC / HZ; 693 /* too much load - let's continue after a break for scheduling */
694 if (!(q->warned & HTB_WARN_TOOMANYEVENTS)) {
695 printk(KERN_WARNING "htb: too many events!\n");
696 q->warned |= HTB_WARN_TOOMANYEVENTS;
697 }
698
699 return q->now;
691} 700}
692 701
693/* Returns class->node+prio from id-tree where classe's id is >= id. NULL 702/* Returns class->node+prio from id-tree where classe's id is >= id. NULL
@@ -809,13 +818,8 @@ next:
809 skb = cl->un.leaf.q->dequeue(cl->un.leaf.q); 818 skb = cl->un.leaf.q->dequeue(cl->un.leaf.q);
810 if (likely(skb != NULL)) 819 if (likely(skb != NULL))
811 break; 820 break;
812 if (!cl->warned) {
813 printk(KERN_WARNING
814 "htb: class %X isn't work conserving ?!\n",
815 cl->common.classid);
816 cl->warned = 1;
817 }
818 821
822 qdisc_warn_nonwc("htb", cl->un.leaf.q);
819 htb_next_rb_node((level ? cl->parent->un.inner.ptr : q-> 823 htb_next_rb_node((level ? cl->parent->un.inner.ptr : q->
820 ptr[0]) + prio); 824 ptr[0]) + prio);
821 cl = htb_lookup_leaf(q->row[level] + prio, prio, 825 cl = htb_lookup_leaf(q->row[level] + prio, prio,
@@ -892,7 +896,10 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch)
892 } 896 }
893 } 897 }
894 sch->qstats.overlimits++; 898 sch->qstats.overlimits++;
895 qdisc_watchdog_schedule(&q->watchdog, next_event); 899 if (likely(next_event > q->now))
900 qdisc_watchdog_schedule(&q->watchdog, next_event);
901 else
902 schedule_work(&q->work);
896fin: 903fin:
897 return skb; 904 return skb;
898} 905}
@@ -962,6 +969,14 @@ static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = {
962 [TCA_HTB_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, 969 [TCA_HTB_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
963}; 970};
964 971
972static void htb_work_func(struct work_struct *work)
973{
974 struct htb_sched *q = container_of(work, struct htb_sched, work);
975 struct Qdisc *sch = q->watchdog.qdisc;
976
977 __netif_schedule(qdisc_root(sch));
978}
979
965static int htb_init(struct Qdisc *sch, struct nlattr *opt) 980static int htb_init(struct Qdisc *sch, struct nlattr *opt)
966{ 981{
967 struct htb_sched *q = qdisc_priv(sch); 982 struct htb_sched *q = qdisc_priv(sch);
@@ -996,6 +1011,7 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt)
996 INIT_LIST_HEAD(q->drops + i); 1011 INIT_LIST_HEAD(q->drops + i);
997 1012
998 qdisc_watchdog_init(&q->watchdog, sch); 1013 qdisc_watchdog_init(&q->watchdog, sch);
1014 INIT_WORK(&q->work, htb_work_func);
999 skb_queue_head_init(&q->direct_queue); 1015 skb_queue_head_init(&q->direct_queue);
1000 1016
1001 q->direct_qlen = qdisc_dev(sch)->tx_queue_len; 1017 q->direct_qlen = qdisc_dev(sch)->tx_queue_len;
@@ -1188,7 +1204,6 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
1188 kfree(cl); 1204 kfree(cl);
1189} 1205}
1190 1206
1191/* always caled under BH & queue lock */
1192static void htb_destroy(struct Qdisc *sch) 1207static void htb_destroy(struct Qdisc *sch)
1193{ 1208{
1194 struct htb_sched *q = qdisc_priv(sch); 1209 struct htb_sched *q = qdisc_priv(sch);
@@ -1196,6 +1211,7 @@ static void htb_destroy(struct Qdisc *sch)
1196 struct htb_class *cl; 1211 struct htb_class *cl;
1197 unsigned int i; 1212 unsigned int i;
1198 1213
1214 cancel_work_sync(&q->work);
1199 qdisc_watchdog_cancel(&q->watchdog); 1215 qdisc_watchdog_cancel(&q->watchdog);
1200 /* This line used to be after htb_destroy_class call below 1216 /* This line used to be after htb_destroy_class call below
1201 and surprisingly it worked in 2.4. But it must precede it 1217 and surprisingly it worked in 2.4. But it must precede it
@@ -1259,8 +1275,11 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
1259 if (last_child) 1275 if (last_child)
1260 htb_parent_to_leaf(q, cl, new_q); 1276 htb_parent_to_leaf(q, cl, new_q);
1261 1277
1262 if (--cl->refcnt == 0) 1278 BUG_ON(--cl->refcnt == 0);
1263 htb_destroy_class(sch, cl); 1279 /*
1280 * This shouldn't happen: we "hold" one cops->get() when called
1281 * from tc_ctl_tclass; the destroy method is done from cops->put().
1282 */
1264 1283
1265 sch_tree_unlock(sch); 1284 sch_tree_unlock(sch);
1266 return 0; 1285 return 0;