return 0;
}
+static void vhost_virtqueue_error_notifier(EventNotifier *n)
+{
+ struct vhost_virtqueue *vq = container_of(n, struct vhost_virtqueue,
+ error_notifier);
+ struct vhost_dev *dev = vq->dev;
+ int index = vq - dev->vqs;
+
+ if (event_notifier_test_and_clear(n) && dev->vdev) {
+ VHOST_OPS_DEBUG(-EINVAL, "vhost vring error in virtqueue %d",
+ dev->vq_index + index);
+ }
+}
+
static int vhost_virtqueue_init(struct vhost_dev *dev,
struct vhost_virtqueue *vq, int n)
{
vq->dev = dev;
+ if (dev->vhost_ops->vhost_set_vring_err) {
+ r = event_notifier_init(&vq->error_notifier, 0);
+ if (r < 0) {
+ goto fail_call;
+ }
+
+ file.fd = event_notifier_get_fd(&vq->error_notifier);
+ r = dev->vhost_ops->vhost_set_vring_err(dev, &file);
+ if (r) {
+ VHOST_OPS_DEBUG(r, "vhost_set_vring_err failed");
+ goto fail_err;
+ }
+
+ event_notifier_set_handler(&vq->error_notifier,
+ vhost_virtqueue_error_notifier);
+ }
+
return 0;
+
+fail_err:
+ event_notifier_cleanup(&vq->error_notifier);
fail_call:
event_notifier_cleanup(&vq->masked_notifier);
return r;
static void vhost_virtqueue_cleanup(struct vhost_virtqueue *vq)
{
event_notifier_cleanup(&vq->masked_notifier);
+ if (vq->dev->vhost_ops->vhost_set_vring_err) {
+ event_notifier_set_handler(&vq->error_notifier, NULL);
+ event_notifier_cleanup(&vq->error_notifier);
+ }
}
int vhost_dev_init(struct vhost_dev *hdev, void *opaque,