From mboxrd@z Thu Jan 1 00:00:00 1970 From: Konstantin Khorenko Date: Tue, 18 Aug 2026 18:41:14 +0200 Subject: Re: [Devel] [PATCH vz10 3/5] fixup! vhost/vsock: only refuse connection when guest has never been ready In-Reply-To: <20260625181637.1555685-3-eva.kurchatova@virtuozzo.com> References: <20260625181637.1555685-1-eva.kurchatova@virtuozzo.com> <20260625181637.1555685-3-eva.kurchatova@virtuozzo.com> Message-ID: List-Id: Andrey, can you please clarify - do we really need this patch? -- Best regards, Konstantin Khorenko, Virtuozzo Linux Kernel Team On 6/25/26 20:16, Eva Kurchatova wrote: > From: Andrey Drobyshev > > 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 > --- > 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; >