vsock/virtio: rewrite MSG_ZEROCOPY flag handling

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.

Signed-off-by: Arseniy Krasnov <avkrasnov@rulkc.org>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Link: https://patch.msgid.link/20260628182052.951760-1-avkrasnov@rulkc.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Arseniy Krasnov
2026-06-28 21:20:52 +03:00
committed by Paolo Abeni
parent cef9d68040
commit f456c1922c

View File

@@ -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_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;
}
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;