When a live migration is started the log address to mark dirty pages is provided to the vhost backend through the vhost_dev_set_log function. This function is called for each queue pairs but the queue index provided to the vhost_virtqueue_set_addr function is wrongly set: always set to the first queue pair. Then vhost backend lost descriptor addresses of the queue pairs greater than 1 and behaviour of the vhost backend is unpredictable.
The vhost_dev_set_log is modified to provide the correct queue index to the vhost_virtqueue_set_addr function that calls internally the vhost_get_vq_index to compute the expected vhost_vq_index for vhost kernel and vhost user. This change implies a modification of the vhost_virtqueue_start function to provide the index and not the vhost_vq_index. Signed-off-by: Thibaut Collet <thibaut.col...@6wind.com> --- hw/virtio/vhost.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index feeaaa4..9311832 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -628,8 +628,9 @@ static int vhost_virtqueue_set_addr(struct vhost_dev *dev, struct vhost_virtqueue *vq, unsigned idx, bool enable_log) { + int vhost_vq_index = dev->vhost_ops->vhost_get_vq_index(dev, idx); struct vhost_vring_addr addr = { - .index = idx, + .index = vhost_vq_index, .desc_user_addr = (uint64_t)(unsigned long)vq->desc, .avail_user_addr = (uint64_t)(unsigned long)vq->avail, .used_user_addr = (uint64_t)(unsigned long)vq->used, @@ -662,7 +663,7 @@ static int vhost_dev_set_log(struct vhost_dev *dev, bool enable_log) goto err_features; } for (i = 0; i < dev->nvqs; ++i) { - r = vhost_virtqueue_set_addr(dev, dev->vqs + i, i, + r = vhost_virtqueue_set_addr(dev, dev->vqs + i, dev->vq_index + i, enable_log); if (r < 0) { goto err_vq; @@ -671,7 +672,7 @@ static int vhost_dev_set_log(struct vhost_dev *dev, bool enable_log) return 0; err_vq: for (; i >= 0; --i) { - t = vhost_virtqueue_set_addr(dev, dev->vqs + i, i, + t = vhost_virtqueue_set_addr(dev, dev->vqs + i, dev->vq_index + i, dev->log_enabled); assert(t >= 0); } @@ -836,7 +837,7 @@ static int vhost_virtqueue_start(struct vhost_dev *dev, goto fail_alloc_ring; } - r = vhost_virtqueue_set_addr(dev, vq, vhost_vq_index, dev->log_enabled); + r = vhost_virtqueue_set_addr(dev, vq, idx, dev->log_enabled); if (r < 0) { r = -errno; goto fail_alloc; -- 2.1.4