diff options
author | Eric Dumazet <edumazet@google.com> | 2023-08-18 17:41:45 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2023-08-20 15:17:47 +0100 |
commit | 0f158b32a9b146c9b86783efccfd9ed02c744623 (patch) | |
tree | 7b0a7ea12da8b4a7bc37f84cb9a9101ec80f60d5 /net/core | |
parent | 412a75dc612a15fc87a755b182bd36f747a70bf6 (diff) | |
download | linux-stable-0f158b32a9b146c9b86783efccfd9ed02c744623.tar.gz linux-stable-0f158b32a9b146c9b86783efccfd9ed02c744623.tar.bz2 linux-stable-0f158b32a9b146c9b86783efccfd9ed02c744623.zip |
net: selectively purge error queue in IP_RECVERR / IPV6_RECVERR
Setting IP_RECVERR and IPV6_RECVERR options to zero currently
purges the socket error queue, which was probably not expected
for zerocopy and tx_timestamp users.
I discovered this issue while preparing commit 6b5f43ea0815
("inet: move inet->recverr to inet->inet_flags"), I presume this
change does not need to be backported to stable kernels.
Add skb_errqueue_purge() helper to purge error messages only.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Willem de Bruijn <willemb@google.com>
Cc: Soheil Hassas Yeganeh <soheil@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/skbuff.c | 21 |
1 files changed, 21 insertions, 0 deletions
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 |