The vhost-user specification was updated to say that front-ends should inject a kick after SET_VRING_KICK in case the back-end implements the old spec wording which said vrings start when a kick is received. Do this in QEMU's front-end.
An example scenario where this behavior helps: the back-end fails to check if the vring has available buffers when SET_VRING_KICK is received and the front-end stopped and then restarted the vring. In the case the back-end may not notice the available buffers unless the front-end injects a kick. Signed-off-by: Stefan Hajnoczi <[email protected]> --- hw/virtio/vhost-user.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index a8907cca74..7ef4105473 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -1365,7 +1365,29 @@ static int vhost_set_vring_file(struct vhost_dev *dev, static int vhost_user_set_vring_kick(struct vhost_dev *dev, struct vhost_vring_file *file) { - return vhost_set_vring_file(dev, VHOST_USER_SET_VRING_KICK, file); + int ret = vhost_set_vring_file(dev, VHOST_USER_SET_VRING_KICK, file); + if (ret < 0) { + return ret; + } + + /* + * Inject a kick in case the back-end only starts vring processing upon + * 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); + + if (nwritten < 0 && errno != EAGAIN /* back-end can already read */) { + return -errno; + } + } + + return 0; } static int vhost_user_set_vring_call(struct vhost_dev *dev, -- 2.54.0
