net_sched: drop packets after root qdisc lock is released
[cascardo/linux.git] / net / sched / sch_dsmark.c
index b9ba5f6..1308bbf 100644 (file)
@@ -191,7 +191,8 @@ static inline struct tcf_proto __rcu **dsmark_find_tcf(struct Qdisc *sch,
 
 /* --------------------------- Qdisc operations ---------------------------- */
 
-static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+                         struct sk_buff **to_free)
 {
        struct dsmark_qdisc_data *p = qdisc_priv(sch);
        int err;
@@ -234,7 +235,7 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 #ifdef CONFIG_NET_CLS_ACT
                case TC_ACT_QUEUED:
                case TC_ACT_STOLEN:
-                       kfree_skb(skb);
+                       __qdisc_drop(skb, to_free);
                        return NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
 
                case TC_ACT_SHOT:
@@ -251,7 +252,7 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                }
        }
 
-       err = qdisc_enqueue(skb, p->q);
+       err = qdisc_enqueue(skb, p->q, to_free);
        if (err != NET_XMIT_SUCCESS) {
                if (net_xmit_drop_count(err))
                        qdisc_qstats_drop(sch);
@@ -264,7 +265,7 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        return NET_XMIT_SUCCESS;
 
 drop:
-       qdisc_drop(skb, sch);
+       qdisc_drop(skb, sch, to_free);
        return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
 }