From mboxrd@z Thu Jan 1 00:00:00 1970 From: Andrey Drobyshev Date: Wed, 19 Aug 2026 12:01:11 +0300 Subject: Re: [Devel] [PATCH vz10 3/5] fixup! vhost/vsock: only refuse connection when guest has never been ready In-Reply-To: References: <20260625181637.1555685-1-eva.kurchatova@virtuozzo.com> <20260625181637.1555685-3-eva.kurchatova@virtuozzo.com> Message-ID: <07f24d9e-08f1-4a4c-932c-0a1a41a77b76@virtuozzo.com> List-Id: 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 >> >> 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; >> >