diff options
Diffstat (limited to 'include/net')
| -rw-r--r-- | include/net/sch_generic.h | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 5af262ec4bbd..11159a50d6a1 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -1187,12 +1187,22 @@ static inline void tcf_kfree_skb_list(struct sk_buff *skb, struct Qdisc *q, static inline void qdisc_dequeue_drop(struct Qdisc *q, struct sk_buff *skb, enum qdisc_drop_reason reason) { + struct Qdisc *root; + DEBUG_NET_WARN_ON_ONCE(!(q->flags & TCQ_F_DEQUEUE_DROPS)); DEBUG_NET_WARN_ON_ONCE(q->flags & TCQ_F_NOLOCK); - tcf_set_qdisc_drop_reason(skb, reason); - skb->next = q->to_free; - q->to_free = skb; + rcu_read_lock(); + root = qdisc_root_sleeping(q); + + if (root->flags & TCQ_F_DEQUEUE_DROPS) { + tcf_set_qdisc_drop_reason(skb, reason); + skb->next = root->to_free; + root->to_free = skb; + } else { + kfree_skb_reason(skb, (enum skb_drop_reason)reason); + } + rcu_read_unlock(); } /* Instead of calling kfree_skb() while root qdisc lock is held, |
