diff options
author | Patrick McHardy <kaber@trash.net> | 2009-09-04 02:41:16 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-09-06 05:07:02 -0400 |
commit | de6d5cdf881353f83006d5f3e28ac4fffd42145e (patch) | |
tree | edc032e4d0a868578780facdd28fb0ee277aadc3 /net | |
parent | 71ebe5e91947392bc276af713827eab12b6db8e4 (diff) |
net_sched: make cls_ops->change and cls_ops->delete optional
Some schedulers don't support creating, changing or deleting classes.
Make the respective callbacks optionally and consistently return
-EOPNOTSUPP for unsupported operations, instead of currently either
-EOPNOTSUPP, -ENOSYS or no error.
In case of sch_prio and sch_multiq, the removed operations additionally
checked for an invalid class. This is not necessary since the class
argument can only orginate from ->get() or in case of ->change is 0
for creation of new classes, in which case ->change() incorrectly
returned -ENOENT.
As a side-effect, this patch fixes a possible (root-only) NULL pointer
function call in sch_ingress, which didn't implement a so far mandatory
->delete() operation.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/sched/sch_api.c | 8 | ||||
-rw-r--r-- | net/sched/sch_ingress.c | 7 | ||||
-rw-r--r-- | net/sched/sch_multiq.c | 22 | ||||
-rw-r--r-- | net/sched/sch_prio.c | 21 | ||||
-rw-r--r-- | net/sched/sch_red.c | 13 | ||||
-rw-r--r-- | net/sched/sch_sfq.c | 7 | ||||
-rw-r--r-- | net/sched/sch_tbf.c | 13 |
7 files changed, 6 insertions, 85 deletions
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index bef2d645a366..166fcca86e7a 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -1417,7 +1417,9 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1417 | goto out; | 1417 | goto out; |
1418 | break; | 1418 | break; |
1419 | case RTM_DELTCLASS: | 1419 | case RTM_DELTCLASS: |
1420 | err = cops->delete(q, cl); | 1420 | err = -EOPNOTSUPP; |
1421 | if (cops->delete) | ||
1422 | err = cops->delete(q, cl); | ||
1421 | if (err == 0) | 1423 | if (err == 0) |
1422 | tclass_notify(skb, n, q, cl, RTM_DELTCLASS); | 1424 | tclass_notify(skb, n, q, cl, RTM_DELTCLASS); |
1423 | goto out; | 1425 | goto out; |
@@ -1431,7 +1433,9 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1431 | } | 1433 | } |
1432 | 1434 | ||
1433 | new_cl = cl; | 1435 | new_cl = cl; |
1434 | err = cops->change(q, clid, pid, tca, &new_cl); | 1436 | err = -EOPNOTSUPP; |
1437 | if (cops->change) | ||
1438 | err = cops->change(q, clid, pid, tca, &new_cl); | ||
1435 | if (err == 0) | 1439 | if (err == 0) |
1436 | tclass_notify(skb, n, q, new_cl, RTM_NEWTCLASS); | 1440 | tclass_notify(skb, n, q, new_cl, RTM_NEWTCLASS); |
1437 | 1441 | ||
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c index ace7902b5097..a9e646bdb605 100644 --- a/net/sched/sch_ingress.c +++ b/net/sched/sch_ingress.c | |||
@@ -42,12 +42,6 @@ static void ingress_put(struct Qdisc *sch, unsigned long cl) | |||
42 | { | 42 | { |
43 | } | 43 | } |
44 | 44 | ||
45 | static int ingress_change(struct Qdisc *sch, u32 classid, u32 parent, | ||
46 | struct nlattr **tca, unsigned long *arg) | ||
47 | { | ||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | static void ingress_walk(struct Qdisc *sch, struct qdisc_walker *walker) | 45 | static void ingress_walk(struct Qdisc *sch, struct qdisc_walker *walker) |
52 | { | 46 | { |
53 | return; | 47 | return; |
@@ -120,7 +114,6 @@ static const struct Qdisc_class_ops ingress_class_ops = { | |||
120 | .leaf = ingress_leaf, | 114 | .leaf = ingress_leaf, |
121 | .get = ingress_get, | 115 | .get = ingress_get, |
122 | .put = ingress_put, | 116 | .put = ingress_put, |
123 | .change = ingress_change, | ||
124 | .walk = ingress_walk, | 117 | .walk = ingress_walk, |
125 | .tcf_chain = ingress_find_tcf, | 118 | .tcf_chain = ingress_find_tcf, |
126 | .bind_tcf = ingress_bind_filter, | 119 | .bind_tcf = ingress_bind_filter, |
diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c index 912731203047..a0ffe7158ff3 100644 --- a/net/sched/sch_multiq.c +++ b/net/sched/sch_multiq.c | |||
@@ -348,26 +348,6 @@ static void multiq_put(struct Qdisc *q, unsigned long cl) | |||
348 | return; | 348 | return; |
349 | } | 349 | } |
350 | 350 | ||
351 | static int multiq_change(struct Qdisc *sch, u32 handle, u32 parent, | ||
352 | struct nlattr **tca, unsigned long *arg) | ||
353 | { | ||
354 | unsigned long cl = *arg; | ||
355 | struct multiq_sched_data *q = qdisc_priv(sch); | ||
356 | |||
357 | if (cl - 1 > q->bands) | ||
358 | return -ENOENT; | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static int multiq_delete(struct Qdisc *sch, unsigned long cl) | ||
363 | { | ||
364 | struct multiq_sched_data *q = qdisc_priv(sch); | ||
365 | if (cl - 1 > q->bands) | ||
366 | return -ENOENT; | ||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | |||
371 | static int multiq_dump_class(struct Qdisc *sch, unsigned long cl, | 351 | static int multiq_dump_class(struct Qdisc *sch, unsigned long cl, |
372 | struct sk_buff *skb, struct tcmsg *tcm) | 352 | struct sk_buff *skb, struct tcmsg *tcm) |
373 | { | 353 | { |
@@ -430,8 +410,6 @@ static const struct Qdisc_class_ops multiq_class_ops = { | |||
430 | .leaf = multiq_leaf, | 410 | .leaf = multiq_leaf, |
431 | .get = multiq_get, | 411 | .get = multiq_get, |
432 | .put = multiq_put, | 412 | .put = multiq_put, |
433 | .change = multiq_change, | ||
434 | .delete = multiq_delete, | ||
435 | .walk = multiq_walk, | 413 | .walk = multiq_walk, |
436 | .tcf_chain = multiq_find_tcf, | 414 | .tcf_chain = multiq_find_tcf, |
437 | .bind_tcf = multiq_bind, | 415 | .bind_tcf = multiq_bind, |
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index 94cecef70145..209a4ca4b98d 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c | |||
@@ -311,25 +311,6 @@ static void prio_put(struct Qdisc *q, unsigned long cl) | |||
311 | return; | 311 | return; |
312 | } | 312 | } |
313 | 313 | ||
314 | static int prio_change(struct Qdisc *sch, u32 handle, u32 parent, struct nlattr **tca, unsigned long *arg) | ||
315 | { | ||
316 | unsigned long cl = *arg; | ||
317 | struct prio_sched_data *q = qdisc_priv(sch); | ||
318 | |||
319 | if (cl - 1 > q->bands) | ||
320 | return -ENOENT; | ||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static int prio_delete(struct Qdisc *sch, unsigned long cl) | ||
325 | { | ||
326 | struct prio_sched_data *q = qdisc_priv(sch); | ||
327 | if (cl - 1 > q->bands) | ||
328 | return -ENOENT; | ||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | |||
333 | static int prio_dump_class(struct Qdisc *sch, unsigned long cl, struct sk_buff *skb, | 314 | static int prio_dump_class(struct Qdisc *sch, unsigned long cl, struct sk_buff *skb, |
334 | struct tcmsg *tcm) | 315 | struct tcmsg *tcm) |
335 | { | 316 | { |
@@ -392,8 +373,6 @@ static const struct Qdisc_class_ops prio_class_ops = { | |||
392 | .leaf = prio_leaf, | 373 | .leaf = prio_leaf, |
393 | .get = prio_get, | 374 | .get = prio_get, |
394 | .put = prio_put, | 375 | .put = prio_put, |
395 | .change = prio_change, | ||
396 | .delete = prio_delete, | ||
397 | .walk = prio_walk, | 376 | .walk = prio_walk, |
398 | .tcf_chain = prio_find_tcf, | 377 | .tcf_chain = prio_find_tcf, |
399 | .bind_tcf = prio_bind, | 378 | .bind_tcf = prio_bind, |
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index c27b8023f079..a2c4d1aa3cb1 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c | |||
@@ -308,17 +308,6 @@ static void red_put(struct Qdisc *sch, unsigned long arg) | |||
308 | return; | 308 | return; |
309 | } | 309 | } |
310 | 310 | ||
311 | static int red_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | ||
312 | struct nlattr **tca, unsigned long *arg) | ||
313 | { | ||
314 | return -ENOSYS; | ||
315 | } | ||
316 | |||
317 | static int red_delete(struct Qdisc *sch, unsigned long cl) | ||
318 | { | ||
319 | return -ENOSYS; | ||
320 | } | ||
321 | |||
322 | static void red_walk(struct Qdisc *sch, struct qdisc_walker *walker) | 311 | static void red_walk(struct Qdisc *sch, struct qdisc_walker *walker) |
323 | { | 312 | { |
324 | if (!walker->stop) { | 313 | if (!walker->stop) { |
@@ -336,8 +325,6 @@ static const struct Qdisc_class_ops red_class_ops = { | |||
336 | .leaf = red_leaf, | 325 | .leaf = red_leaf, |
337 | .get = red_get, | 326 | .get = red_get, |
338 | .put = red_put, | 327 | .put = red_put, |
339 | .change = red_change_class, | ||
340 | .delete = red_delete, | ||
341 | .walk = red_walk, | 328 | .walk = red_walk, |
342 | .dump = red_dump_class, | 329 | .dump = red_dump_class, |
343 | }; | 330 | }; |
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 8706920a6d45..cb21380c0605 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c | |||
@@ -496,12 +496,6 @@ nla_put_failure: | |||
496 | return -1; | 496 | return -1; |
497 | } | 497 | } |
498 | 498 | ||
499 | static int sfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | ||
500 | struct nlattr **tca, unsigned long *arg) | ||
501 | { | ||
502 | return -EOPNOTSUPP; | ||
503 | } | ||
504 | |||
505 | static unsigned long sfq_get(struct Qdisc *sch, u32 classid) | 499 | static unsigned long sfq_get(struct Qdisc *sch, u32 classid) |
506 | { | 500 | { |
507 | return 0; | 501 | return 0; |
@@ -560,7 +554,6 @@ static void sfq_walk(struct Qdisc *sch, struct qdisc_walker *arg) | |||
560 | 554 | ||
561 | static const struct Qdisc_class_ops sfq_class_ops = { | 555 | static const struct Qdisc_class_ops sfq_class_ops = { |
562 | .get = sfq_get, | 556 | .get = sfq_get, |
563 | .change = sfq_change_class, | ||
564 | .tcf_chain = sfq_find_tcf, | 557 | .tcf_chain = sfq_find_tcf, |
565 | .dump = sfq_dump_class, | 558 | .dump = sfq_dump_class, |
566 | .dump_stats = sfq_dump_class_stats, | 559 | .dump_stats = sfq_dump_class_stats, |
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 28909699d24d..d904167e73b3 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c | |||
@@ -410,17 +410,6 @@ static void tbf_put(struct Qdisc *sch, unsigned long arg) | |||
410 | { | 410 | { |
411 | } | 411 | } |
412 | 412 | ||
413 | static int tbf_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | ||
414 | struct nlattr **tca, unsigned long *arg) | ||
415 | { | ||
416 | return -ENOSYS; | ||
417 | } | ||
418 | |||
419 | static int tbf_delete(struct Qdisc *sch, unsigned long arg) | ||
420 | { | ||
421 | return -ENOSYS; | ||
422 | } | ||
423 | |||
424 | static void tbf_walk(struct Qdisc *sch, struct qdisc_walker *walker) | 413 | static void tbf_walk(struct Qdisc *sch, struct qdisc_walker *walker) |
425 | { | 414 | { |
426 | if (!walker->stop) { | 415 | if (!walker->stop) { |
@@ -439,8 +428,6 @@ static const struct Qdisc_class_ops tbf_class_ops = | |||
439 | .leaf = tbf_leaf, | 428 | .leaf = tbf_leaf, |
440 | .get = tbf_get, | 429 | .get = tbf_get, |
441 | .put = tbf_put, | 430 | .put = tbf_put, |
442 | .change = tbf_change_class, | ||
443 | .delete = tbf_delete, | ||
444 | .walk = tbf_walk, | 431 | .walk = tbf_walk, |
445 | .dump = tbf_dump_class, | 432 | .dump = tbf_dump_class, |
446 | }; | 433 | }; |