From 148eda65c1b41a9340cb8d3768702eca2b556a76 Mon Sep 17 00:00:00 2001 From: Darek Stojaczyk Date: Mon, 7 Jan 2019 22:26:14 +0100 Subject: [PATCH] virtio: don't reinitialize entire virtqueues on mem hotplug One of the messages we send on memory hotplug event is SET_VRING_BASE, which tells vhost e.g. the position in a vring it should start processing requests from. Sending this message with any outstanding I/O could cause that I/O to be never processed as it could be at a vring position that won't be practically polled. To fix the above, we don't send SET_VRING_BASE message on memory hotplug event anymore since it's completely unnecessary. It was sent together with a couple other messages that would reinitialize the vring, but we know vrings occupy a memory buffer that won't be hotremoved during vring lifetime. We also know that vring GPAs will never change. Hence we can initialize the vrings just once on device start now. We still need to send SET_VRING_ADDR after updating the memory table, as rte_vhost depends on it to apply that new memory table. Luckily, this single message doesn't cause us any trouble. Change-Id: I2125099f1cf3f8c76e8160ec819bd1a9a3e7823c Signed-off-by: Darek Stojaczyk Reviewed-on: https://review.gerrithub.io/c/439436 Tested-by: SPDK CI Jenkins Chandler-Test-Pool: SPDK Automated Test System Reviewed-by: Pawel Wodkowski Reviewed-by: Ben Walker Reviewed-by: Jim Harris --- lib/virtio/virtio_user.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/virtio/virtio_user.c b/lib/virtio/virtio_user.c index 5dadda6177..fddc79ca85 100644 --- a/lib/virtio/virtio_user.c +++ b/lib/virtio/virtio_user.c @@ -67,11 +67,9 @@ virtio_user_create_queue(struct virtio_dev *vdev, uint32_t queue_sel) } static int -virtio_user_kick_queue(struct virtio_dev *vdev, uint32_t queue_sel) +virtio_user_set_vring_addr(struct virtio_dev *vdev, uint32_t queue_sel) { struct virtio_user_dev *dev = vdev->ctx; - struct vhost_vring_file file; - struct vhost_vring_state state; struct vring *vring = &dev->vrings[queue_sel]; struct vhost_vring_addr addr = { .index = queue_sel, @@ -81,6 +79,17 @@ virtio_user_kick_queue(struct virtio_dev *vdev, uint32_t queue_sel) .log_guest_addr = 0, .flags = 0, /* disable log */ }; + + return dev->ops->send_request(dev, VHOST_USER_SET_VRING_ADDR, &addr); +} + +static int +virtio_user_kick_queue(struct virtio_dev *vdev, uint32_t queue_sel) +{ + struct virtio_user_dev *dev = vdev->ctx; + struct vhost_vring_file file; + struct vhost_vring_state state; + struct vring *vring = &dev->vrings[queue_sel]; int rc; state.index = queue_sel; @@ -97,10 +106,7 @@ virtio_user_kick_queue(struct virtio_dev *vdev, uint32_t queue_sel) return rc; } - rc = dev->ops->send_request(dev, VHOST_USER_SET_VRING_ADDR, &addr); - if (rc < 0) { - return rc; - } + virtio_user_set_vring_addr(vdev, queue_sel); /* Of all per virtqueue MSGs, make sure VHOST_USER_SET_VRING_KICK comes * lastly because vhost depends on this msg to judge if @@ -162,7 +168,7 @@ virtio_user_map_notify(void *cb_ctx, struct spdk_mem_map *map, /* We have to send SET_VRING_ADDR to make rte_vhost flush a pending * SET_MEM_TABLE... */ - ret = virtio_user_queue_setup(vdev, virtio_user_kick_queue); + ret = virtio_user_queue_setup(vdev, virtio_user_set_vring_addr); if (ret < 0) { return ret; } @@ -243,7 +249,7 @@ virtio_user_start_device(struct virtio_dev *vdev) return ret; } - return 0; + return virtio_user_queue_setup(vdev, virtio_user_kick_queue); } static int