--- x/net/core/skbuff.c +++ y/net/core/skbuff.c @@ -1099,13 +1099,22 @@ static void skb_free_head(struct sk_buff } } +static DEFINE_SPINLOCK(skb_release_data_lock); static void skb_release_data(struct sk_buff *skb, enum skb_drop_reason reason) { struct skb_shared_info *shinfo = skb_shinfo(skb); int i; + unsigned long flg; if (!skb_data_unref(skb, shinfo)) - goto exit; + return; + spin_lock_irqsave(&skb_release_data_lock, flg); + if ((1 << 6) & shinfo->flags) { + spin_unlock_irqrestore(&skb_release_data_lock, flg); + return; + } + shinfo->flags |= (1 << 6); + spin_unlock_irqrestore(&skb_release_data_lock, flg); if (skb_zcopy(skb)) { bool skip_unref = shinfo->flags & SKBFL_MANAGED_FRAG_REFS;