aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--include/linux/skbuff.h1
-rw-r--r--net/core/skbuff.c21
-rw-r--r--net/ipv4/ip_sockglue.c2
-rw-r--r--net/ipv6/ipv6_sockglue.c2
4 files changed, 24 insertions, 2 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 9aec136bc690..4174c4b82d13 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -3180,6 +3180,7 @@ static inline void skb_queue_purge(struct sk_buff_head *list)
}
unsigned int skb_rbtree_purge(struct rb_root *root);
+void skb_errqueue_purge(struct sk_buff_head *list);
void *__netdev_alloc_frag_align(unsigned int fragsz, unsigned int align_mask);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 117d36b1fae3..faa6c86da2a5 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3745,6 +3745,27 @@ unsigned int skb_rbtree_purge(struct rb_root *root)
return sum;
}
+void skb_errqueue_purge(struct sk_buff_head *list)
+{
+ struct sk_buff *skb, *next;
+ struct sk_buff_head kill;
+ unsigned long flags;
+
+ __skb_queue_head_init(&kill);
+
+ spin_lock_irqsave(&list->lock, flags);
+ skb_queue_walk_safe(list, skb, next) {
+ if (SKB_EXT_ERR(skb)->ee.ee_origin == SO_EE_ORIGIN_ZEROCOPY ||
+ SKB_EXT_ERR(skb)->ee.ee_origin == SO_EE_ORIGIN_TIMESTAMPING)
+ continue;
+ __skb_unlink(skb, list);
+ __skb_queue_tail(&kill, skb);
+ }
+ spin_unlock_irqrestore(&list->lock, flags);
+ __skb_queue_purge(&kill);
+}
+EXPORT_SYMBOL(skb_errqueue_purge);
+
/**
* skb_queue_head - queue a buffer at the list head
* @list: list to use
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 61b2e7bc7031..54ad0f0d5c2d 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -976,7 +976,7 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
case IP_RECVERR:
inet_assign_bit(RECVERR, sk, val);
if (!val)
- skb_queue_purge(&sk->sk_error_queue);
+ skb_errqueue_purge(&sk->sk_error_queue);
return 0;
case IP_RECVERR_RFC4884:
if (val < 0 || val > 1)
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index d19577a94bcc..0e2a0847b387 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -923,7 +923,7 @@ done:
goto e_inval;
np->recverr = valbool;
if (!val)
- skb_queue_purge(&sk->sk_error_queue);
+ skb_errqueue_purge(&sk->sk_error_queue);
retv = 0;
break;
case IPV6_FLOWINFO_SEND: