On Sat, Oct 10, 2026 at 10:22:45PM +0800, Jia Jia wrote:
> An RX lock batch still looks up the socket for every packet and takes a
> temporary lookup reference, even though the batch already holds a reference
> to the locked socket.
> 
> Record the network namespace and packet address tuple when a batch starts.
> Reuse the batch socket for later STREAM/RW packets with the same tuple, and
> release the batch before looking up a different flow.
> 
> The cached path still traces every packet, takes an skb owner reference,
> validates socket state, source and transport, updates credit, and runs the
> receive state machine. Only the socket table lookup and its temporary
> reference are skipped.
> 
> Signed-off-by: Jia Jia <[email protected]>
> ---
>  include/linux/virtio_vsock.h            |  3 ++
>  net/vmw_vsock/virtio_transport_common.c | 58 +++++++++++++++----------
>  2 files changed, 38 insertions(+), 23 deletions(-)
> 
> diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h
> index 26dde6909c4e..d6528681e052 100644
> --- a/include/linux/virtio_vsock.h
> +++ b/include/linux/virtio_vsock.h
> @@ -287,6 +287,9 @@ struct virtio_transport_rx_batch {
>       struct sock *sk;
>       unsigned int pkts;
>       size_t bytes;
> +     struct net *net;
> +     struct sockaddr_vm src;
> +     struct sockaddr_vm dst;
>  };
>  
>  void virtio_transport_recv_pkt_batch(struct virtio_transport *t,
> diff --git a/net/vmw_vsock/virtio_transport_common.c 
> b/net/vmw_vsock/virtio_transport_common.c
> index e67dfcaa279c..73e5c7dfe8b4 100644
> --- a/net/vmw_vsock/virtio_transport_common.c
> +++ b/net/vmw_vsock/virtio_transport_common.c
> @@ -1977,6 +1977,7 @@ void virtio_transport_rx_batch_finish(struct 
> virtio_transport_rx_batch *batch)
>       batch->sk = NULL;
>       batch->pkts = 0;
>       batch->bytes = 0;
> +     batch->net = NULL;
>  
>       if (!sk)
>               return;
> @@ -2008,6 +2009,37 @@ void virtio_transport_recv_pkt_batch(struct 
> virtio_transport *t,
>       virtio_transport_recv_pkt_init_addrs(skb, &src, &dst);
>       virtio_transport_trace_recv_pkt(skb, &src, &dst);
>  
> +     if (batch->sk) {
> +             if (batch->net == net &&
> +                 vsock_addr_equals_addr(&batch->src, &src) &&
> +                 vsock_addr_equals_addr(&batch->dst, &dst) &&
> +                 virtio_transport_recv_pkt_batchable(t, batch->sk)) {
> +                     sk = batch->sk;
> +                     if (!skb_set_owner_sk_safe(skb, sk)) {
> +                             WARN_ONCE(1, "receiving vsock socket has 
> sk_refcnt == 0\n");
> +                             virtio_transport_rx_batch_finish(batch);
> +                             kfree_skb(skb);
> +                             return;
> +                     }
> +
> +                     ctx = (struct virtio_transport_rx_pkt_ctx) {
> +                             .net = net,
> +                             .src = &src,
> +                             .dst = &dst,
> +                             .batchable = &batchable,
> +                     };
> +                     free_pkt = virtio_transport_recv_pkt_locked(t, skb, sk, 
> &ctx);
> +
> +                     if (!batchable)
> +                             virtio_transport_rx_batch_finish(batch);
> +                     if (free_pkt)
> +                             kfree_skb(skb);
> +                     return;
> +             }
> +
> +             virtio_transport_rx_batch_finish(batch);
> +     }
> +
>       sk = virtio_transport_recv_pkt_find_socket(skb, &src, &dst, net);
>       if (!sk) {
>               virtio_transport_rx_batch_finish(batch);
> @@ -2018,33 +2050,10 @@ void virtio_transport_recv_pkt_batch(struct 
> virtio_transport *t,
>  
>       if (!skb_set_owner_sk_safe(skb, sk)) {
>               WARN_ONCE(1, "receiving vsock socket has sk_refcnt == 0\n");
> -             virtio_transport_rx_batch_finish(batch);
>               kfree_skb(skb);
>               return;
>       }
>  
> -     if (batch->sk && batch->sk != sk) {
> -             /* Never acquire a second socket lock. */
> -             virtio_transport_rx_batch_finish(batch);
> -     }
> -
> -     if (batch->sk == sk) {
> -             /* Keep the batch reference; drop this packet's lookup 
> reference. */
> -             sock_put(sk);
> -             ctx = (struct virtio_transport_rx_pkt_ctx) {
> -                     .net = net,
> -                     .src = &src,
> -                     .dst = &dst,
> -                     .batchable = &batchable,
> -             };
> -             free_pkt = virtio_transport_recv_pkt_locked(t, skb, sk, &ctx);
> -             if (!batchable)
> -                     virtio_transport_rx_batch_finish(batch);
> -             if (free_pkt)
> -                     kfree_skb(skb);
> -             return;
> -     }
> -

Not sure I love adding code and then removing it in the same series.
Seems like these are asking to be squashed?

>       lock_sock(sk);
>       /*
>        * Sockmap removal restores the native protocol under sk_callback_lock.
> @@ -2063,6 +2072,9 @@ void virtio_transport_recv_pkt_batch(struct 
> virtio_transport *t,
>       free_pkt = virtio_transport_recv_pkt_locked(t, skb, sk, &ctx);
>       if (start_batch && batchable) {
>               /* Keep the lookup reference until the batch is released. */
> +             batch->net = net;
> +             batch->src = src;
> +             batch->dst = dst;

Similar to my comment in the other patch, seems these are all in sk
already?

Best,
Bobby

Reply via email to