Subject: [rulkc] [PATCH net-next v4] vsock/virtio: rewrite MSG_ZEROCOPY flag handling

From: sgarzare at redhat.com (Stefano Garzarella)
Date: Tue, 30 Jun 2026 11:41:07 +0200

On Sun, Jun 28, 2026 at 09:20:52PM +0300, Arseniy Krasnov wrote:
>Logically it was based on TCP implementation, so to make further support
>easier, rewrite it in the TCP way (like in 'tcp_sendmsg_locked()'). By
>this way, patch also adds handling case when 'msg_ubuf' is already set.

Thanks for this!

IIUC the result will be similar of commit eb315a7d1396 ("tcp: support 
externally provided ubufs") for tcp. Maybe I would have added it to the 
commit description, anyway the patch LGTM:

Reviewed-by: Stefano Garzarella <sgarzare at redhat.com>

>
>Signed-off-by: Arseniy Krasnov <avkrasnov at rulkc.org>
>---
> Changelog v1->v2:
> * Rebase on last 'net-next'. Don't need 'skb_zcopy_set()' now - it was
>   already added.
> Changelog v2->v3:
> * Update commit message.
> * Remove one empty line.
> Changelog v3->v4:
> * Update commit message.
>
> net/vmw_vsock/virtio_transport_common.c | 47 ++++++++++++-------------
> 1 file changed, 22 insertions(+), 25 deletions(-)
>
>diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
>index 09475007165b..41c2a0b82a8e 100644
>--- a/net/vmw_vsock/virtio_transport_common.c
>+++ b/net/vmw_vsock/virtio_transport_common.c
>@@ -328,38 +328,35 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
> 	if (pkt_len == 0 && info->op == VIRTIO_VSOCK_OP_RW)
> 		return pkt_len;
>
>-	if (info->msg) {
>-		/* If zerocopy is not enabled by 'setsockopt()', we behave as
>-		 * there is no MSG_ZEROCOPY flag set.
>+	if (info->msg && (info->msg->msg_flags & MSG_ZEROCOPY)) {
>+		/* If 'info->msg' is not NULL, this is only VIRTIO_VSOCK_OP_RW.
>+		 * 'MSG_ZEROCOPY' flag handling here is based on the same flag
>+		 * handling from 'tcp_sendmsg_locked()'.
> 		 */
>-		if (!sock_flag(sk_vsock(vsk), SOCK_ZEROCOPY))
>-			info->msg->msg_flags &= ~MSG_ZEROCOPY;
>+		if (info->msg->msg_ubuf) {
>+			uarg = info->msg->msg_ubuf;
>+			can_zcopy = virtio_transport_can_zcopy(t_ops, info, pkt_len);
>+		} else if (sock_flag(sk_vsock(vsk), SOCK_ZEROCOPY)) {
>+			uarg = msg_zerocopy_realloc(sk_vsock(vsk), pkt_len,
>+						    NULL, false);
>+			if (!uarg) {
>+				virtio_transport_put_credit(vvs, pkt_len);
>+				return -ENOMEM;
>+			}
>
>-		if (info->msg->msg_flags & MSG_ZEROCOPY)
> 			can_zcopy = virtio_transport_can_zcopy(t_ops, info, pkt_len);
>+			if (!can_zcopy)
>+				uarg_to_msgzc(uarg)->zerocopy = 0;
>
>+			have_uref = true;
>+		}
>+
>+		/* 'can_zcopy' means that this transmission will be
>+		 * in zerocopy way (e.g. using 'frags' array).
>+		 */
> 		if (can_zcopy)
> 			max_skb_len = min_t(u32, VIRTIO_VSOCK_MAX_PKT_BUF_SIZE,
> 					    (MAX_SKB_FRAGS * PAGE_SIZE));
>-
>-		if (info->msg->msg_flags & MSG_ZEROCOPY &&
>-		    info->op == VIRTIO_VSOCK_OP_RW) {
>-			uarg = info->msg->msg_ubuf;
>-
>-			if (!uarg) {
>-				uarg = msg_zerocopy_realloc(sk_vsock(vsk),
>-							    pkt_len, NULL, false);
>-				if (!uarg) {
>-					virtio_transport_put_credit(vvs, pkt_len);
>-					return -ENOMEM;
>-				}
>-
>-				if (!can_zcopy)
>-					uarg_to_msgzc(uarg)->zerocopy = 0;
>-
>-				have_uref = true;
>-			}
>-		}
> 	}
>
> 	rest_len = pkt_len;
>-- 
>2.25.1
>