diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-14 13:37:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-14 13:37:28 -0400 |
commit | d7e9660ad9d5e0845f52848bce31bcf5cdcdea6b (patch) | |
tree | c6c67d145771187b194d79d603742b31090a59d6 /net/sched/sch_api.c | |
parent | b8cb48aae1b8c50b37dcb7710363aa69a7a0d9ca (diff) | |
parent | 13af7a6ea502fcdd4c0e3d7de6e332b102309491 (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.c | 139 |
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) | |||
207 | static void qdisc_list_add(struct Qdisc *q) | 207 | static 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 | ||
213 | void qdisc_list_del(struct Qdisc *q) | 213 | void qdisc_list_del(struct Qdisc *q) |
@@ -219,17 +219,11 @@ EXPORT_SYMBOL(qdisc_list_del); | |||
219 | 219 | ||
220 | struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) | 220 | struct 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); |
235 | out: | 229 | out: |
@@ -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 | |||
621 | static 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 | |||
645 | void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n) | 613 | void 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 | ||
756 | static struct Qdisc * | 734 | static struct Qdisc * |
757 | qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue, | 735 | qdisc_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: | |||
865 | err_out: | 841 | err_out: |
866 | *errp = err; | 842 | *errp = err; |
867 | return NULL; | 843 | return NULL; |
844 | |||
845 | err_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 | ||
870 | static int qdisc_change(struct Qdisc *sch, struct nlattr **tca) | 855 | static 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 | } | |
886 | out: | ||
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: | |||
1323 | static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | 1312 | static 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); |