fprintf(stderr, "virtio-blk failed to set host notifier (%d)\n", r);
while (i--) {
virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
+ virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i);
}
goto fail_guest_notifiers;
}
for (i = 0; i < nvqs; i++) {
virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
+ virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i);
}
/* Clean up guest notifier (irq) */
aio_context_release(s->ctx);
for (i = 0; i < vs->conf.num_queues + 2; i++) {
virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
+ virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i);
}
k->set_guest_notifiers(qbus->parent, vs->conf.num_queues + 2, false);
fail_guest_notifiers:
for (i = 0; i < vs->conf.num_queues + 2; i++) {
virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), i, false);
+ virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i);
}
/* Clean up guest notifier (irq) */
error_report("vhost VQ %d notifier cleanup error: %d", i, -r);
}
assert (e >= 0);
+ virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), hdev->vq_index + i);
}
virtio_device_release_ioeventfd(vdev);
fail:
error_report("vhost VQ %d notifier cleanup failed: %d", i, -r);
}
assert (r >= 0);
+ virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), hdev->vq_index + i);
}
virtio_device_release_ioeventfd(vdev);
}
r = k->ioeventfd_assign(proxy, notifier, n, true);
if (r < 0) {
error_report("%s: unable to assign ioeventfd: %d", __func__, r);
- goto cleanup_event_notifier;
+ virtio_bus_cleanup_host_notifier(bus, n);
}
- return 0;
} else {
k->ioeventfd_assign(proxy, notifier, n, false);
}
-cleanup_event_notifier:
+ return r;
+}
+
+void virtio_bus_cleanup_host_notifier(VirtioBusState *bus, int n)
+{
+ VirtIODevice *vdev = virtio_bus_get_device(bus);
+ VirtQueue *vq = virtio_get_queue(vdev, n);
+ EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
+
/* Test and clear notifier after disabling event,
* in case poll callback didn't have time to run.
*/
virtio_queue_host_notifier_read(notifier);
event_notifier_cleanup(notifier);
- return r;
}
static char *virtio_bus_get_dev_path(DeviceState *dev)
event_notifier_set_handler(&vq->host_notifier, NULL);
r = virtio_bus_set_host_notifier(qbus, n, false);
assert(r >= 0);
+ virtio_bus_cleanup_host_notifier(qbus, n);
}
return err;
}
event_notifier_set_handler(&vq->host_notifier, NULL);
r = virtio_bus_set_host_notifier(qbus, n, false);
assert(r >= 0);
+ virtio_bus_cleanup_host_notifier(qbus, n);
}
}
void virtio_bus_release_ioeventfd(VirtioBusState *bus);
/* Switch from/to the generic ioeventfd handler */
int virtio_bus_set_host_notifier(VirtioBusState *bus, int n, bool assign);
+/* Tell the bus that the ioeventfd handler is no longer required. */
+void virtio_bus_cleanup_host_notifier(VirtioBusState *bus, int n);
#endif /* VIRTIO_BUS_H */