diff options
-rw-r--r-- | include/net/sch_generic.h | 1 | ||||
-rw-r--r-- | net/sched/sch_api.c | 42 | ||||
-rw-r--r-- | net/sched/sch_mq.c | 1 |
3 files changed, 28 insertions, 16 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 9c69585a1be8..88eb9de095de 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h | |||
@@ -46,6 +46,7 @@ struct Qdisc | |||
46 | #define TCQ_F_THROTTLED 2 | 46 | #define TCQ_F_THROTTLED 2 |
47 | #define TCQ_F_INGRESS 4 | 47 | #define TCQ_F_INGRESS 4 |
48 | #define TCQ_F_CAN_BYPASS 8 | 48 | #define TCQ_F_CAN_BYPASS 8 |
49 | #define TCQ_F_MQROOT 16 | ||
49 | #define TCQ_F_WARN_NONWC (1 << 16) | 50 | #define TCQ_F_WARN_NONWC (1 << 16) |
50 | int padded; | 51 | int padded; |
51 | struct Qdisc_ops *ops; | 52 | struct Qdisc_ops *ops; |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 2a78d5410154..3af106140f35 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -733,7 +733,8 @@ static struct lock_class_key qdisc_rx_lock; | |||
733 | 733 | ||
734 | static struct Qdisc * | 734 | static struct Qdisc * |
735 | qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue, | 735 | qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue, |
736 | u32 parent, u32 handle, struct nlattr **tca, int *errp) | 736 | struct Qdisc *p, u32 parent, u32 handle, |
737 | struct nlattr **tca, int *errp) | ||
737 | { | 738 | { |
738 | int err; | 739 | int err; |
739 | struct nlattr *kind = tca[TCA_KIND]; | 740 | struct nlattr *kind = tca[TCA_KIND]; |
@@ -810,24 +811,21 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue, | |||
810 | if (tca[TCA_RATE]) { | 811 | if (tca[TCA_RATE]) { |
811 | spinlock_t *root_lock; | 812 | spinlock_t *root_lock; |
812 | 813 | ||
814 | err = -EOPNOTSUPP; | ||
815 | if (sch->flags & TCQ_F_MQROOT) | ||
816 | goto err_out4; | ||
817 | |||
813 | if ((sch->parent != TC_H_ROOT) && | 818 | if ((sch->parent != TC_H_ROOT) && |
814 | !(sch->flags & TCQ_F_INGRESS)) | 819 | !(sch->flags & TCQ_F_INGRESS) && |
820 | (!p || !(p->flags & TCQ_F_MQROOT))) | ||
815 | root_lock = qdisc_root_sleeping_lock(sch); | 821 | root_lock = qdisc_root_sleeping_lock(sch); |
816 | else | 822 | else |
817 | root_lock = qdisc_lock(sch); | 823 | root_lock = qdisc_lock(sch); |
818 | 824 | ||
819 | err = gen_new_estimator(&sch->bstats, &sch->rate_est, | 825 | err = gen_new_estimator(&sch->bstats, &sch->rate_est, |
820 | root_lock, tca[TCA_RATE]); | 826 | root_lock, tca[TCA_RATE]); |
821 | if (err) { | 827 | if (err) |
822 | /* | 828 | goto err_out4; |
823 | * Any broken qdiscs that would require | ||
824 | * a ops->reset() here? The qdisc was never | ||
825 | * in action so it shouldn't be necessary. | ||
826 | */ | ||
827 | if (ops->destroy) | ||
828 | ops->destroy(sch); | ||
829 | goto err_out3; | ||
830 | } | ||
831 | } | 829 | } |
832 | 830 | ||
833 | qdisc_list_add(sch); | 831 | qdisc_list_add(sch); |
@@ -843,6 +841,15 @@ err_out2: | |||
843 | err_out: | 841 | err_out: |
844 | *errp = err; | 842 | *errp = err; |
845 | 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; | ||
846 | } | 853 | } |
847 | 854 | ||
848 | static int qdisc_change(struct Qdisc *sch, struct nlattr **tca) | 855 | static int qdisc_change(struct Qdisc *sch, struct nlattr **tca) |
@@ -867,13 +874,16 @@ static int qdisc_change(struct Qdisc *sch, struct nlattr **tca) | |||
867 | qdisc_put_stab(sch->stab); | 874 | qdisc_put_stab(sch->stab); |
868 | sch->stab = stab; | 875 | sch->stab = stab; |
869 | 876 | ||
870 | if (tca[TCA_RATE]) | 877 | if (tca[TCA_RATE]) { |
871 | /* NB: ignores errors from replace_estimator | 878 | /* NB: ignores errors from replace_estimator |
872 | because change can't be undone. */ | 879 | because change can't be undone. */ |
880 | if (sch->flags & TCQ_F_MQROOT) | ||
881 | goto out; | ||
873 | gen_replace_estimator(&sch->bstats, &sch->rate_est, | 882 | gen_replace_estimator(&sch->bstats, &sch->rate_est, |
874 | qdisc_root_sleeping_lock(sch), | 883 | qdisc_root_sleeping_lock(sch), |
875 | tca[TCA_RATE]); | 884 | tca[TCA_RATE]); |
876 | 885 | } | |
886 | out: | ||
877 | return 0; | 887 | return 0; |
878 | } | 888 | } |
879 | 889 | ||
@@ -1097,7 +1107,7 @@ create_n_graft: | |||
1097 | if (!(n->nlmsg_flags&NLM_F_CREATE)) | 1107 | if (!(n->nlmsg_flags&NLM_F_CREATE)) |
1098 | return -ENOENT; | 1108 | return -ENOENT; |
1099 | if (clid == TC_H_INGRESS) | 1109 | if (clid == TC_H_INGRESS) |
1100 | q = qdisc_create(dev, &dev->rx_queue, | 1110 | q = qdisc_create(dev, &dev->rx_queue, p, |
1101 | tcm->tcm_parent, tcm->tcm_parent, | 1111 | tcm->tcm_parent, tcm->tcm_parent, |
1102 | tca, &err); | 1112 | tca, &err); |
1103 | else { | 1113 | else { |
@@ -1106,7 +1116,7 @@ create_n_graft: | |||
1106 | if (p && p->ops->cl_ops && p->ops->cl_ops->select_queue) | 1116 | if (p && p->ops->cl_ops && p->ops->cl_ops->select_queue) |
1107 | ntx = p->ops->cl_ops->select_queue(p, tcm); | 1117 | ntx = p->ops->cl_ops->select_queue(p, tcm); |
1108 | 1118 | ||
1109 | q = qdisc_create(dev, netdev_get_tx_queue(dev, ntx), | 1119 | q = qdisc_create(dev, netdev_get_tx_queue(dev, ntx), p, |
1110 | tcm->tcm_parent, tcm->tcm_handle, | 1120 | tcm->tcm_parent, tcm->tcm_handle, |
1111 | tca, &err); | 1121 | tca, &err); |
1112 | } | 1122 | } |
diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c index c84dec9c8c7d..dd5ee022f1f7 100644 --- a/net/sched/sch_mq.c +++ b/net/sched/sch_mq.c | |||
@@ -64,6 +64,7 @@ static int mq_init(struct Qdisc *sch, struct nlattr *opt) | |||
64 | priv->qdiscs[ntx] = qdisc; | 64 | priv->qdiscs[ntx] = qdisc; |
65 | } | 65 | } |
66 | 66 | ||
67 | sch->flags |= TCQ_F_MQROOT; | ||
67 | return 0; | 68 | return 0; |
68 | 69 | ||
69 | err: | 70 | err: |