>
> 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?
>

I'll fold patch 3 into patch 2 so batching is introduced with
same-flow lookup reuse from the start.

> >       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?
>

For the batch cache, yes. I'll use the locked socket state for the
same-flow check. The packet values still need to be passed to the
locked receive path for source validation and reset handling.

> Best,
> Bobby

Reply via email to