net: skb_queue_purge_reason() optimizations
authorEric Dumazet <edumazet@google.com>
Tue, 3 Oct 2023 18:19:20 +0000 (18:19 +0000)
committerJakub Kicinski <kuba@kernel.org>
Thu, 5 Oct 2023 00:32:24 +0000 (17:32 -0700)
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>
net/core/skbuff.c

index 2198979470ecfaf5667aca7bdecfbf2aa569f852..da3f96bdd6f66cbea2f8e17513bff05a036a48ac 100644 (file)
@@ -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);