diff options
author | David S. Miller <davem@davemloft.net> | 2008-07-17 03:50:32 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-07-17 22:21:26 -0400 |
commit | ead81cc5fc6d996db6afb20f211241612610a07a (patch) | |
tree | 5ffc3c7960f6ba755fe6e44eda0b82cdb8209180 /net | |
parent | 15b458fa65cbba395724a99ab1b7d3785ca76c1c (diff) |
netdevice: Move qdisc_list back into net_device proper.
And give it it's own lock.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/dev.c | 2 | ||||
-rw-r--r-- | net/sched/sch_api.c | 31 | ||||
-rw-r--r-- | net/sched/sch_generic.c | 9 |
3 files changed, 16 insertions, 26 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 0b909b74f698..6741e344ac59 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -3886,6 +3886,8 @@ int register_netdevice(struct net_device *dev) | |||
3886 | net = dev_net(dev); | 3886 | net = dev_net(dev); |
3887 | 3887 | ||
3888 | spin_lock_init(&dev->addr_list_lock); | 3888 | spin_lock_init(&dev->addr_list_lock); |
3889 | spin_lock_init(&dev->qdisc_list_lock); | ||
3890 | INIT_LIST_HEAD(&dev->qdisc_list); | ||
3889 | netdev_init_queue_locks(dev); | 3891 | netdev_init_queue_locks(dev); |
3890 | 3892 | ||
3891 | dev->iflink = -1; | 3893 | dev->iflink = -1; |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 8e8c5becc348..6958fe7c9a77 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -183,30 +183,17 @@ EXPORT_SYMBOL(unregister_qdisc); | |||
183 | (root qdisc, all its children, children of children etc.) | 183 | (root qdisc, all its children, children of children etc.) |
184 | */ | 184 | */ |
185 | 185 | ||
186 | static struct Qdisc *__qdisc_lookup(struct netdev_queue *dev_queue, u32 handle) | 186 | struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) |
187 | { | 187 | { |
188 | struct Qdisc *q; | 188 | struct Qdisc *q; |
189 | 189 | ||
190 | list_for_each_entry(q, &dev_queue->qdisc_list, list) { | 190 | list_for_each_entry(q, &dev->qdisc_list, list) { |
191 | if (q->handle == handle) | 191 | if (q->handle == handle) |
192 | return q; | 192 | return q; |
193 | } | 193 | } |
194 | return NULL; | 194 | return NULL; |
195 | } | 195 | } |
196 | 196 | ||
197 | struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) | ||
198 | { | ||
199 | unsigned int i; | ||
200 | |||
201 | for (i = 0; i < dev->num_tx_queues; i++) { | ||
202 | struct netdev_queue *txq = netdev_get_tx_queue(dev, i); | ||
203 | struct Qdisc *q = __qdisc_lookup(txq, handle); | ||
204 | if (q) | ||
205 | return q; | ||
206 | } | ||
207 | return NULL; | ||
208 | } | ||
209 | |||
210 | static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid) | 197 | static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid) |
211 | { | 198 | { |
212 | unsigned long cl; | 199 | unsigned long cl; |
@@ -645,9 +632,9 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue, | |||
645 | goto err_out3; | 632 | goto err_out3; |
646 | } | 633 | } |
647 | } | 634 | } |
648 | qdisc_lock_tree(dev); | 635 | spin_lock_bh(&dev->qdisc_list_lock); |
649 | list_add_tail(&sch->list, &dev_queue->qdisc_list); | 636 | list_add_tail(&sch->list, &dev->qdisc_list); |
650 | qdisc_unlock_tree(dev); | 637 | spin_unlock_bh(&dev->qdisc_list_lock); |
651 | 638 | ||
652 | return sch; | 639 | return sch; |
653 | } | 640 | } |
@@ -1032,14 +1019,12 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb) | |||
1032 | read_lock(&dev_base_lock); | 1019 | read_lock(&dev_base_lock); |
1033 | idx = 0; | 1020 | idx = 0; |
1034 | for_each_netdev(&init_net, dev) { | 1021 | for_each_netdev(&init_net, dev) { |
1035 | struct netdev_queue *dev_queue; | ||
1036 | if (idx < s_idx) | 1022 | if (idx < s_idx) |
1037 | goto cont; | 1023 | goto cont; |
1038 | if (idx > s_idx) | 1024 | if (idx > s_idx) |
1039 | s_q_idx = 0; | 1025 | s_q_idx = 0; |
1040 | q_idx = 0; | 1026 | q_idx = 0; |
1041 | dev_queue = netdev_get_tx_queue(dev, 0); | 1027 | list_for_each_entry(q, &dev->qdisc_list, list) { |
1042 | list_for_each_entry(q, &dev_queue->qdisc_list, list) { | ||
1043 | if (q_idx < s_q_idx) { | 1028 | if (q_idx < s_q_idx) { |
1044 | q_idx++; | 1029 | q_idx++; |
1045 | continue; | 1030 | continue; |
@@ -1269,7 +1254,6 @@ static int qdisc_class_dump(struct Qdisc *q, unsigned long cl, struct qdisc_walk | |||
1269 | static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) | 1254 | static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) |
1270 | { | 1255 | { |
1271 | struct net *net = sock_net(skb->sk); | 1256 | struct net *net = sock_net(skb->sk); |
1272 | struct netdev_queue *dev_queue; | ||
1273 | int t; | 1257 | int t; |
1274 | int s_t; | 1258 | int s_t; |
1275 | struct net_device *dev; | 1259 | struct net_device *dev; |
@@ -1288,8 +1272,7 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) | |||
1288 | s_t = cb->args[0]; | 1272 | s_t = cb->args[0]; |
1289 | t = 0; | 1273 | t = 0; |
1290 | 1274 | ||
1291 | dev_queue = netdev_get_tx_queue(dev, 0); | 1275 | list_for_each_entry(q, &dev->qdisc_list, list) { |
1292 | list_for_each_entry(q, &dev_queue->qdisc_list, list) { | ||
1293 | if (t < s_t || !q->ops->cl_ops || | 1276 | if (t < s_t || !q->ops->cl_ops || |
1294 | (tcm->tcm_parent && | 1277 | (tcm->tcm_parent && |
1295 | TC_H_MAJ(tcm->tcm_parent) != q->handle)) { | 1278 | TC_H_MAJ(tcm->tcm_parent) != q->handle)) { |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index efa418a1b34e..8cdf0b4a6a5a 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -563,11 +563,15 @@ static void __qdisc_destroy(struct rcu_head *head) | |||
563 | 563 | ||
564 | void qdisc_destroy(struct Qdisc *qdisc) | 564 | void qdisc_destroy(struct Qdisc *qdisc) |
565 | { | 565 | { |
566 | struct net_device *dev = qdisc_dev(qdisc); | ||
567 | |||
566 | if (qdisc->flags & TCQ_F_BUILTIN || | 568 | if (qdisc->flags & TCQ_F_BUILTIN || |
567 | !atomic_dec_and_test(&qdisc->refcnt)) | 569 | !atomic_dec_and_test(&qdisc->refcnt)) |
568 | return; | 570 | return; |
569 | 571 | ||
572 | spin_lock_bh(&dev->qdisc_list_lock); | ||
570 | list_del(&qdisc->list); | 573 | list_del(&qdisc->list); |
574 | spin_unlock_bh(&dev->qdisc_list_lock); | ||
571 | 575 | ||
572 | call_rcu(&qdisc->q_rcu, __qdisc_destroy); | 576 | call_rcu(&qdisc->q_rcu, __qdisc_destroy); |
573 | } | 577 | } |
@@ -599,7 +603,9 @@ static void attach_one_default_qdisc(struct net_device *dev, | |||
599 | printk(KERN_INFO "%s: activation failed\n", dev->name); | 603 | printk(KERN_INFO "%s: activation failed\n", dev->name); |
600 | return; | 604 | return; |
601 | } | 605 | } |
602 | list_add_tail(&qdisc->list, &dev_queue->qdisc_list); | 606 | spin_lock_bh(&dev->qdisc_list_lock); |
607 | list_add_tail(&qdisc->list, &dev->qdisc_list); | ||
608 | spin_unlock_bh(&dev->qdisc_list_lock); | ||
603 | } else { | 609 | } else { |
604 | qdisc = &noqueue_qdisc; | 610 | qdisc = &noqueue_qdisc; |
605 | } | 611 | } |
@@ -738,7 +744,6 @@ static void dev_init_scheduler_queue(struct net_device *dev, | |||
738 | 744 | ||
739 | dev_queue->qdisc = qdisc; | 745 | dev_queue->qdisc = qdisc; |
740 | dev_queue->qdisc_sleeping = qdisc; | 746 | dev_queue->qdisc_sleeping = qdisc; |
741 | INIT_LIST_HEAD(&dev_queue->qdisc_list); | ||
742 | } | 747 | } |
743 | 748 | ||
744 | void dev_init_scheduler(struct net_device *dev) | 749 | void dev_init_scheduler(struct net_device *dev) |