diff options
author | Eric Dumazet <edumazet@google.com> | 2023-10-03 18:19:20 +0000 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2023-10-04 17:32:24 -0700 |
commit | d86e5fbd4c965fdda72f99ccd54a1031ea4df51d (patch) | |
tree | e0ee9a23128b71d61e4836e0ef1a524e0c48f26a | |
parent | 397f70e3be01e2a62d08a12fa135d0f13fea9fb8 (diff) |
net: skb_queue_purge_reason() optimizations
1) Exit early if the list is empty.
2) splice the list into a local list,
so that we block hard irqs only once.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://lore.kernel.org/r/20231003181920.3280453-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r-- | net/core/skbuff.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 2198979470ec..da3f96bdd6f6 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3722,10 +3722,19 @@ EXPORT_SYMBOL(skb_dequeue_tail); void skb_queue_purge_reason(struct sk_buff_head *list, enum skb_drop_reason reason) { - struct sk_buff *skb; + struct sk_buff_head tmp; + unsigned long flags; + + if (skb_queue_empty_lockless(list)) + return; + + __skb_queue_head_init(&tmp); + + spin_lock_irqsave(&list->lock, flags); + skb_queue_splice_init(list, &tmp); + spin_unlock_irqrestore(&list->lock, flags); - while ((skb = skb_dequeue(list)) != NULL) - kfree_skb_reason(skb, reason); + __skb_queue_purge_reason(&tmp, reason); } EXPORT_SYMBOL(skb_queue_purge_reason); |