Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1742905

[PATCH net 3/3] net: skb_queue_purge(): lock/unlock the queue only once

From Michael Witten <mfwitten@gmail.com>
Newsgroups linux.kernel
Subject [PATCH net 3/3] net: skb_queue_purge(): lock/unlock the queue only once
Date 2017-10-02 00:50 +0200
Message-ID <uvVdE-7RC-7@gated-at.bofh.it> (permalink)
References <unkuB-2yh-5@gated-at.bofh.it> <uvV3X-7M7-1@gated-at.bofh.it> <unkEh-2Qx-3@gated-at.bofh.it>
Organization linux.* mail to news gateway

Show all headers | View raw


Date: Sat, 9 Sep 2017 05:50:23 +0000
Hitherto, the queue's lock has been locked/unlocked every time
an item is dequeued; this seems not only inefficient, but also
incorrect, as the whole point of `skb_queue_purge()' is to clear
the queue, presumably without giving any other thread a chance to
manipulate the queue in the interim.

With this commit, the queue's lock is locked/unlocked only once
when `skb_queue_purge()' is called, and in a way that disables
the IRQs for only a minimal amount of time.

This is achieved by atomically re-initializing the queue (thereby
clearing it), and then freeing each of the items as though it were
enqueued in a private queue that doesn't require locking.

Signed-off-by: Michael Witten <mfwitten@gmail.com>
---
 net/core/skbuff.c | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 68065d7d383f..bd26b0bde784 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2825,18 +2825,28 @@ struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list)
 EXPORT_SYMBOL(skb_dequeue_tail);
 
 /**
- *	skb_queue_purge - empty a list
- *	@list: list to empty
+ *	skb_queue_purge - empty a queue
+ *	@q: the queue to empty
  *
- *	Delete all buffers on an &sk_buff list. Each buffer is removed from
- *	the list and one reference dropped. This function takes the list
- *	lock and is atomic with respect to other list locking functions.
+ *	Dequeue and free each socket buffer that is in @q.
+ *
+ *	This function is atomic with respect to other queue-locking functions.
  */
-void skb_queue_purge(struct sk_buff_head *list)
+void skb_queue_purge(struct sk_buff_head *q)
 {
-	struct sk_buff *skb;
-	while ((skb = skb_dequeue(list)) != NULL)
+	unsigned long flags;
+	struct sk_buff *skb, *next, *head = (struct sk_buff *)q;
+
+	spin_lock_irqsave(&q->lock, flags);
+	skb = q->next;
+	__skb_queue_head_init(q);
+	spin_unlock_irqrestore(&q->lock, flags);
+
+	while (skb != head) {
+		next = skb->next;
 		kfree_skb(skb);
+		skb = next;
+	}
 }
 EXPORT_SYMBOL(skb_queue_purge);
 
-- 
2.14.1

Back to linux.kernel | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

[PATCH net 0/3] net: TCP/IP: A few minor cleanups Michael Witten <mfwitten@gmail.com> - 2017-10-02 00:40 +0200
  [PATCH net 2/3] net: inet_recvmsg(): Remove unnecessary bitwise operation Michael Witten <mfwitten@gmail.com> - 2017-10-02 00:50 +0200
  [PATCH net 3/3] net: skb_queue_purge(): lock/unlock the queue only once Michael Witten <mfwitten@gmail.com> - 2017-10-02 00:50 +0200
    Re: [PATCH net 3/3] net: skb_queue_purge(): lock/unlock the queue  only once Stephen Hemminger <stephen@networkplumber.org> - 2017-10-02 03:00 +0200
      Re: [PATCH net 3/3] net: skb_queue_purge(): lock/unlock the queue only once Michael Witten <mfwitten@gmail.com> - 2017-10-02 07:20 +0200
  [PATCH net 1/3] net: __sock_cmsg_send(): Remove unused parameter `msg' Michael Witten <mfwitten@gmail.com> - 2017-10-02 00:50 +0200

csiph-web