[Devel] [PATCH RHEL9 COMMIT] net: [PATCH VZ9 1/2] zerocopy for unix socket, fixups

Konstantin Khorenko khorenko at virtuozzo.com
Wed Jan 24 18:13:59 MSK 2024


The commit is pushed to "branch-rh9-5.14.0-362.8.1.vz9.35.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh9-5.14.0-362.8.1.vz9.35.8
------>
commit de315c56c4ef8c35bb68b3f1a9dddfff94498581
Author: Alexey Kuznetsov <kuznet at virtuozzo.com>
Date:   Wed Jan 24 03:33:26 2024 +0800

    net: [PATCH VZ9 1/2] zerocopy for unix socket, fixups
    
    We do not want to deal with SOCK_SEQPACKET sockets, as was
    noticed by Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
    
    Fallback for occasional splicing of zerocopied pages did not
    work, returned EINVAL. Not essential as we do not use it,
    still tests revealed this situation. So, repairing this.
    
    vstorage specific note: soon we enable zerocopy at server
    side and will have to choose between zerocopy at sender
    and splice are receiver. Kernel will not be affected.
    Yet, we should think how to save cpu both in server
    and client, this is not impossible, but not straightforward
    at all.
    
    https://pmc.acronis.work/browse/VSTOR-79527
    
    Fixes: 137e8807d5b0 ("net: zerocopy over unix sockets")
    Signed-off-by: Alexey Kuznetsov <kuznet at acronis.com>
    
    Feature: net: zerocopy over unix sockets
---
 net/core/sock.c    |  2 +-
 net/unix/af_unix.c | 31 ++++++++++++++++++++++++-------
 2 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/net/core/sock.c b/net/core/sock.c
index e53ec1279c14..a4367895149c 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1448,7 +1448,7 @@ int sk_setsockopt(struct sock *sk, int level, int optname,
 			       sk->sk_protocol == IPPROTO_UDP)))
 				ret = -EOPNOTSUPP;
 		} else if (sk->sk_family == PF_UNIX) {
-			if (sk->sk_type == SOCK_DGRAM)
+			if (sk->sk_type != SOCK_STREAM)
 				ret = -EOPNOTSUPP;
 		} else if (sk->sk_family != PF_RDS) {
 			ret = -EOPNOTSUPP;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 8ebaaa41fa73..2f4d192cceca 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2832,16 +2832,33 @@ static int unix_stream_splice_actor(struct sk_buff *skb,
 {
 	/* Zerocopy pages cannot be spliced, alas. It looks like splice interface
 	 * gives no way to notify about actual page consumption. So, we have to copy.
-	 * This path is not going be legit, sender will be notified and will stop zerocopying.
+	 * This path is not going be used, sender and receiver should agree
+	 * about the protocol apriori or sender will be notified with
+	 * SO_EE_CODE_ZEROCOPY_COPIED to stop zerocopying.
 	 */
-	int err = skb_orphan_frags_rx(skb, GFP_KERNEL);
+	int err = 0;
+	struct sk_buff *__skb = skb;
+
+	if (skb_zcopy(skb)) {
+		/* skb is always shared, unfortunately. */
+		if (skb_shared(skb)) {
+			__skb = skb_clone(skb, GFP_KERNEL);
+			if (!__skb)
+				return -ENOMEM;
+		}
+		err = skb_orphan_frags_rx(__skb, GFP_KERNEL);
+		if (err)
+			goto out;
+	}
 
-	if (err)
-		return err;
+	err = skb_splice_bits(__skb, state->socket->sk,
+			      UNIXCB(__skb).consumed + skip,
+			      state->pipe, chunk, state->splice_flags);
 
-	return skb_splice_bits(skb, state->socket->sk,
-			       UNIXCB(skb).consumed + skip,
-			       state->pipe, chunk, state->splice_flags);
+out:
+	if (skb != __skb)
+		kfree_skb(__skb);
+	return err;
 }
 
 static ssize_t unix_stream_splice_read(struct socket *sock,  loff_t *ppos,


More information about the Devel mailing list