summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2023-10-03 18:19:20 +0000
committerJakub Kicinski <kuba@kernel.org>2023-10-04 17:32:24 -0700
commitd86e5fbd4c965fdda72f99ccd54a1031ea4df51d (patch)
treee0ee9a23128b71d61e4836e0ef1a524e0c48f26a
parent397f70e3be01e2a62d08a12fa135d0f13fea9fb8 (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.c15
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);