[Devel] [PATCH vz10 3/5] fixup! vhost/vsock: only refuse connection when guest has never been ready
Andrey Drobyshev
andrey.drobyshev at virtuozzo.com
Wed Aug 19 12:01:11 MSK 2026
On 8/18/26 7:41 PM, Konstantin Khorenko wrote:
> Andrey, can you please clarify - do we really need this patch?
>
> --
> Best regards,
>
> Konstantin Khorenko,
> Virtuozzo Linux Kernel Team
>
No we don't. On branch-rh10-6.12.0-211.39.1.16.x.vz10-ovz we have:
780730eefdcb ("vhost/vsock: suppress EHOSTUNREACH fast-fail during CPR
pause")
9727608ea5ec ("vhost/vsock: always initialize vhost_vsock->cpr_paused
field")
With those applied, my old patch is redundant.
Andrey
> On 6/25/26 20:16, Eva Kurchatova wrote:
>> From: Andrey Drobyshev <andrey.drobyshev at virtuozzo.com>
>>
>> Commit 4ff28534c799 ("ms/vhost/vsock: Refuse the connection immediately
>> when guest isn't ready") added a check which immediately returns
>> EHOSTUNREACH when the guest isn't ready yet. Namely, we check that guest
>> hasn't enabled the RX vq yet, i.e. virtio-vsock has never beed enabled.
>>
>> However, the check also affects the transient state when backend is
>> temporarily set to NULL during VHOST_VSOCK_SET_RUNNING(0). Notably,
>> this is the case with qemu-update operation, during which we perform
>> VHOST_RESET_OWNER. In this case sendmsg()/connect() on otherwise healthy
>> connection gets EHOSTUNREACH.
>>
>> Gate the fast-fail on a sticky started_once bit set in
>> vhost_vsock_start() and never cleared. Once the guest has brought
>> up virtio-vsock at least once, a NULL backend means a transient stop
>> window and the packet must be queued for vhost_vsock_start() to drain
>> on re-attach.
>>
>> Fixes: 4ff28534c799 ("ms/vhost/vsock: Refuse the connection immediately when guest isn't ready")
>> https://virtuozzo.atlassian.net/browse/VSTOR-131956
>> Signed-off-by: Andrey Drobyshev <andrey.drobyshev at virtuozzo.com>
>> ---
>> drivers/vhost/vsock.c | 31 ++++++++++++++-----------------
>> 1 file changed, 14 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
>> index d4c3f94308db..f652f47956d7 100644
>> --- a/drivers/vhost/vsock.c
>> +++ b/drivers/vhost/vsock.c
>> @@ -59,6 +59,7 @@ struct vhost_vsock {
>>
>> u32 guest_cid;
>> bool seqpacket_allow;
>> + bool started_once; /* latched in vhost_vsock_start(); never cleared */
>> bool cpr_paused; /* between stop and next start; queues sends */
>> };
>>
>> @@ -289,24 +290,17 @@ vhost_transport_send_pkt(struct sk_buff *skb, struct net *net)
>> return -ENODEV;
>> }
>>
>> - /* Fast-fail if the guest hasn't enabled the RX vq yet. Queuing the packet
>> - * and making the caller wait is pointless: even if the guest manages to init
>> - * within the timeout, it'll immediately reply with RST, because there's no
>> - * listener on the port yet.
>> - *
>> - * vhost_vq_get_backend() without vq->mutex is acceptable here: locking
>> - * the mutex would be too expensive in this hot path, and we already have
>> - * all the outcomes covered: if the backend becomes NULL right after the check,
>> - * vhost_transport_do_send_pkt() will check it under the mutex anyway.
>> + /*
>> + * Fast-fail only when the guest has never enabled virtio-vsock.
>> + * Once it has, a NULL backend means a transient SET_RUNNING(0)
>> + * window (e.g. VHOST_RESET_OWNER); the packet must be
>> + * queued for vhost_vsock_start() to drain on re-attach.
>> */
>> - /* cpr_paused: queue across CPR; else NULL backend means not ready. */
>> - if (unlikely(!data_race(vhost_vq_get_backend(&vsock->vqs[VSOCK_VQ_RX])))) {
>> - smp_rmb(); /* pairs with smp_wmb() in start/drop_backends */
>> - if (!READ_ONCE(vsock->cpr_paused)) {
>> - rcu_read_unlock();
>> - kfree_skb(skb);
>> - return -EHOSTUNREACH;
>> - }
>> + if (unlikely(!READ_ONCE(vsock->started_once)) &&
>> + !data_race(vhost_vq_get_backend(&vsock->vqs[VSOCK_VQ_RX]))) {
>> + rcu_read_unlock();
>> + kfree_skb(skb);
>> + return -EHOSTUNREACH;
>> }
>>
>> if (virtio_vsock_skb_reply(skb))
>> @@ -637,6 +631,9 @@ static int vhost_vsock_start(struct vhost_vsock *vsock)
>> */
>> vhost_vq_work_queue(&vsock->vqs[VSOCK_VQ_RX], &vsock->send_pkt_work);
>>
>> + /* See vhost_transport_send_pkt(); never cleared. */
>> + WRITE_ONCE(vsock->started_once, true);
>> +
>> mutex_unlock(&vsock->dev.mutex);
>> return 0;
>>
>
More information about the Devel
mailing list