diff options
Diffstat (limited to 'net/sched/sch_api.c')
-rw-r--r-- | net/sched/sch_api.c | 65 |
1 files changed, 28 insertions, 37 deletions
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 97c1c75d5c78..b9a069af4a02 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -399,10 +399,8 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp) | |||
399 | { | 399 | { |
400 | int err; | 400 | int err; |
401 | struct rtattr *kind = tca[TCA_KIND-1]; | 401 | struct rtattr *kind = tca[TCA_KIND-1]; |
402 | void *p = NULL; | ||
403 | struct Qdisc *sch; | 402 | struct Qdisc *sch; |
404 | struct Qdisc_ops *ops; | 403 | struct Qdisc_ops *ops; |
405 | int size; | ||
406 | 404 | ||
407 | ops = qdisc_lookup_ops(kind); | 405 | ops = qdisc_lookup_ops(kind); |
408 | #ifdef CONFIG_KMOD | 406 | #ifdef CONFIG_KMOD |
@@ -437,64 +435,55 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp) | |||
437 | if (ops == NULL) | 435 | if (ops == NULL) |
438 | goto err_out; | 436 | goto err_out; |
439 | 437 | ||
440 | /* ensure that the Qdisc and the private data are 32-byte aligned */ | 438 | sch = qdisc_alloc(dev, ops); |
441 | size = ((sizeof(*sch) + QDISC_ALIGN_CONST) & ~QDISC_ALIGN_CONST); | 439 | if (IS_ERR(sch)) { |
442 | size += ops->priv_size + QDISC_ALIGN_CONST; | 440 | err = PTR_ERR(sch); |
443 | |||
444 | p = kmalloc(size, GFP_KERNEL); | ||
445 | err = -ENOBUFS; | ||
446 | if (!p) | ||
447 | goto err_out2; | 441 | goto err_out2; |
448 | memset(p, 0, size); | 442 | } |
449 | sch = (struct Qdisc *)(((unsigned long)p + QDISC_ALIGN_CONST) | ||
450 | & ~QDISC_ALIGN_CONST); | ||
451 | sch->padded = (char *)sch - (char *)p; | ||
452 | |||
453 | INIT_LIST_HEAD(&sch->list); | ||
454 | skb_queue_head_init(&sch->q); | ||
455 | 443 | ||
456 | if (handle == TC_H_INGRESS) | 444 | if (handle == TC_H_INGRESS) { |
457 | sch->flags |= TCQ_F_INGRESS; | 445 | sch->flags |= TCQ_F_INGRESS; |
458 | 446 | handle = TC_H_MAKE(TC_H_INGRESS, 0); | |
459 | sch->ops = ops; | 447 | } else if (handle == 0) { |
460 | sch->enqueue = ops->enqueue; | ||
461 | sch->dequeue = ops->dequeue; | ||
462 | sch->dev = dev; | ||
463 | dev_hold(dev); | ||
464 | atomic_set(&sch->refcnt, 1); | ||
465 | sch->stats_lock = &dev->queue_lock; | ||
466 | if (handle == 0) { | ||
467 | handle = qdisc_alloc_handle(dev); | 448 | handle = qdisc_alloc_handle(dev); |
468 | err = -ENOMEM; | 449 | err = -ENOMEM; |
469 | if (handle == 0) | 450 | if (handle == 0) |
470 | goto err_out3; | 451 | goto err_out3; |
471 | } | 452 | } |
472 | 453 | ||
473 | if (handle == TC_H_INGRESS) | 454 | sch->handle = handle; |
474 | sch->handle =TC_H_MAKE(TC_H_INGRESS, 0); | ||
475 | else | ||
476 | sch->handle = handle; | ||
477 | 455 | ||
478 | if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) { | 456 | if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) { |
457 | #ifdef CONFIG_NET_ESTIMATOR | ||
458 | if (tca[TCA_RATE-1]) { | ||
459 | err = gen_new_estimator(&sch->bstats, &sch->rate_est, | ||
460 | sch->stats_lock, | ||
461 | tca[TCA_RATE-1]); | ||
462 | if (err) { | ||
463 | /* | ||
464 | * Any broken qdiscs that would require | ||
465 | * a ops->reset() here? The qdisc was never | ||
466 | * in action so it shouldn't be necessary. | ||
467 | */ | ||
468 | if (ops->destroy) | ||
469 | ops->destroy(sch); | ||
470 | goto err_out3; | ||
471 | } | ||
472 | } | ||
473 | #endif | ||
479 | qdisc_lock_tree(dev); | 474 | qdisc_lock_tree(dev); |
480 | list_add_tail(&sch->list, &dev->qdisc_list); | 475 | list_add_tail(&sch->list, &dev->qdisc_list); |
481 | qdisc_unlock_tree(dev); | 476 | qdisc_unlock_tree(dev); |
482 | 477 | ||
483 | #ifdef CONFIG_NET_ESTIMATOR | ||
484 | if (tca[TCA_RATE-1]) | ||
485 | gen_new_estimator(&sch->bstats, &sch->rate_est, | ||
486 | sch->stats_lock, tca[TCA_RATE-1]); | ||
487 | #endif | ||
488 | return sch; | 478 | return sch; |
489 | } | 479 | } |
490 | err_out3: | 480 | err_out3: |
491 | dev_put(dev); | 481 | dev_put(dev); |
482 | kfree((char *) sch - sch->padded); | ||
492 | err_out2: | 483 | err_out2: |
493 | module_put(ops->owner); | 484 | module_put(ops->owner); |
494 | err_out: | 485 | err_out: |
495 | *errp = err; | 486 | *errp = err; |
496 | if (p) | ||
497 | kfree(p); | ||
498 | return NULL; | 487 | return NULL; |
499 | } | 488 | } |
500 | 489 | ||
@@ -770,6 +759,8 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid, | |||
770 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags); | 759 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags); |
771 | tcm = NLMSG_DATA(nlh); | 760 | tcm = NLMSG_DATA(nlh); |
772 | tcm->tcm_family = AF_UNSPEC; | 761 | tcm->tcm_family = AF_UNSPEC; |
762 | tcm->tcm__pad1 = 0; | ||
763 | tcm->tcm__pad2 = 0; | ||
773 | tcm->tcm_ifindex = q->dev->ifindex; | 764 | tcm->tcm_ifindex = q->dev->ifindex; |
774 | tcm->tcm_parent = clid; | 765 | tcm->tcm_parent = clid; |
775 | tcm->tcm_handle = q->handle; | 766 | tcm->tcm_handle = q->handle; |