mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 11:03:43 +02:00
Merge branch 'vsock-virtio-fix-skb-overhead-accounting-to-preserve-full-buf_alloc'
Stefano Garzarella says: ==================== vsock/virtio: fix skb overhead accounting to preserve full buf_alloc Patch 1 resets the connection when we can no longer queue packets, this prevents silent data loss, and both peers are notified. Patch 2 increases the total budget to `buf_alloc * 2` for payload plus skb overhead similar to how SO_RCVBUF is doubled to reserve space for sk_buff metadata. This preserves the full buf_alloc for payload under normal operation, while still bounding the skb queue growth. In the future, we plan to improve how we handle the merging of packets to minimize overhead and avoid closing connections. v3: https://lore.kernel.org/netdev/20260513105417.56761-1-sgarzare@redhat.com/ v2: https://lore.kernel.org/netdev/20260512080737.36787-1-sgarzare@redhat.com/ v1: https://lore.kernel.org/netdev/20260508092330.69690-1-sgarzare@redhat.com/ ==================== Link: https://patch.msgid.link/20260518090656.134588-1-sgarzare@redhat.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
94e3dd6874
|
|
@ -419,7 +419,14 @@ static bool virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs,
|
|||
{
|
||||
u64 skb_overhead = (skb_queue_len(&vvs->rx_queue) + 1) * SKB_TRUESIZE(0);
|
||||
|
||||
if (skb_overhead + vvs->buf_used + len > vvs->buf_alloc)
|
||||
/* Allow at most buf_alloc * 2 total budget (payload + overhead),
|
||||
* similar to how SO_RCVBUF is doubled to reserve space for sk_buff
|
||||
* metadata. Check payload against buf_alloc to be sure the other
|
||||
* peer is respecting the credit, and sk_buff overhead to bound
|
||||
* queue growth.
|
||||
*/
|
||||
if ((u64)vvs->buf_used + len > vvs->buf_alloc ||
|
||||
skb_overhead > vvs->buf_alloc)
|
||||
return false;
|
||||
|
||||
vvs->rx_bytes += len;
|
||||
|
|
@ -1335,7 +1342,7 @@ virtio_transport_recv_connecting(struct sock *sk,
|
|||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
static bool
|
||||
virtio_transport_recv_enqueue(struct vsock_sock *vsk,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
|
|
@ -1350,10 +1357,8 @@ virtio_transport_recv_enqueue(struct vsock_sock *vsk,
|
|||
spin_lock_bh(&vvs->rx_lock);
|
||||
|
||||
can_enqueue = virtio_transport_inc_rx_pkt(vvs, len);
|
||||
if (!can_enqueue) {
|
||||
free_pkt = true;
|
||||
if (!can_enqueue)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SEQ_EOM)
|
||||
vvs->msg_count++;
|
||||
|
|
@ -1393,6 +1398,8 @@ virtio_transport_recv_enqueue(struct vsock_sock *vsk,
|
|||
spin_unlock_bh(&vvs->rx_lock);
|
||||
if (free_pkt)
|
||||
kfree_skb(skb);
|
||||
|
||||
return can_enqueue;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -1405,7 +1412,17 @@ virtio_transport_recv_connected(struct sock *sk,
|
|||
|
||||
switch (le16_to_cpu(hdr->op)) {
|
||||
case VIRTIO_VSOCK_OP_RW:
|
||||
virtio_transport_recv_enqueue(vsk, skb);
|
||||
if (!virtio_transport_recv_enqueue(vsk, skb)) {
|
||||
/* There is no more space to queue the packet, so let's
|
||||
* close the connection; otherwise, we'll lose data.
|
||||
*/
|
||||
(void)virtio_transport_reset(vsk, skb);
|
||||
virtio_transport_do_close(vsk, true);
|
||||
sk->sk_err = ENOBUFS;
|
||||
sk_error_report(sk);
|
||||
vsock_remove_sock(vsk);
|
||||
break;
|
||||
}
|
||||
vsock_data_ready(sk);
|
||||
return err;
|
||||
case VIRTIO_VSOCK_OP_CREDIT_REQUEST:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user