vhost-user injects a kick by writing to the fd it has just passed to the
back-end. With an eventfd that fd is writable, but when pipes are used
it is the read end and the write fails.

Instead, kick via event_notifier_set() on the queue's host notifier,
which writes to the correct end in both cases.

Signed-off-by: Tim Pambor <[email protected]>
---
Changes in v2:
- Add comment about eventfd vs pipe
- Add assert file->fd == event_notifier_get_fd()
---
 hw/virtio/vhost-user.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 65889b0776..868b3d25ca 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -1527,16 +1527,17 @@ static int vhost_user_set_vring_kick(struct vhost_dev 
*dev,
      * receiving a kick. The spec suggests this to improve compatibility.
      */
     if (file->fd != -1) {
-        uint64_t val = 1;
-        ssize_t nwritten;
-
-        do {
-            nwritten = write(file->fd, &val, sizeof(val));
-        } while (nwritten < 0 && errno == EINTR);
+        /*
+         * With an eventfd that fd is writable, but when pipes are used it is
+         * the read end and the write fails. Instead, kick via
+         * event_notifier_set() on the queue's host notifier, which writes
+         * to the correct end in both cases.
+         */
+        VirtQueue *vq = virtio_get_queue(dev->vdev, file->index);
+        EventNotifier *n = virtio_queue_get_host_notifier(vq);
 
-        if (nwritten < 0 && errno != EAGAIN /* back-end can already read */) {
-            return -errno;
-        }
+        assert(file->fd == event_notifier_get_fd(n));
+        return event_notifier_set(n);
     }
 
     return 0;

-- 
2.55.0


Reply via email to