Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1742901 > unrolled thread
| Started by | Michael Witten <mfwitten@gmail.com> |
|---|---|
| First post | 2017-10-02 00:40 +0200 |
| Last post | 2017-10-02 00:50 +0200 |
| Articles | 6 — 2 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
[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
| From | Michael Witten <mfwitten@gmail.com> |
|---|---|
| Date | 2017-10-02 00:40 +0200 |
| Subject | [PATCH net 0/3] net: TCP/IP: A few minor cleanups |
| Message-ID | <uvV3X-7M7-1@gated-at.bofh.it> |
The following patch series is an ad hoc "cleanup" that I made
while perusing the code (I'm not well versed in this code, so I
would not be surprised if there were objections to the changes):
[1] net: __sock_cmsg_send(): Remove unused parameter `msg'
[2] net: inet_recvmsg(): Remove unnecessary bitwise operation
[3] net: skb_queue_purge(): lock/unlock the queue only once
Each patch will be sent as an individual reply to this email;
the total diff is appended below for your convenience.
You may also fetch these patches from GitHub:
git checkout --detach 5969d1bb3082b41eba8fd2c826559abe38ccb6df
git pull https://github.com/mfwitten/linux.git net/tcp-ip/01-cleanup/02
Overall:
include/net/sock.h | 2 +-
net/core/skbuff.c | 26 ++++++++++++++++++--------
net/core/sock.c | 4 ++--
net/ipv4/af_inet.c | 2 +-
net/ipv4/ip_sockglue.c | 2 +-
net/ipv6/datagram.c | 2 +-
6 files changed, 24 insertions(+), 14 deletions(-)
Sincerly,
Michael Witten
diff --git a/include/net/sock.h b/include/net/sock.h
index 03a362568357..83373d7148a9 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1562,7 +1562,7 @@ struct sockcm_cookie {
u16 tsflags;
};
-int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg,
+int __sock_cmsg_send(struct sock *sk, struct cmsghdr *cmsg,
struct sockcm_cookie *sockc);
int sock_cmsg_send(struct sock *sk, struct msghdr *msg,
struct sockcm_cookie *sockc);
diff --git a/net/core/sock.c b/net/core/sock.c
index 9b7b6bbb2a23..425e03fe1c56 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2091,7 +2091,7 @@ struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size,
}
EXPORT_SYMBOL(sock_alloc_send_skb);
-int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg,
+int __sock_cmsg_send(struct sock *sk, struct cmsghdr *cmsg,
struct sockcm_cookie *sockc)
{
u32 tsflags;
@@ -2137,7 +2137,7 @@ int sock_cmsg_send(struct sock *sk, struct msghdr *msg,
return -EINVAL;
if (cmsg->cmsg_level != SOL_SOCKET)
continue;
- ret = __sock_cmsg_send(sk, msg, cmsg, sockc);
+ ret = __sock_cmsg_send(sk, cmsg, sockc);
if (ret)
return ret;
}
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index e558e4f9597b..c79b7822b0b9 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -263,7 +263,7 @@ int ip_cmsg_send(struct sock *sk, struct msghdr *msg, struct ipcm_cookie *ipc,
}
#endif
if (cmsg->cmsg_level == SOL_SOCKET) {
- err = __sock_cmsg_send(sk, msg, cmsg, &ipc->sockc);
+ err = __sock_cmsg_send(sk, cmsg, &ipc->sockc);
if (err)
return err;
continue;
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index a1f918713006..1d1926a4cbe2 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -756,7 +756,7 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
}
if (cmsg->cmsg_level == SOL_SOCKET) {
- err = __sock_cmsg_send(sk, msg, cmsg, sockc);
+ err = __sock_cmsg_send(sk, cmsg, sockc);
if (err)
return err;
continue;
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index e31108e5ef79..2dbed042a412 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -791,7 +791,7 @@ int inet_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
sock_rps_record_flow(sk);
err = sk->sk_prot->recvmsg(sk, msg, size, flags & MSG_DONTWAIT,
- flags & ~MSG_DONTWAIT, &addr_len);
+ flags, &addr_len);
if (err >= 0)
msg->msg_namelen = addr_len;
return err;
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 @@
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
[toc] | [next] | [standalone]
| From | Michael Witten <mfwitten@gmail.com> |
|---|---|
| Date | 2017-10-02 00:50 +0200 |
| Subject | [PATCH net 2/3] net: inet_recvmsg(): Remove unnecessary bitwise operation |
| Message-ID | <uvVdE-7RC-3@gated-at.bofh.it> |
| In reply to | #1742901 |
Date: Fri, 8 Sep 2017 00:47:49 +0000 The flag `MSG_DONTWAIT' is handled by passing an argument through the dedicated parameter `nonblock' of the function `tcp_recvmsg()'. Presumably because `MSG_DONTWAIT' is handled so explicitly, it is unset in the collection of flags that are passed to `tcp_recvmsg()'; yet, this unsetting appears to be unnecessary, and so this commit removes the bitwise operation that performs the unsetting. Signed-off-by: Michael Witten <mfwitten@gmail.com> --- net/ipv4/af_inet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index e31108e5ef79..2dbed042a412 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -791,7 +791,7 @@ int inet_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, sock_rps_record_flow(sk); err = sk->sk_prot->recvmsg(sk, msg, size, flags & MSG_DONTWAIT, - flags & ~MSG_DONTWAIT, &addr_len); + flags, &addr_len); if (err >= 0) msg->msg_namelen = addr_len; return err; -- 2.14.1
[toc] | [prev] | [next] | [standalone]
| From | Michael Witten <mfwitten@gmail.com> |
|---|---|
| Date | 2017-10-02 00:50 +0200 |
| Subject | [PATCH net 3/3] net: skb_queue_purge(): lock/unlock the queue only once |
| Message-ID | <uvVdE-7RC-7@gated-at.bofh.it> |
| In reply to | #1742901 |
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
[toc] | [prev] | [next] | [standalone]
| From | Stephen Hemminger <stephen@networkplumber.org> |
|---|---|
| Date | 2017-10-02 03:00 +0200 |
| Subject | Re: [PATCH net 3/3] net: skb_queue_purge(): lock/unlock the queue only once |
| Message-ID | <uvXfr-z0-3@gated-at.bofh.it> |
| In reply to | #1742905 |
On Sun, 01 Oct 2017 22:19:20 -0000
Michael Witten <mfwitten@gmail.com> wrote:
> + spin_lock_irqsave(&q->lock, flags);
> + skb = q->next;
> + __skb_queue_head_init(q);
> + spin_unlock_irqrestore(&q->lock, flags);
Other code manipulating lists uses splice operation and
a sk_buff_head temporary on the stack. That would be easier
to understand.
struct sk_buf_head head;
__skb_queue_head_init(&head);
spin_lock_irqsave(&q->lock, flags);
skb_queue_splice_init(q, &head);
spin_unlock_irqrestore(&q->lock, flags);
> + while (skb != head) {
> + next = skb->next;
> kfree_skb(skb);
> + skb = next;
> + }
It would be cleaner if you could use
skb_queue_walk_safe rather than open coding the loop.
skb_queue_walk_safe(&head, skb, tmp)
kfree_skb(skb);
[toc] | [prev] | [next] | [standalone]
| From | Michael Witten <mfwitten@gmail.com> |
|---|---|
| Date | 2017-10-02 07:20 +0200 |
| Subject | Re: [PATCH net 3/3] net: skb_queue_purge(): lock/unlock the queue only once |
| Message-ID | <uw1j3-3gP-3@gated-at.bofh.it> |
| In reply to | #1742918 |
On Sun, 1 Oct 2017 17:59:09 -0700, Stephen Hemminger wrote:
> On Sun, 01 Oct 2017 22:19:20 -0000 Michael Witten wrote:
>
>> + spin_lock_irqsave(&q->lock, flags);
>> + skb = q->next;
>> + __skb_queue_head_init(q);
>> + spin_unlock_irqrestore(&q->lock, flags);
>
> Other code manipulating lists uses splice operation and
> a sk_buff_head temporary on the stack. That would be easier
> to understand.
>
> struct sk_buf_head head;
>
> __skb_queue_head_init(&head);
> spin_lock_irqsave(&q->lock, flags);
> skb_queue_splice_init(q, &head);
> spin_unlock_irqrestore(&q->lock, flags);
>
>
>> + while (skb != head) {
>> + next = skb->next;
>> kfree_skb(skb);
>> + skb = next;
>> + }
>
> It would be cleaner if you could use
> skb_queue_walk_safe rather than open coding the loop.
>
> skb_queue_walk_safe(&head, skb, tmp)
> kfree_skb(skb);
I appreciate abstraction as much as anybody, but I do not believe
that such abstractions would actually be an improvement here.
* Splice-initing seems more like an idiom than an abstraction;
at first blush, it wouldn't be clear to me what the intention
is.
* Such abstractions are fairly unnecessary.
* The function as written is already so short as to be
easily digested.
* More to the point, this function is not some generic,
higher-level algorithm that just happens to employ the
socket buffer interface; rather, it is a function that
implements part of that very interface, and may thus
twiddle the intimate bits of these data structures
without being accused of abusing a leaky abstraction.
* Such abstractions add overhead, if only conceptually. In this
case, a temporary socket buffer queue allocates *3* unnecessary
struct members, including a whole `spinlock_t' member:
prev
qlen
lock
It's possible that the compiler will be smart enough to leave
those out, but I have my suspicions that it won't, not only
given that the interface contract requires that the temporary
socket buffer queue be properly initialized before use, but
also because splicing into the temporary will manipulate its
`qlen'. Yet, why worry whether optimization happens? The whole
issue can simply be avoided by exploiting the intimate details
that are already philosophically available to us.
Similarly, the function `skb_queue_walk_safe' is nice, but it
loses value both because a temporary queue loses value (as just
described), and because it ignores the fact that legitimate
access to the internals of these data structures allows for
setting up the requested loop in advance; that is to say, the
two parts of the function that we are now debating can be woven
together more tightly than `skb_queue_walk_safe' allows.
For these reasons, I stand by the way that the patch currently
implements this function; it does exactly what is desired, no more
or less.
Sincerely,
Michael Witten
[toc] | [prev] | [next] | [standalone]
| From | Michael Witten <mfwitten@gmail.com> |
|---|---|
| Date | 2017-10-02 00:50 +0200 |
| Subject | [PATCH net 1/3] net: __sock_cmsg_send(): Remove unused parameter `msg' |
| Message-ID | <uvVdE-7RC-11@gated-at.bofh.it> |
| In reply to | #1742901 |
Date: Thu, 7 Sep 2017 03:21:38 +0000
Signed-off-by: Michael Witten <mfwitten@gmail.com>
---
include/net/sock.h | 2 +-
net/core/sock.c | 4 ++--
net/ipv4/ip_sockglue.c | 2 +-
net/ipv6/datagram.c | 2 +-
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/include/net/sock.h b/include/net/sock.h
index 03a362568357..83373d7148a9 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1562,7 +1562,7 @@ struct sockcm_cookie {
u16 tsflags;
};
-int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg,
+int __sock_cmsg_send(struct sock *sk, struct cmsghdr *cmsg,
struct sockcm_cookie *sockc);
int sock_cmsg_send(struct sock *sk, struct msghdr *msg,
struct sockcm_cookie *sockc);
diff --git a/net/core/sock.c b/net/core/sock.c
index 9b7b6bbb2a23..425e03fe1c56 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2091,7 +2091,7 @@ struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size,
}
EXPORT_SYMBOL(sock_alloc_send_skb);
-int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg,
+int __sock_cmsg_send(struct sock *sk, struct cmsghdr *cmsg,
struct sockcm_cookie *sockc)
{
u32 tsflags;
@@ -2137,7 +2137,7 @@ int sock_cmsg_send(struct sock *sk, struct msghdr *msg,
return -EINVAL;
if (cmsg->cmsg_level != SOL_SOCKET)
continue;
- ret = __sock_cmsg_send(sk, msg, cmsg, sockc);
+ ret = __sock_cmsg_send(sk, cmsg, sockc);
if (ret)
return ret;
}
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index e558e4f9597b..c79b7822b0b9 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -263,7 +263,7 @@ int ip_cmsg_send(struct sock *sk, struct msghdr *msg, struct ipcm_cookie *ipc,
}
#endif
if (cmsg->cmsg_level == SOL_SOCKET) {
- err = __sock_cmsg_send(sk, msg, cmsg, &ipc->sockc);
+ err = __sock_cmsg_send(sk, cmsg, &ipc->sockc);
if (err)
return err;
continue;
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index a1f918713006..1d1926a4cbe2 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -756,7 +756,7 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
}
if (cmsg->cmsg_level == SOL_SOCKET) {
- err = __sock_cmsg_send(sk, msg, cmsg, sockc);
+ err = __sock_cmsg_send(sk, cmsg, sockc);
if (err)
return err;
continue;
--
2.14.1
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web