aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/sch_api.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-09-14 13:37:28 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-14 13:37:28 -0400
commitd7e9660ad9d5e0845f52848bce31bcf5cdcdea6b (patch)
treec6c67d145771187b194d79d603742b31090a59d6 /net/sched/sch_api.c
parentb8cb48aae1b8c50b37dcb7710363aa69a7a0d9ca (diff)
parent13af7a6ea502fcdd4c0e3d7de6e332b102309491 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1623 commits) netxen: update copyright netxen: fix tx timeout recovery netxen: fix file firmware leak netxen: improve pci memory access netxen: change firmware write size tg3: Fix return ring size breakage netxen: build fix for INET=n cdc-phonet: autoconfigure Phonet address Phonet: back-end for autoconfigured addresses Phonet: fix netlink address dump error handling ipv6: Add IFA_F_DADFAILED flag net: Add DEVTYPE support for Ethernet based devices mv643xx_eth.c: remove unused txq_set_wrr() ucc_geth: Fix hangs after switching from full to half duplex ucc_geth: Rearrange some code to avoid forward declarations phy/marvell: Make non-aneg speed/duplex forcing work for 88E1111 PHYs drivers/net/phy: introduce missing kfree drivers/net/wan: introduce missing kfree net: force bridge module(s) to be GPL Subject: [PATCH] appletalk: Fix skb leak when ipddp interface is not loaded ... Fixed up trivial conflicts: - arch/x86/include/asm/socket.h converted to <asm-generic/socket.h> in the x86 tree. The generic header has the same new #define's, so that works out fine. - drivers/net/tun.c fix conflict between 89f56d1e9 ("tun: reuse struct sock fields") that switched over to using 'tun->socket.sk' instead of the redundantly available (and thus removed) 'tun->sk', and 2b980dbd ("lsm: Add hooks to the TUN driver") which added a new 'tun->sk' use. Noted in 'next' by Stephen Rothwell.
Diffstat (limited to 'net/sched/sch_api.c')
-rw-r--r--net/sched/sch_api.c139
1 files changed, 65 insertions, 74 deletions
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index fdb694e9f759..692d9a41cd23 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -207,7 +207,7 @@ static struct Qdisc *qdisc_match_from_root(struct Qdisc *root, u32 handle)
207static void qdisc_list_add(struct Qdisc *q) 207static void qdisc_list_add(struct Qdisc *q)
208{ 208{
209 if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS)) 209 if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS))
210 list_add_tail(&q->list, &qdisc_root_sleeping(q)->list); 210 list_add_tail(&q->list, &qdisc_dev(q)->qdisc->list);
211} 211}
212 212
213void qdisc_list_del(struct Qdisc *q) 213void qdisc_list_del(struct Qdisc *q)
@@ -219,17 +219,11 @@ EXPORT_SYMBOL(qdisc_list_del);
219 219
220struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) 220struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
221{ 221{
222 unsigned int i;
223 struct Qdisc *q; 222 struct Qdisc *q;
224 223
225 for (i = 0; i < dev->num_tx_queues; i++) { 224 q = qdisc_match_from_root(dev->qdisc, handle);
226 struct netdev_queue *txq = netdev_get_tx_queue(dev, i); 225 if (q)
227 struct Qdisc *txq_root = txq->qdisc_sleeping; 226 goto out;
228
229 q = qdisc_match_from_root(txq_root, handle);
230 if (q)
231 goto out;
232 }
233 227
234 q = qdisc_match_from_root(dev->rx_queue.qdisc_sleeping, handle); 228 q = qdisc_match_from_root(dev->rx_queue.qdisc_sleeping, handle);
235out: 229out:
@@ -616,32 +610,6 @@ static u32 qdisc_alloc_handle(struct net_device *dev)
616 return i>0 ? autohandle : 0; 610 return i>0 ? autohandle : 0;
617} 611}
618 612
619/* Attach toplevel qdisc to device queue. */
620
621static struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue,
622 struct Qdisc *qdisc)
623{
624 struct Qdisc *oqdisc = dev_queue->qdisc_sleeping;
625 spinlock_t *root_lock;
626
627 root_lock = qdisc_lock(oqdisc);
628 spin_lock_bh(root_lock);
629
630 /* Prune old scheduler */
631 if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1)
632 qdisc_reset(oqdisc);
633
634 /* ... and graft new one */
635 if (qdisc == NULL)
636 qdisc = &noop_qdisc;
637 dev_queue->qdisc_sleeping = qdisc;
638 rcu_assign_pointer(dev_queue->qdisc, &noop_qdisc);
639
640 spin_unlock_bh(root_lock);
641
642 return oqdisc;
643}
644
645void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n) 613void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n)
646{ 614{
647 const struct Qdisc_class_ops *cops; 615 const struct Qdisc_class_ops *cops;
@@ -710,6 +678,11 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
710 if (dev->flags & IFF_UP) 678 if (dev->flags & IFF_UP)
711 dev_deactivate(dev); 679 dev_deactivate(dev);
712 680
681 if (new && new->ops->attach) {
682 new->ops->attach(new);
683 num_q = 0;
684 }
685
713 for (i = 0; i < num_q; i++) { 686 for (i = 0; i < num_q; i++) {
714 struct netdev_queue *dev_queue = &dev->rx_queue; 687 struct netdev_queue *dev_queue = &dev->rx_queue;
715 688
@@ -720,22 +693,27 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent,
720 if (new && i > 0) 693 if (new && i > 0)
721 atomic_inc(&new->refcnt); 694 atomic_inc(&new->refcnt);
722 695
723 notify_and_destroy(skb, n, classid, old, new); 696 qdisc_destroy(old);
724 } 697 }
725 698
699 notify_and_destroy(skb, n, classid, dev->qdisc, new);
700 if (new && !new->ops->attach)
701 atomic_inc(&new->refcnt);
702 dev->qdisc = new ? : &noop_qdisc;
703
726 if (dev->flags & IFF_UP) 704 if (dev->flags & IFF_UP)
727 dev_activate(dev); 705 dev_activate(dev);
728 } else { 706 } else {
729 const struct Qdisc_class_ops *cops = parent->ops->cl_ops; 707 const struct Qdisc_class_ops *cops = parent->ops->cl_ops;
730 708
731 err = -EINVAL; 709 err = -EOPNOTSUPP;
732 710 if (cops && cops->graft) {
733 if (cops) {
734 unsigned long cl = cops->get(parent, classid); 711 unsigned long cl = cops->get(parent, classid);
735 if (cl) { 712 if (cl) {
736 err = cops->graft(parent, cl, new, &old); 713 err = cops->graft(parent, cl, new, &old);
737 cops->put(parent, cl); 714 cops->put(parent, cl);
738 } 715 } else
716 err = -ENOENT;
739 } 717 }
740 if (!err) 718 if (!err)
741 notify_and_destroy(skb, n, classid, old, new); 719 notify_and_destroy(skb, n, classid, old, new);
@@ -755,7 +733,8 @@ static struct lock_class_key qdisc_rx_lock;
755 733
756static struct Qdisc * 734static struct Qdisc *
757qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue, 735qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
758 u32 parent, u32 handle, struct nlattr **tca, int *errp) 736 struct Qdisc *p, u32 parent, u32 handle,
737 struct nlattr **tca, int *errp)
759{ 738{
760 int err; 739 int err;
761 struct nlattr *kind = tca[TCA_KIND]; 740 struct nlattr *kind = tca[TCA_KIND];
@@ -832,24 +811,21 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
832 if (tca[TCA_RATE]) { 811 if (tca[TCA_RATE]) {
833 spinlock_t *root_lock; 812 spinlock_t *root_lock;
834 813
814 err = -EOPNOTSUPP;
815 if (sch->flags & TCQ_F_MQROOT)
816 goto err_out4;
817
835 if ((sch->parent != TC_H_ROOT) && 818 if ((sch->parent != TC_H_ROOT) &&
836 !(sch->flags & TCQ_F_INGRESS)) 819 !(sch->flags & TCQ_F_INGRESS) &&
820 (!p || !(p->flags & TCQ_F_MQROOT)))
837 root_lock = qdisc_root_sleeping_lock(sch); 821 root_lock = qdisc_root_sleeping_lock(sch);
838 else 822 else
839 root_lock = qdisc_lock(sch); 823 root_lock = qdisc_lock(sch);
840 824
841 err = gen_new_estimator(&sch->bstats, &sch->rate_est, 825 err = gen_new_estimator(&sch->bstats, &sch->rate_est,
842 root_lock, tca[TCA_RATE]); 826 root_lock, tca[TCA_RATE]);
843 if (err) { 827 if (err)
844 /* 828 goto err_out4;
845 * Any broken qdiscs that would require
846 * a ops->reset() here? The qdisc was never
847 * in action so it shouldn't be necessary.
848 */
849 if (ops->destroy)
850 ops->destroy(sch);
851 goto err_out3;
852 }
853 } 829 }
854 830
855 qdisc_list_add(sch); 831 qdisc_list_add(sch);
@@ -865,6 +841,15 @@ err_out2:
865err_out: 841err_out:
866 *errp = err; 842 *errp = err;
867 return NULL; 843 return NULL;
844
845err_out4:
846 /*
847 * Any broken qdiscs that would require a ops->reset() here?
848 * The qdisc was never in action so it shouldn't be necessary.
849 */
850 if (ops->destroy)
851 ops->destroy(sch);
852 goto err_out3;
868} 853}
869 854
870static int qdisc_change(struct Qdisc *sch, struct nlattr **tca) 855static int qdisc_change(struct Qdisc *sch, struct nlattr **tca)
@@ -889,13 +874,16 @@ static int qdisc_change(struct Qdisc *sch, struct nlattr **tca)
889 qdisc_put_stab(sch->stab); 874 qdisc_put_stab(sch->stab);
890 sch->stab = stab; 875 sch->stab = stab;
891 876
892 if (tca[TCA_RATE]) 877 if (tca[TCA_RATE]) {
893 /* NB: ignores errors from replace_estimator 878 /* NB: ignores errors from replace_estimator
894 because change can't be undone. */ 879 because change can't be undone. */
880 if (sch->flags & TCQ_F_MQROOT)
881 goto out;
895 gen_replace_estimator(&sch->bstats, &sch->rate_est, 882 gen_replace_estimator(&sch->bstats, &sch->rate_est,
896 qdisc_root_sleeping_lock(sch), 883 qdisc_root_sleeping_lock(sch),
897 tca[TCA_RATE]); 884 tca[TCA_RATE]);
898 885 }
886out:
899 return 0; 887 return 0;
900} 888}
901 889
@@ -974,9 +962,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
974 q = dev->rx_queue.qdisc_sleeping; 962 q = dev->rx_queue.qdisc_sleeping;
975 } 963 }
976 } else { 964 } else {
977 struct netdev_queue *dev_queue; 965 q = dev->qdisc;
978 dev_queue = netdev_get_tx_queue(dev, 0);
979 q = dev_queue->qdisc_sleeping;
980 } 966 }
981 if (!q) 967 if (!q)
982 return -ENOENT; 968 return -ENOENT;
@@ -1044,9 +1030,7 @@ replay:
1044 q = dev->rx_queue.qdisc_sleeping; 1030 q = dev->rx_queue.qdisc_sleeping;
1045 } 1031 }
1046 } else { 1032 } else {
1047 struct netdev_queue *dev_queue; 1033 q = dev->qdisc;
1048 dev_queue = netdev_get_tx_queue(dev, 0);
1049 q = dev_queue->qdisc_sleeping;
1050 } 1034 }
1051 1035
1052 /* It may be default qdisc, ignore it */ 1036 /* It may be default qdisc, ignore it */
@@ -1123,13 +1107,19 @@ create_n_graft:
1123 if (!(n->nlmsg_flags&NLM_F_CREATE)) 1107 if (!(n->nlmsg_flags&NLM_F_CREATE))
1124 return -ENOENT; 1108 return -ENOENT;
1125 if (clid == TC_H_INGRESS) 1109 if (clid == TC_H_INGRESS)
1126 q = qdisc_create(dev, &dev->rx_queue, 1110 q = qdisc_create(dev, &dev->rx_queue, p,
1127 tcm->tcm_parent, tcm->tcm_parent, 1111 tcm->tcm_parent, tcm->tcm_parent,
1128 tca, &err); 1112 tca, &err);
1129 else 1113 else {
1130 q = qdisc_create(dev, netdev_get_tx_queue(dev, 0), 1114 unsigned int ntx = 0;
1115
1116 if (p && p->ops->cl_ops && p->ops->cl_ops->select_queue)
1117 ntx = p->ops->cl_ops->select_queue(p, tcm);
1118
1119 q = qdisc_create(dev, netdev_get_tx_queue(dev, ntx), p,
1131 tcm->tcm_parent, tcm->tcm_handle, 1120 tcm->tcm_parent, tcm->tcm_handle,
1132 tca, &err); 1121 tca, &err);
1122 }
1133 if (q == NULL) { 1123 if (q == NULL) {
1134 if (err == -EAGAIN) 1124 if (err == -EAGAIN)
1135 goto replay; 1125 goto replay;
@@ -1291,8 +1281,7 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
1291 s_q_idx = 0; 1281 s_q_idx = 0;
1292 q_idx = 0; 1282 q_idx = 0;
1293 1283
1294 dev_queue = netdev_get_tx_queue(dev, 0); 1284 if (tc_dump_qdisc_root(dev->qdisc, skb, cb, &q_idx, s_q_idx) < 0)
1295 if (tc_dump_qdisc_root(dev_queue->qdisc_sleeping, skb, cb, &q_idx, s_q_idx) < 0)
1296 goto done; 1285 goto done;
1297 1286
1298 dev_queue = &dev->rx_queue; 1287 dev_queue = &dev->rx_queue;
@@ -1323,7 +1312,6 @@ done:
1323static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) 1312static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
1324{ 1313{
1325 struct net *net = sock_net(skb->sk); 1314 struct net *net = sock_net(skb->sk);
1326 struct netdev_queue *dev_queue;
1327 struct tcmsg *tcm = NLMSG_DATA(n); 1315 struct tcmsg *tcm = NLMSG_DATA(n);
1328 struct nlattr *tca[TCA_MAX + 1]; 1316 struct nlattr *tca[TCA_MAX + 1];
1329 struct net_device *dev; 1317 struct net_device *dev;
@@ -1361,7 +1349,6 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
1361 1349
1362 /* Step 1. Determine qdisc handle X:0 */ 1350 /* Step 1. Determine qdisc handle X:0 */
1363 1351
1364 dev_queue = netdev_get_tx_queue(dev, 0);
1365 if (pid != TC_H_ROOT) { 1352 if (pid != TC_H_ROOT) {
1366 u32 qid1 = TC_H_MAJ(pid); 1353 u32 qid1 = TC_H_MAJ(pid);
1367 1354
@@ -1372,7 +1359,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
1372 } else if (qid1) { 1359 } else if (qid1) {
1373 qid = qid1; 1360 qid = qid1;
1374 } else if (qid == 0) 1361 } else if (qid == 0)
1375 qid = dev_queue->qdisc_sleeping->handle; 1362 qid = dev->qdisc->handle;
1376 1363
1377 /* Now qid is genuine qdisc handle consistent 1364 /* Now qid is genuine qdisc handle consistent
1378 both with parent and child. 1365 both with parent and child.
@@ -1383,7 +1370,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
1383 pid = TC_H_MAKE(qid, pid); 1370 pid = TC_H_MAKE(qid, pid);
1384 } else { 1371 } else {
1385 if (qid == 0) 1372 if (qid == 0)
1386 qid = dev_queue->qdisc_sleeping->handle; 1373 qid = dev->qdisc->handle;
1387 } 1374 }
1388 1375
1389 /* OK. Locate qdisc */ 1376 /* OK. Locate qdisc */
@@ -1417,7 +1404,9 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
1417 goto out; 1404 goto out;
1418 break; 1405 break;
1419 case RTM_DELTCLASS: 1406 case RTM_DELTCLASS:
1420 err = cops->delete(q, cl); 1407 err = -EOPNOTSUPP;
1408 if (cops->delete)
1409 err = cops->delete(q, cl);
1421 if (err == 0) 1410 if (err == 0)
1422 tclass_notify(skb, n, q, cl, RTM_DELTCLASS); 1411 tclass_notify(skb, n, q, cl, RTM_DELTCLASS);
1423 goto out; 1412 goto out;
@@ -1431,7 +1420,9 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
1431 } 1420 }
1432 1421
1433 new_cl = cl; 1422 new_cl = cl;
1434 err = cops->change(q, clid, pid, tca, &new_cl); 1423 err = -EOPNOTSUPP;
1424 if (cops->change)
1425 err = cops->change(q, clid, pid, tca, &new_cl);
1435 if (err == 0) 1426 if (err == 0)
1436 tclass_notify(skb, n, q, new_cl, RTM_NEWTCLASS); 1427 tclass_notify(skb, n, q, new_cl, RTM_NEWTCLASS);
1437 1428
@@ -1586,8 +1577,7 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
1586 s_t = cb->args[0]; 1577 s_t = cb->args[0];
1587 t = 0; 1578 t = 0;
1588 1579
1589 dev_queue = netdev_get_tx_queue(dev, 0); 1580 if (tc_dump_tclass_root(dev->qdisc, skb, tcm, cb, &t, s_t) < 0)
1590 if (tc_dump_tclass_root(dev_queue->qdisc_sleeping, skb, tcm, cb, &t, s_t) < 0)
1591 goto done; 1581 goto done;
1592 1582
1593 dev_queue = &dev->rx_queue; 1583 dev_queue = &dev->rx_queue;
@@ -1707,6 +1697,7 @@ static int __init pktsched_init(void)
1707{ 1697{
1708 register_qdisc(&pfifo_qdisc_ops); 1698 register_qdisc(&pfifo_qdisc_ops);
1709 register_qdisc(&bfifo_qdisc_ops); 1699 register_qdisc(&bfifo_qdisc_ops);
1700 register_qdisc(&mq_qdisc_ops);
1710 proc_net_fops_create(&init_net, "psched", 0, &psched_fops); 1701 proc_net_fops_create(&init_net, "psched", 0, &psched_fops);
1711 1702
1712 rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL); 1703 rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL);