@@ -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 */
@@ -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);
}
To notify the caller it needs to discard the element. Signed-off-by: Eugenio PĂ©rez <eperezma@redhat.com> --- hw/virtio/vhost-shadow-virtqueue.h | 11 +++++++++++ hw/virtio/vhost-shadow-virtqueue.c | 11 ++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-)