diff options
Diffstat (limited to 'net/sched/sch_generic.c')
-rw-r--r-- | net/sched/sch_generic.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 5173c1e1b19c..aeddabfb8e4e 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/rcupdate.h> | 25 | #include <linux/rcupdate.h> |
26 | #include <linux/list.h> | 26 | #include <linux/list.h> |
27 | #include <linux/slab.h> | ||
27 | #include <net/pkt_sched.h> | 28 | #include <net/pkt_sched.h> |
28 | 29 | ||
29 | /* Main transmission queue. */ | 30 | /* Main transmission queue. */ |
@@ -528,7 +529,7 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, | |||
528 | unsigned int size; | 529 | unsigned int size; |
529 | int err = -ENOBUFS; | 530 | int err = -ENOBUFS; |
530 | 531 | ||
531 | /* ensure that the Qdisc and the private data are 32-byte aligned */ | 532 | /* ensure that the Qdisc and the private data are 64-byte aligned */ |
532 | size = QDISC_ALIGN(sizeof(*sch)); | 533 | size = QDISC_ALIGN(sizeof(*sch)); |
533 | size += ops->priv_size + (QDISC_ALIGNTO - 1); | 534 | size += ops->priv_size + (QDISC_ALIGNTO - 1); |
534 | 535 | ||
@@ -590,6 +591,13 @@ void qdisc_reset(struct Qdisc *qdisc) | |||
590 | } | 591 | } |
591 | EXPORT_SYMBOL(qdisc_reset); | 592 | EXPORT_SYMBOL(qdisc_reset); |
592 | 593 | ||
594 | static void qdisc_rcu_free(struct rcu_head *head) | ||
595 | { | ||
596 | struct Qdisc *qdisc = container_of(head, struct Qdisc, rcu_head); | ||
597 | |||
598 | kfree((char *) qdisc - qdisc->padded); | ||
599 | } | ||
600 | |||
593 | void qdisc_destroy(struct Qdisc *qdisc) | 601 | void qdisc_destroy(struct Qdisc *qdisc) |
594 | { | 602 | { |
595 | const struct Qdisc_ops *ops = qdisc->ops; | 603 | const struct Qdisc_ops *ops = qdisc->ops; |
@@ -613,7 +621,11 @@ void qdisc_destroy(struct Qdisc *qdisc) | |||
613 | dev_put(qdisc_dev(qdisc)); | 621 | dev_put(qdisc_dev(qdisc)); |
614 | 622 | ||
615 | kfree_skb(qdisc->gso_skb); | 623 | kfree_skb(qdisc->gso_skb); |
616 | kfree((char *) qdisc - qdisc->padded); | 624 | /* |
625 | * gen_estimator est_timer() might access qdisc->q.lock, | ||
626 | * wait a RCU grace period before freeing qdisc. | ||
627 | */ | ||
628 | call_rcu(&qdisc->rcu_head, qdisc_rcu_free); | ||
617 | } | 629 | } |
618 | EXPORT_SYMBOL(qdisc_destroy); | 630 | EXPORT_SYMBOL(qdisc_destroy); |
619 | 631 | ||