sctp: validate chunk len before actually using it
[cascardo/linux.git] / net / sched / sch_drr.c
index bf8af2c..8af5c59 100644 (file)
@@ -91,7 +91,8 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
                if (tca[TCA_RATE]) {
                        err = gen_replace_estimator(&cl->bstats, NULL,
                                                    &cl->rate_est,
-                                                   qdisc_root_sleeping_lock(sch),
+                                                   NULL,
+                                                   qdisc_root_sleeping_running(sch),
                                                    tca[TCA_RATE]);
                        if (err)
                                return err;
@@ -119,7 +120,8 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
 
        if (tca[TCA_RATE]) {
                err = gen_replace_estimator(&cl->bstats, NULL, &cl->rate_est,
-                                           qdisc_root_sleeping_lock(sch),
+                                           NULL,
+                                           qdisc_root_sleeping_running(sch),
                                            tca[TCA_RATE]);
                if (err) {
                        qdisc_destroy(cl->qdisc);
@@ -279,7 +281,8 @@ static int drr_dump_class_stats(struct Qdisc *sch, unsigned long arg,
        if (qlen)
                xstats.deficit = cl->deficit;
 
-       if (gnet_stats_copy_basic(d, NULL, &cl->bstats) < 0 ||
+       if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch),
+                                 d, NULL, &cl->bstats) < 0 ||
            gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 ||
            gnet_stats_copy_queue(d, NULL, &cl->qdisc->qstats, qlen) < 0)
                return -1;
@@ -347,7 +350,8 @@ static struct drr_class *drr_classify(struct sk_buff *skb, struct Qdisc *sch,
        return NULL;
 }
 
-static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+                      struct sk_buff **to_free)
 {
        struct drr_sched *q = qdisc_priv(sch);
        struct drr_class *cl;
@@ -357,11 +361,11 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        if (cl == NULL) {
                if (err & __NET_XMIT_BYPASS)
                        qdisc_qstats_drop(sch);
-               kfree_skb(skb);
+               __qdisc_drop(skb, to_free);
                return err;
        }
 
-       err = qdisc_enqueue(skb, cl->qdisc);
+       err = qdisc_enqueue(skb, cl->qdisc, to_free);
        if (unlikely(err != NET_XMIT_SUCCESS)) {
                if (net_xmit_drop_count(err)) {
                        cl->qstats.drops++;
@@ -420,27 +424,6 @@ out:
        return NULL;
 }
 
-static unsigned int drr_drop(struct Qdisc *sch)
-{
-       struct drr_sched *q = qdisc_priv(sch);
-       struct drr_class *cl;
-       unsigned int len;
-
-       list_for_each_entry(cl, &q->active, alist) {
-               if (cl->qdisc->ops->drop) {
-                       len = cl->qdisc->ops->drop(cl->qdisc);
-                       if (len > 0) {
-                               sch->qstats.backlog -= len;
-                               sch->q.qlen--;
-                               if (cl->qdisc->q.qlen == 0)
-                                       list_del(&cl->alist);
-                               return len;
-                       }
-               }
-       }
-       return 0;
-}
-
 static int drr_init_qdisc(struct Qdisc *sch, struct nlattr *opt)
 {
        struct drr_sched *q = qdisc_priv(sch);
@@ -510,7 +493,6 @@ static struct Qdisc_ops drr_qdisc_ops __read_mostly = {
        .enqueue        = drr_enqueue,
        .dequeue        = drr_dequeue,
        .peek           = qdisc_peek_dequeued,
-       .drop           = drr_drop,
        .init           = drr_init_qdisc,
        .reset          = drr_reset_qdisc,
        .destroy        = drr_destroy_qdisc,