The commit is pushed to "branch-rh10-6.12.0-55.52.1.5.x.vz10-ovz" and will 
appear at [email protected]:openvz/vzkernel.git
after rh10-6.12.0-55.52.1.5.28.vz10
------>
commit a64088581d4d6f414835a8463271becb1acd3965
Author: Stefano Garzarella <[email protected]>
Date:   Wed May 21 14:17:05 2025 +0200

    ms/vsock/virtio: fix `rx_bytes` accounting for stream sockets
    
    In `struct virtio_vsock_sock`, we maintain two counters:
    - `rx_bytes`: used internally to track how many bytes have been read.
      This supports mechanisms like .stream_has_data() and sock_rcvlowat().
    - `fwd_cnt`: used for the credit mechanism to inform available receive
      buffer space to the remote peer.
    
    These counters are updated via virtio_transport_inc_rx_pkt() and
    virtio_transport_dec_rx_pkt().
    
    Since the beginning with commit 06a8fc78367d ("VSOCK: Introduce
    virtio_vsock_common.ko"), we call virtio_transport_dec_rx_pkt() in
    virtio_transport_stream_do_dequeue() only when we consume the entire
    packet, so partial reads, do not update `rx_bytes` and `fwd_cnt`.
    
    This is fine for `fwd_cnt`, because we still have space used for the
    entire packet, and we don't want to update the credit for the other
    peer until we free the space of the entire packet. However, this
    causes `rx_bytes` to be stale on partial reads.
    
    Previously, this didn’t cause issues because `rx_bytes` was used only by
    .stream_has_data(), and any unread portion of a packet implied data was
    still available. However, since commit 93b808876682
    ("virtio/vsock: fix logic which reduces credit update messages"), we now
    rely on `rx_bytes` to determine if a credit update should be sent when
    the data in the RX queue drops below SO_RCVLOWAT value.
    
    This patch fixes the accounting by updating `rx_bytes` with the number
    of bytes actually read, even on partial reads, while leaving `fwd_cnt`
    untouched until the packet is fully consumed. Also introduce a new
    `buf_used` counter to check that the remote peer is honoring the given
    credit; this was previously done via `rx_bytes`.
    
    Fixes: 93b808876682 ("virtio/vsock: fix logic which reduces credit update 
messages")
    Signed-off-by: Stefano Garzarella <[email protected]>
    Link: https://patch.msgid.link/[email protected]
    Signed-off-by: Paolo Abeni <[email protected]>
    https://virtuozzo.atlassian.net/browse/VSTOR-132908
    Signed-off-by: Denis V. Lunev <[email protected]>
    
    Feature: fix ms/vsock
---
 include/linux/virtio_vsock.h            |  1 +
 net/vmw_vsock/virtio_transport_common.c | 26 ++++++++++++++++----------
 2 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h
index 0387d64e2c66c..36fb3edfa403d 100644
--- a/include/linux/virtio_vsock.h
+++ b/include/linux/virtio_vsock.h
@@ -140,6 +140,7 @@ struct virtio_vsock_sock {
        u32 last_fwd_cnt;
        u32 rx_bytes;
        u32 buf_alloc;
+       u32 buf_used;
        struct sk_buff_head rx_queue;
        u32 msg_count;
 };
diff --git a/net/vmw_vsock/virtio_transport_common.c 
b/net/vmw_vsock/virtio_transport_common.c
index 51a494b69be84..ff295a7818221 100644
--- a/net/vmw_vsock/virtio_transport_common.c
+++ b/net/vmw_vsock/virtio_transport_common.c
@@ -438,18 +438,20 @@ static int virtio_transport_send_pkt_info(struct 
vsock_sock *vsk,
 static bool virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs,
                                        u32 len)
 {
-       if (vvs->rx_bytes + len > vvs->buf_alloc)
+       if (vvs->buf_used + len > vvs->buf_alloc)
                return false;
 
        vvs->rx_bytes += len;
+       vvs->buf_used += len;
        return true;
 }
 
 static void virtio_transport_dec_rx_pkt(struct virtio_vsock_sock *vvs,
-                                       u32 len)
+                                       u32 bytes_read, u32 bytes_dequeued)
 {
-       vvs->rx_bytes -= len;
-       vvs->fwd_cnt += len;
+       vvs->rx_bytes -= bytes_read;
+       vvs->buf_used -= bytes_dequeued;
+       vvs->fwd_cnt += bytes_dequeued;
 }
 
 void virtio_transport_inc_tx_pkt(struct virtio_vsock_sock *vvs, struct sk_buff 
*skb)
@@ -578,11 +580,11 @@ virtio_transport_stream_do_dequeue(struct vsock_sock *vsk,
                                   size_t len)
 {
        struct virtio_vsock_sock *vvs = vsk->trans;
-       size_t bytes, total = 0;
        struct sk_buff *skb;
        u32 fwd_cnt_delta;
        bool low_rx_bytes;
        int err = -EFAULT;
+       size_t total = 0;
        u32 free_space;
 
        spin_lock_bh(&vvs->rx_lock);
@@ -594,6 +596,8 @@ virtio_transport_stream_do_dequeue(struct vsock_sock *vsk,
        }
 
        while (total < len && !skb_queue_empty(&vvs->rx_queue)) {
+               size_t bytes, dequeued = 0;
+
                skb = skb_peek(&vvs->rx_queue);
 
                bytes = min_t(size_t, len - total,
@@ -617,12 +621,12 @@ virtio_transport_stream_do_dequeue(struct vsock_sock *vsk,
                VIRTIO_VSOCK_SKB_CB(skb)->offset += bytes;
 
                if (skb->len == VIRTIO_VSOCK_SKB_CB(skb)->offset) {
-                       u32 pkt_len = le32_to_cpu(virtio_vsock_hdr(skb)->len);
-
-                       virtio_transport_dec_rx_pkt(vvs, pkt_len);
+                       dequeued = le32_to_cpu(virtio_vsock_hdr(skb)->len);
                        __skb_unlink(skb, &vvs->rx_queue);
                        consume_skb(skb);
                }
+
+               virtio_transport_dec_rx_pkt(vvs, bytes, dequeued);
        }
 
        fwd_cnt_delta = vvs->fwd_cnt - vvs->last_fwd_cnt;
@@ -778,7 +782,7 @@ static int virtio_transport_seqpacket_do_dequeue(struct 
vsock_sock *vsk,
                                msg->msg_flags |= MSG_EOR;
                }
 
-               virtio_transport_dec_rx_pkt(vvs, pkt_len);
+               virtio_transport_dec_rx_pkt(vvs, pkt_len, pkt_len);
                kfree_skb(skb);
        }
 
@@ -1722,6 +1726,7 @@ int virtio_transport_read_skb(struct vsock_sock *vsk, 
skb_read_actor_t recv_acto
        struct sock *sk = sk_vsock(vsk);
        struct virtio_vsock_hdr *hdr;
        struct sk_buff *skb;
+       u32 pkt_len;
        int off = 0;
        int err;
 
@@ -1739,7 +1744,8 @@ int virtio_transport_read_skb(struct vsock_sock *vsk, 
skb_read_actor_t recv_acto
        if (le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SEQ_EOM)
                vvs->msg_count--;
 
-       virtio_transport_dec_rx_pkt(vvs, le32_to_cpu(hdr->len));
+       pkt_len = le32_to_cpu(hdr->len);
+       virtio_transport_dec_rx_pkt(vvs, pkt_len, pkt_len);
        spin_unlock_bh(&vvs->rx_lock);
 
        virtio_transport_send_credit_update(vsk);
_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to