diff options
author | Patrick McHardy <kaber@trash.net> | 2004-08-03 23:30:46 -0700 |
---|---|---|
committer | David S. Miller <davem@nuts.davemloft.net> | 2004-08-03 23:30:46 -0700 |
commit | 251f4c317c0d60922313476cabf37d755c88244d (patch) | |
tree | 91cf57d5a8503f0040b7e081765a38e2ccdf55ed /net | |
parent | a7682ad7d0f1d85825e2c0b0e7ccdf26d719e6af (diff) | |
download | history-251f4c317c0d60922313476cabf37d755c88244d.tar.gz |
[PKT_SCHED]: Use double-linked list for dev->qdisc_list
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@redhat.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/sched/sch_api.c | 27 | ||||
-rw-r--r-- | net/sched/sch_generic.c | 24 |
2 files changed, 21 insertions, 30 deletions
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 80cd0adfbdf92a..a69089d442d43a 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -34,6 +34,7 @@ #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/kmod.h> +#include <linux/list.h> #include <net/sock.h> #include <net/pkt_sched.h> @@ -195,7 +196,7 @@ struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) { struct Qdisc *q; - for (q = dev->qdisc_list; q; q = q->next) { + list_for_each_entry(q, &dev->qdisc_list, list) { if (q->handle == handle) return q; } @@ -421,6 +422,7 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp) memset(sch, 0, size); + INIT_LIST_HEAD(&sch->list); skb_queue_head_init(&sch->q); if (handle == TC_H_INGRESS) @@ -454,8 +456,7 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp) smp_wmb(); if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) { qdisc_lock_tree(dev); - sch->next = dev->qdisc_list; - dev->qdisc_list = sch; + list_add_tail(&sch->list, &dev->qdisc_list); qdisc_unlock_tree(dev); #ifdef CONFIG_NET_ESTIMATOR @@ -814,9 +815,9 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb) if (idx > s_idx) s_q_idx = 0; read_lock_bh(&qdisc_tree_lock); - for (q = dev->qdisc_list, q_idx = 0; q; - q = q->next, q_idx++) { - if (q_idx < s_q_idx) + q_idx = 0; + list_for_each_entry(q, &dev->qdisc_list, list) { + if (q_idx++ < s_q_idx) continue; if (tc_fill_qdisc(skb, q, 0, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) { @@ -831,7 +832,7 @@ done: read_unlock(&dev_base_lock); cb->args[0] = idx; - cb->args[1] = q_idx; + cb->args[1] = q_idx - 1; return skb->len; } @@ -1033,13 +1034,16 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) return 0; s_t = cb->args[0]; + t = 0; read_lock_bh(&qdisc_tree_lock); - for (q=dev->qdisc_list, t=0; q; q = q->next, t++) { - if (t < s_t) continue; - if (!q->ops->cl_ops) continue; - if (tcm->tcm_parent && TC_H_MAJ(tcm->tcm_parent) != q->handle) + list_for_each_entry(q, &dev->qdisc_list, list) { + if (t < s_t || !q->ops->cl_ops || + (tcm->tcm_parent && + TC_H_MAJ(tcm->tcm_parent) != q->handle)) { + t++; continue; + } if (t > s_t) memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0])); arg.w.fn = qdisc_class_dump; @@ -1052,6 +1056,7 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) cb->args[1] = arg.w.count; if (arg.w.stop) break; + t++; } read_unlock_bh(&qdisc_tree_lock); diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index d9e6a0860667bf..addece5b15c63e 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -31,6 +31,7 @@ #include <linux/rtnetlink.h> #include <linux/init.h> #include <linux/rcupdate.h> +#include <linux/list.h> #include <net/sock.h> #include <net/pkt_sched.h> @@ -394,6 +395,7 @@ struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops) return NULL; memset(sch, 0, size); + INIT_LIST_HEAD(&sch->list); skb_queue_head_init(&sch->q); sch->ops = ops; sch->enqueue = ops->enqueue; @@ -450,20 +452,9 @@ static void __qdisc_destroy(struct rcu_head *head) void qdisc_destroy(struct Qdisc *qdisc) { - struct net_device *dev = qdisc->dev; - if (!atomic_dec_and_test(&qdisc->refcnt)) return; - - if (dev) { - struct Qdisc *q, **qp; - for (qp = &qdisc->dev->qdisc_list; (q=*qp) != NULL; qp = &q->next) { - if (q == qdisc) { - *qp = q->next; - break; - } - } - } + list_del(&qdisc->list); call_rcu(&qdisc->q_rcu, __qdisc_destroy); } @@ -483,12 +474,9 @@ void dev_activate(struct net_device *dev) printk(KERN_INFO "%s: activation failed\n", dev->name); return; } - write_lock_bh(&qdisc_tree_lock); - qdisc->next = dev->qdisc_list; - dev->qdisc_list = qdisc; + list_add_tail(&qdisc->list, &dev->qdisc_list); write_unlock_bh(&qdisc_tree_lock); - } else { qdisc = &noqueue_qdisc; } @@ -530,7 +518,7 @@ void dev_init_scheduler(struct net_device *dev) qdisc_lock_tree(dev); dev->qdisc = &noop_qdisc; dev->qdisc_sleeping = &noop_qdisc; - dev->qdisc_list = NULL; + INIT_LIST_HEAD(&dev->qdisc_list); qdisc_unlock_tree(dev); dev_watchdog_init(dev); @@ -551,9 +539,7 @@ void dev_shutdown(struct net_device *dev) qdisc_destroy(qdisc); } #endif - BUG_TRAP(dev->qdisc_list == NULL); BUG_TRAP(!timer_pending(&dev->watchdog_timer)); - dev->qdisc_list = NULL; qdisc_unlock_tree(dev); } |