vdpa: fix vhost-vdpa suspended state not be shared

When stopping a vhost-vdpa device, only the first queue pair is marked as suspended,
while the remaining queues are not updated to the suspended state.
As a result, when stopping a multi-queue vhost-vdpa device,
the following error message will be printed.

qemu-system-x86_64:vhost VQ 2 ring restore failed: -1: Operation not permitted (1)

qemu-system-x86_64:vhost VQ 3 ring restore failed: -1: Operation not permitted (1)

So move v->suspended to v->shared, and then all the vhost_vdpa devices cannot
have different suspended states.

Fixes: 0bb302a996 ("vdpa: add vhost_vdpa_suspend")
Suggested-by: Eugenio Pérez <eperezma@redhat.com>
Acked-by: Eugenio Pérez <eperezma@redhat.com>
Acked-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Wafer Xie <wafer@jaguarmicro.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Jason Wang <jasowang@redhat.com>
Message-Id: <20251119132452.3117-1-wafer@jaguarmicro.com>
(cherry picked from commit fd3a2c601ab4a1bdb669e4c584b364e00a978702)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
This commit is contained in:
Wafer Xie 2025-11-19 21:24:52 +08:00 committed by Michael Tokarev
parent 0b1ddf19d0
commit ad2c2ef5e5
2 changed files with 9 additions and 5 deletions

View file

@ -905,7 +905,7 @@ static int vhost_vdpa_reset_device(struct vhost_dev *dev)
memory_listener_unregister(&v->shared->listener); memory_listener_unregister(&v->shared->listener);
v->shared->listener_registered = false; v->shared->listener_registered = false;
v->suspended = false; v->shared->suspended = false;
return 0; return 0;
} }
@ -1354,7 +1354,7 @@ static void vhost_vdpa_suspend(struct vhost_dev *dev)
if (unlikely(r)) { if (unlikely(r)) {
error_report("Cannot suspend: %s(%d)", g_strerror(errno), errno); error_report("Cannot suspend: %s(%d)", g_strerror(errno), errno);
} else { } else {
v->suspended = true; v->shared->suspended = true;
return; return;
} }
} }
@ -1481,7 +1481,7 @@ static int vhost_vdpa_get_vring_base(struct vhost_dev *dev,
return 0; return 0;
} }
if (!v->suspended) { if (!v->shared->suspended) {
/* /*
* Cannot trust in value returned by device, let vhost recover used * Cannot trust in value returned by device, let vhost recover used
* idx from guest. * idx from guest.

View file

@ -76,6 +76,12 @@ typedef struct vhost_vdpa_shared {
/* SVQ switching is in progress, or already completed? */ /* SVQ switching is in progress, or already completed? */
SVQTransitionState svq_switching; SVQTransitionState svq_switching;
/*
* Device suspended successfully.
* The vhost_vdpa devices cannot have different suspended states.
*/
bool suspended;
} VhostVDPAShared; } VhostVDPAShared;
typedef struct vhost_vdpa { typedef struct vhost_vdpa {
@ -83,8 +89,6 @@ typedef struct vhost_vdpa {
uint32_t address_space_id; uint32_t address_space_id;
uint64_t acked_features; uint64_t acked_features;
bool shadow_vqs_enabled; bool shadow_vqs_enabled;
/* Device suspended successfully */
bool suspended;
VhostVDPAShared *shared; VhostVDPAShared *shared;
GPtrArray *shadow_vqs; GPtrArray *shadow_vqs;
const VhostShadowVirtqueueOps *shadow_vq_ops; const VhostShadowVirtqueueOps *shadow_vq_ops;