To notify the caller it needs to discard the element. Signed-off-by: Eugenio Pérez <epere...@redhat.com> --- hw/virtio/vhost-shadow-virtqueue.h | 11 +++++++++++ hw/virtio/vhost-shadow-virtqueue.c | 11 ++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/hw/virtio/vhost-shadow-virtqueue.h b/hw/virtio/vhost-shadow-virtqueue.h index 4300cb66f8..583b6fda5d 100644 --- a/hw/virtio/vhost-shadow-virtqueue.h +++ b/hw/virtio/vhost-shadow-virtqueue.h @@ -46,10 +46,21 @@ typedef void (*VirtQueueUsedCallback)(VhostShadowVirtqueue *svq, void *used_elem_opaque, uint32_t written); +/** + * Detach the element from the shadow virtqueue. SVQ needs to free it and it + * cannot be pushed or discarded. + * + * @elem_opaque: The element opaque + * + * Return the guest element to detach and free if any. + */ +typedef VirtQueueElement *(*VirtQueueDetachCallback)(void *elem_opaque); + typedef struct VhostShadowVirtqueueOps { ShadowVirtQueueStart start; VirtQueueAvailCallback avail_handler; VirtQueueUsedCallback used_handler; + VirtQueueDetachCallback detach_handler; } VhostShadowVirtqueueOps; /* Shadow virtqueue to relay notifications */ diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c index dffea256f1..4f072f040b 100644 --- a/hw/virtio/vhost-shadow-virtqueue.c +++ b/hw/virtio/vhost-shadow-virtqueue.c @@ -746,7 +746,16 @@ void vhost_svq_stop(VhostShadowVirtqueue *svq) for (unsigned i = 0; i < svq->vring.num; ++i) { g_autofree VirtQueueElement *elem = NULL; - elem = g_steal_pointer(&svq->ring_id_maps[i].opaque); + void *opaque = g_steal_pointer(&svq->ring_id_maps[i].opaque); + + if (!opaque) { + continue; + } else if (svq->ops) { + elem = svq->ops->detach_handler(opaque); + } else { + elem = opaque; + } + if (elem) { virtqueue_detach_element(svq->vq, elem, 0); } -- 2.31.1