net_sched: drop packets after root qdisc lock is released
[deliverable/linux.git] / net / sched / sch_tbf.c
index c12df84d1078c5b1a6bd40bba49446f7cc11ece2..303355c449ab336227d9b115496e0882f2f2a079 100644 (file)
@@ -155,7 +155,8 @@ static unsigned int skb_gso_mac_seglen(const struct sk_buff *skb)
 /* GSO packet is too big, segment it so that tbf can transmit
  * each segment in time
  */
-static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch)
+static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch,
+                      struct sk_buff **to_free)
 {
        struct tbf_sched_data *q = qdisc_priv(sch);
        struct sk_buff *segs, *nskb;
@@ -166,7 +167,7 @@ static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch)
        segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
 
        if (IS_ERR_OR_NULL(segs))
-               return qdisc_drop(skb, sch);
+               return qdisc_drop(skb, sch, to_free);
 
        nb = 0;
        while (segs) {
@@ -174,7 +175,7 @@ static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch)
                segs->next = NULL;
                qdisc_skb_cb(segs)->pkt_len = segs->len;
                len += segs->len;
-               ret = qdisc_enqueue(segs, q->qdisc);
+               ret = qdisc_enqueue(segs, q->qdisc, to_free);
                if (ret != NET_XMIT_SUCCESS) {
                        if (net_xmit_drop_count(ret))
                                qdisc_qstats_drop(sch);
@@ -190,17 +191,18 @@ static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch)
        return nb > 0 ? NET_XMIT_SUCCESS : NET_XMIT_DROP;
 }
 
-static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+                      struct sk_buff **to_free)
 {
        struct tbf_sched_data *q = qdisc_priv(sch);
        int ret;
 
        if (qdisc_pkt_len(skb) > q->max_size) {
                if (skb_is_gso(skb) && skb_gso_mac_seglen(skb) <= q->max_size)
-                       return tbf_segment(skb, sch);
-               return qdisc_drop(skb, sch);
+                       return tbf_segment(skb, sch, to_free);
+               return qdisc_drop(skb, sch, to_free);
        }
-       ret = qdisc_enqueue(skb, q->qdisc);
+       ret = qdisc_enqueue(skb, q->qdisc, to_free);
        if (ret != NET_XMIT_SUCCESS) {
                if (net_xmit_drop_count(ret))
                        qdisc_qstats_drop(sch);
This page took 0.042145 seconds and 5 git commands to generate.