aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2004-08-03 23:30:46 -0700
committerDavid S. Miller <davem@nuts.davemloft.net>2004-08-03 23:30:46 -0700
commit251f4c317c0d60922313476cabf37d755c88244d (patch)
tree91cf57d5a8503f0040b7e081765a38e2ccdf55ed /net
parenta7682ad7d0f1d85825e2c0b0e7ccdf26d719e6af (diff)
downloadhistory-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.c27
-rw-r--r--net/sched/sch_generic.c24
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);
}