sch_dsmark: fix invalid skb_cow() usage
[pandora-kernel.git] / net / sched / sch_dsmark.c
index 2c79020..fb24bb4 100644 (file)
@@ -202,9 +202,13 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        pr_debug("dsmark_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
 
        if (p->set_tc_index) {
+               int wlen = skb_network_offset(skb);
+
                switch (skb->protocol) {
                case htons(ETH_P_IP):
-                       if (skb_cow_head(skb, sizeof(struct iphdr)))
+                       wlen += sizeof(struct iphdr);
+                       if (!pskb_may_pull(skb, wlen) ||
+                           skb_try_make_writable(skb, wlen))
                                goto drop;
 
                        skb->tc_index = ipv4_get_dsfield(ip_hdr(skb))
@@ -212,7 +216,9 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                        break;
 
                case htons(ETH_P_IPV6):
-                       if (skb_cow_head(skb, sizeof(struct ipv6hdr)))
+                       wlen += sizeof(struct ipv6hdr);
+                       if (!pskb_may_pull(skb, wlen) ||
+                           skb_try_make_writable(skb, wlen))
                                goto drop;
 
                        skb->tc_index = ipv6_get_dsfield(ipv6_hdr(skb))
@@ -260,6 +266,7 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                return err;
        }
 
+       sch->qstats.backlog += qdisc_pkt_len(skb);
        sch->q.qlen++;
 
        return NET_XMIT_SUCCESS;
@@ -283,6 +290,7 @@ static struct sk_buff *dsmark_dequeue(struct Qdisc *sch)
                return NULL;
 
        qdisc_bstats_update(sch, skb);
+       sch->qstats.backlog -= qdisc_pkt_len(skb);
        sch->q.qlen--;
 
        index = skb->tc_index & (p->indices - 1);
@@ -398,6 +406,7 @@ static void dsmark_reset(struct Qdisc *sch)
 
        pr_debug("dsmark_reset(sch %p,[qdisc %p])\n", sch, p);
        qdisc_reset(p->q);
+       sch->qstats.backlog = 0;
        sch->q.qlen = 0;
 }