aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/sch_generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched/sch_generic.c')
-rw-r--r--net/sched/sch_generic.c16
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}
591EXPORT_SYMBOL(qdisc_reset); 592EXPORT_SYMBOL(qdisc_reset);
592 593
594static 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
593void qdisc_destroy(struct Qdisc *qdisc) 601void 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}
618EXPORT_SYMBOL(qdisc_destroy); 630EXPORT_SYMBOL(qdisc_destroy);
619 631