ipsec: Fix aborted xfrm policy dump crash
[pandora-kernel.git] / net / sched / sch_netem.c
index eb3b9a8..5856ce5 100644 (file)
@@ -118,8 +118,7 @@ struct netem_skb_cb {
 
 static inline struct netem_skb_cb *netem_skb_cb(struct sk_buff *skb)
 {
-       BUILD_BUG_ON(sizeof(skb->cb) <
-               sizeof(struct qdisc_skb_cb) + sizeof(struct netem_skb_cb));
+       qdisc_cb_private_validate(skb, sizeof(struct netem_skb_cb));
        return (struct netem_skb_cb *)qdisc_skb_cb(skb)->data;
 }
 
@@ -352,10 +351,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        if (q->corrupt && q->corrupt >= get_crandom(&q->corrupt_cor)) {
                if (!(skb = skb_unshare(skb, GFP_ATOMIC)) ||
                    (skb->ip_summed == CHECKSUM_PARTIAL &&
-                    skb_checksum_help(skb))) {
-                       sch->qstats.drops++;
-                       return NET_XMIT_DROP;
-               }
+                    skb_checksum_help(skb)))
+                       return qdisc_drop(skb, sch);
 
                skb->data[net_random() % skb_headlen(skb)] ^= 1<<(net_random() % 8);
        }
@@ -383,8 +380,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                q->counter = 0;
 
                __skb_queue_head(&q->qdisc->q, skb);
-               q->qdisc->qstats.backlog += qdisc_pkt_len(skb);
-               q->qdisc->qstats.requeues++;
+               sch->qstats.backlog += qdisc_pkt_len(skb);
+               sch->qstats.requeues++;
                ret = NET_XMIT_SUCCESS;
        }
 
@@ -488,7 +485,7 @@ static int get_dist_table(struct Qdisc *sch, const struct nlattr *attr)
                return -EINVAL;
 
        s = sizeof(struct disttable) + n * sizeof(s16);
-       d = kmalloc(s, GFP_KERNEL);
+       d = kmalloc(s, GFP_KERNEL | __GFP_NOWARN);
        if (!d)
                d = vmalloc(s);
        if (!d)
@@ -501,9 +498,10 @@ static int get_dist_table(struct Qdisc *sch, const struct nlattr *attr)
        root_lock = qdisc_root_sleeping_lock(sch);
 
        spin_lock_bh(root_lock);
-       dist_free(q->delay_dist);
-       q->delay_dist = d;
+       swap(q->delay_dist, d);
        spin_unlock_bh(root_lock);
+
+       dist_free(d);
        return 0;
 }
 
@@ -760,11 +758,11 @@ static int netem_init(struct Qdisc *sch, struct nlattr *opt)
        struct netem_sched_data *q = qdisc_priv(sch);
        int ret;
 
+       qdisc_watchdog_init(&q->watchdog, sch);
+
        if (!opt)
                return -EINVAL;
 
-       qdisc_watchdog_init(&q->watchdog, sch);
-
        q->loss_model = CLG_RANDOM;
        q->qdisc = qdisc_create_dflt(sch->dev_queue, &tfifo_qdisc_ops,
                                     TC_H_MAKE(sch->handle, 1));