diff options
Diffstat (limited to 'net/sched/sch_prio.c')
| -rw-r--r-- | net/sched/sch_prio.c | 67 |
1 files changed, 24 insertions, 43 deletions
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index f4d443aeae54..8f575899adfa 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c | |||
| @@ -153,8 +153,9 @@ prio_destroy(struct Qdisc *sch) | |||
| 153 | static int prio_tune(struct Qdisc *sch, struct nlattr *opt) | 153 | static int prio_tune(struct Qdisc *sch, struct nlattr *opt) |
| 154 | { | 154 | { |
| 155 | struct prio_sched_data *q = qdisc_priv(sch); | 155 | struct prio_sched_data *q = qdisc_priv(sch); |
| 156 | struct Qdisc *queues[TCQ_PRIO_BANDS]; | ||
| 157 | int oldbands = q->bands, i; | ||
| 156 | struct tc_prio_qopt *qopt; | 158 | struct tc_prio_qopt *qopt; |
| 157 | int i; | ||
| 158 | 159 | ||
| 159 | if (nla_len(opt) < sizeof(*qopt)) | 160 | if (nla_len(opt) < sizeof(*qopt)) |
| 160 | return -EINVAL; | 161 | return -EINVAL; |
| @@ -168,62 +169,42 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt) | |||
| 168 | return -EINVAL; | 169 | return -EINVAL; |
| 169 | } | 170 | } |
| 170 | 171 | ||
| 172 | /* Before commit, make sure we can allocate all new qdiscs */ | ||
| 173 | for (i = oldbands; i < qopt->bands; i++) { | ||
| 174 | queues[i] = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, | ||
| 175 | TC_H_MAKE(sch->handle, i + 1)); | ||
| 176 | if (!queues[i]) { | ||
| 177 | while (i > oldbands) | ||
| 178 | qdisc_destroy(queues[--i]); | ||
| 179 | return -ENOMEM; | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 171 | sch_tree_lock(sch); | 183 | sch_tree_lock(sch); |
| 172 | q->bands = qopt->bands; | 184 | q->bands = qopt->bands; |
| 173 | memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1); | 185 | memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1); |
| 174 | 186 | ||
| 175 | for (i = q->bands; i < TCQ_PRIO_BANDS; i++) { | 187 | for (i = q->bands; i < oldbands; i++) { |
| 176 | struct Qdisc *child = q->queues[i]; | 188 | struct Qdisc *child = q->queues[i]; |
| 177 | q->queues[i] = &noop_qdisc; | ||
| 178 | if (child != &noop_qdisc) { | ||
| 179 | qdisc_tree_reduce_backlog(child, child->q.qlen, child->qstats.backlog); | ||
| 180 | qdisc_destroy(child); | ||
| 181 | } | ||
| 182 | } | ||
| 183 | sch_tree_unlock(sch); | ||
| 184 | 189 | ||
| 185 | for (i = 0; i < q->bands; i++) { | 190 | qdisc_tree_reduce_backlog(child, child->q.qlen, |
| 186 | if (q->queues[i] == &noop_qdisc) { | 191 | child->qstats.backlog); |
| 187 | struct Qdisc *child, *old; | 192 | qdisc_destroy(child); |
| 188 | |||
| 189 | child = qdisc_create_dflt(sch->dev_queue, | ||
| 190 | &pfifo_qdisc_ops, | ||
| 191 | TC_H_MAKE(sch->handle, i + 1)); | ||
| 192 | if (child) { | ||
| 193 | sch_tree_lock(sch); | ||
| 194 | old = q->queues[i]; | ||
| 195 | q->queues[i] = child; | ||
| 196 | |||
| 197 | if (old != &noop_qdisc) { | ||
| 198 | qdisc_tree_reduce_backlog(old, | ||
| 199 | old->q.qlen, | ||
| 200 | old->qstats.backlog); | ||
| 201 | qdisc_destroy(old); | ||
| 202 | } | ||
| 203 | sch_tree_unlock(sch); | ||
| 204 | } | ||
| 205 | } | ||
| 206 | } | 193 | } |
| 194 | |||
| 195 | for (i = oldbands; i < q->bands; i++) | ||
| 196 | q->queues[i] = queues[i]; | ||
| 197 | |||
| 198 | sch_tree_unlock(sch); | ||
| 207 | return 0; | 199 | return 0; |
| 208 | } | 200 | } |
| 209 | 201 | ||
| 210 | static int prio_init(struct Qdisc *sch, struct nlattr *opt) | 202 | static int prio_init(struct Qdisc *sch, struct nlattr *opt) |
| 211 | { | 203 | { |
| 212 | struct prio_sched_data *q = qdisc_priv(sch); | 204 | if (!opt) |
| 213 | int i; | ||
| 214 | |||
| 215 | for (i = 0; i < TCQ_PRIO_BANDS; i++) | ||
| 216 | q->queues[i] = &noop_qdisc; | ||
| 217 | |||
| 218 | if (opt == NULL) { | ||
| 219 | return -EINVAL; | 205 | return -EINVAL; |
| 220 | } else { | ||
| 221 | int err; | ||
| 222 | 206 | ||
| 223 | if ((err = prio_tune(sch, opt)) != 0) | 207 | return prio_tune(sch, opt); |
| 224 | return err; | ||
| 225 | } | ||
| 226 | return 0; | ||
| 227 | } | 208 | } |
| 228 | 209 | ||
| 229 | static int prio_dump(struct Qdisc *sch, struct sk_buff *skb) | 210 | static int prio_dump(struct Qdisc *sch, struct sk_buff *skb) |
