On 5/22/26 3:06 PM, Pavel Tikhomirov wrote: > > > On 5/22/26 12:09, Denis V. Lunev wrote: >> The companion commit preserves ring state across VHOST_RESET_OWNER, >> but QEMU still issues VHOST_VSOCK_SET_RUNNING(0) before RESET_OWNER, >> nulling vq->private_data via vhost_vsock_drop_backends(). The >> fast-fail in vhost_transport_send_pkt() from 4ff28534c799 then >> rejects every host send with -EHOSTUNREACH until the destination >> calls SET_RUNNING(1) -- the entire CPR window becomes a hard >> outage for host AF_VSOCK clients (VSTOR-131956). >> >> Add a cpr_paused flag set by vhost_vsock_stop() when the backend >> was previously live, cleared by vhost_vsock_start(). When set, >> vhost_transport_send_pkt() queues the skb instead of fast-failing; >> the existing kick of send_pkt_work in vhost_vsock_start() drains >> it on resume. A device that has never run keeps cpr_paused == false >> and the boot-time fast-fail behaviour is preserved. >> >> Set the flag before dropping backends so a concurrent sender never >> observes (NULL, !paused). >> >> Feature: kvm >> >> https://virtuozzo.atlassian.net/browse/VSTOR-131956 >> Signed-off-by: Denis V. Lunev <[email protected]> >> --- >> drivers/vhost/vsock.c | 11 ++++++++++- >> 1 file changed, 10 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c >> index 0a518c3d1596..1d2ceec7f2e0 100644 >> --- a/drivers/vhost/vsock.c >> +++ b/drivers/vhost/vsock.c >> @@ -57,6 +57,7 @@ struct vhost_vsock { >> >> u32 guest_cid; >> bool seqpacket_allow; >> + bool cpr_paused; /* between stop and next start; queues sends */ >> }; >> >> static u32 vhost_transport_get_local_cid(void) >> @@ -295,7 +296,9 @@ vhost_transport_send_pkt(struct sk_buff *skb) >> * 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. >> */ >> - if >> (unlikely(!data_race(vhost_vq_get_backend(&vsock->vqs[VSOCK_VQ_RX])))) { >> + /* cpr_paused: queue across CPR; else NULL backend means not ready. */ >> + if (unlikely(!data_race(vhost_vq_get_backend(&vsock->vqs[VSOCK_VQ_RX])) >> && >> + !READ_ONCE(vsock->cpr_paused))) { >> rcu_read_unlock(); >> kfree_skb(skb); >> return -EHOSTUNREACH; >> @@ -610,6 +613,8 @@ static int vhost_vsock_start(struct vhost_vsock *vsock) >> mutex_unlock(&vq->mutex); >> } >> >> + WRITE_ONCE(vsock->cpr_paused, false); >> + >> /* Some packets may have been queued before the device was started, >> * let's kick the send worker to send them. >> */ >> @@ -653,6 +658,7 @@ static void vhost_vsock_drop_backends(struct vhost_vsock >> *vsock) >> static int vhost_vsock_stop(struct vhost_vsock *vsock, bool check_owner) >> { >> int ret = 0; >> + bool was_running; >> >> mutex_lock(&vsock->dev.mutex); >> >> @@ -662,6 +668,9 @@ static int vhost_vsock_stop(struct vhost_vsock *vsock, >> bool check_owner) >> goto err; >> } >> >> + was_running = !!vhost_vq_get_backend(&vsock->vqs[VSOCK_VQ_RX]); >> + if (was_running) >> + WRITE_ONCE(vsock->cpr_paused, true); >> vhost_vsock_drop_backends(vsock); > > Should we do the same in vhost_vsock_reset_owner? We also do > vhost_vsock_drop_backends there. >
At least for qemu-update case it's not necessary. Here QEMU calls VHOST_VSOCK_SET_RUNNING(0) BEFORE it calls VHOST_RESET_OWNER. But for whatever other use case which does VHOST_RESET_OWNER independently it should probably be done. Though I don't know what this case might be. Overall: it should be a no-op for our qemu-update case, and a safe move for whatever other case. >> err: >> mutex_unlock(&vsock->dev.mutex); > _______________________________________________ Devel mailing list [email protected] https://lists.openvz.org/mailman/listinfo/devel
