| From 3bbdf4c515b984930c6f1d8e81f4b87f568b2ef8 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 17 Jul 2025 10:01:11 +0100 |
| Subject: vsock/virtio: Resize receive buffers so that each SKB fits in a 4K |
| page |
| |
| From: Will Deacon <will@kernel.org> |
| |
| [ Upstream commit 03a92f036a04fed2b00d69f5f46f1a486e70dc5c ] |
| |
| When allocating receive buffers for the vsock virtio RX virtqueue, an |
| SKB is allocated with a 4140 data payload (the 44-byte packet header + |
| VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE). Even when factoring in the SKB |
| overhead, the resulting 8KiB allocation thanks to the rounding in |
| kmalloc_reserve() is wasteful (~3700 unusable bytes) and results in a |
| higher-order page allocation on systems with 4KiB pages just for the |
| sake of a few hundred bytes of packet data. |
| |
| Limit the vsock virtio RX buffers to 4KiB per SKB, resulting in much |
| better memory utilisation and removing the need to allocate higher-order |
| pages entirely. |
| |
| Reviewed-by: Stefano Garzarella <sgarzare@redhat.com> |
| Signed-off-by: Will Deacon <will@kernel.org> |
| Message-Id: <20250717090116.11987-5-will@kernel.org> |
| Signed-off-by: Michael S. Tsirkin <mst@redhat.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| include/linux/virtio_vsock.h | 7 ++++++- |
| net/vmw_vsock/virtio_transport.c | 2 +- |
| 2 files changed, 7 insertions(+), 2 deletions(-) |
| |
| diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h |
| index 3f9c16611306..689e9fc50e1b 100644 |
| --- a/include/linux/virtio_vsock.h |
| +++ b/include/linux/virtio_vsock.h |
| @@ -110,7 +110,12 @@ static inline size_t virtio_vsock_skb_len(struct sk_buff *skb) |
| return (size_t)(skb_end_pointer(skb) - skb->head); |
| } |
| |
| -#define VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE (1024 * 4) |
| +/* Dimension the RX SKB so that the entire thing fits exactly into |
| + * a single 4KiB page. This avoids wasting memory due to alloc_skb() |
| + * rounding up to the next page order and also means that we |
| + * don't leave higher-order pages sitting around in the RX queue. |
| + */ |
| +#define VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE SKB_WITH_OVERHEAD(1024 * 4) |
| #define VIRTIO_VSOCK_MAX_BUF_SIZE 0xFFFFFFFFUL |
| #define VIRTIO_VSOCK_MAX_PKT_BUF_SIZE (1024 * 64) |
| |
| diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c |
| index 5434c9f11d28..e2cd69c127f9 100644 |
| --- a/net/vmw_vsock/virtio_transport.c |
| +++ b/net/vmw_vsock/virtio_transport.c |
| @@ -221,7 +221,7 @@ virtio_transport_cancel_pkt(struct vsock_sock *vsk) |
| |
| static void virtio_vsock_rx_fill(struct virtio_vsock *vsock) |
| { |
| - int total_len = VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE + VIRTIO_VSOCK_SKB_HEADROOM; |
| + int total_len = VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE; |
| struct scatterlist pkt, *p; |
| struct virtqueue *vq; |
| struct sk_buff *skb; |
| -- |
| 2.39.5 |
| |