From 7fcbd0220ef901a58228dc648cee1324ac236c72 Mon Sep 17 00:00:00 2001 From: Changpeng Liu Date: Tue, 11 Oct 2022 17:16:28 +0800 Subject: [PATCH] lib/vhost: alloc VQ tasks in VQ setting function Currently we will allocate all VQ's tasks when starting the device, it will not allow us to add new VQ after starting the device, so here, we move it to VQ setting function. Change-Id: I59cfc393d66779ab8a0eb704bc73bcede3f0a2a0 Signed-off-by: Changpeng Liu Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14926 Reviewed-by: Ben Walker Reviewed-by: Jim Harris Tested-by: SPDK CI Jenkins --- lib/vhost/rte_vhost_user.c | 8 +++++ lib/vhost/vhost_blk.c | 70 ++++++++++++++++++------------------- lib/vhost/vhost_internal.h | 1 + lib/vhost/vhost_scsi.c | 71 ++++++++++++++++++-------------------- 4 files changed, 76 insertions(+), 74 deletions(-) diff --git a/lib/vhost/rte_vhost_user.c b/lib/vhost/rte_vhost_user.c index b0d8b4f67..b401b6604 100644 --- a/lib/vhost/rte_vhost_user.c +++ b/lib/vhost/rte_vhost_user.c @@ -1018,6 +1018,8 @@ enable_device_vq(struct spdk_vhost_session *vsession, uint16_t qid) { struct spdk_vhost_virtqueue *q; bool packed_ring; + const struct spdk_vhost_user_dev_backend *backend; + int rc; if (qid >= SPDK_VHOST_MAX_VQUEUES) { return -EINVAL; @@ -1047,6 +1049,12 @@ enable_device_vq(struct spdk_vhost_session *vsession, uint16_t qid) return 0; } + backend = to_user_dev(vsession->vdev)->user_backend; + rc = backend->alloc_vq_tasks(vsession, qid); + if (rc) { + return rc; + } + /* * Not sure right now but this look like some kind of QEMU bug and guest IO * might be frozed without kicking all queues after live-migration. This look like diff --git a/lib/vhost/vhost_blk.c b/lib/vhost/vhost_blk.c index 2f63f49ec..dbe2086f9 100644 --- a/lib/vhost/vhost_blk.c +++ b/lib/vhost/vhost_blk.c @@ -1246,45 +1246,46 @@ free_task_pool(struct spdk_vhost_blk_session *bvsession) } static int -alloc_task_pool(struct spdk_vhost_blk_session *bvsession) +alloc_vq_task_pool(struct spdk_vhost_session *vsession, uint16_t qid) { - struct spdk_vhost_session *vsession = &bvsession->vsession; + struct spdk_vhost_blk_session *bvsession = to_blk_session(vsession); struct spdk_vhost_virtqueue *vq; struct spdk_vhost_user_blk_task *task; uint32_t task_cnt; - uint16_t i; uint32_t j; - for (i = 0; i < vsession->max_queues; i++) { - vq = &vsession->virtqueue[i]; - if (vq->vring.desc == NULL) { - continue; - } + if (qid >= SPDK_VHOST_MAX_VQUEUES) { + return -EINVAL; + } - task_cnt = vq->vring.size; - if (task_cnt > SPDK_VHOST_MAX_VQ_SIZE) { - /* sanity check */ - SPDK_ERRLOG("%s: virtqueue %"PRIu16" is too big. (size = %"PRIu32", max = %"PRIu32")\n", - vsession->name, i, task_cnt, SPDK_VHOST_MAX_VQ_SIZE); - free_task_pool(bvsession); - return -1; - } - vq->tasks = spdk_zmalloc(sizeof(struct spdk_vhost_user_blk_task) * task_cnt, - SPDK_CACHE_LINE_SIZE, NULL, - SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); - if (vq->tasks == NULL) { - SPDK_ERRLOG("%s: failed to allocate %"PRIu32" tasks for virtqueue %"PRIu16"\n", - vsession->name, task_cnt, i); - free_task_pool(bvsession); - return -1; - } + vq = &vsession->virtqueue[qid]; + if (vq->vring.desc == NULL) { + return 0; + } - for (j = 0; j < task_cnt; j++) { - task = &((struct spdk_vhost_user_blk_task *)vq->tasks)[j]; - task->bvsession = bvsession; - task->req_idx = j; - task->vq = vq; - } + task_cnt = vq->vring.size; + if (task_cnt > SPDK_VHOST_MAX_VQ_SIZE) { + /* sanity check */ + SPDK_ERRLOG("%s: virtqueue %"PRIu16" is too big. (size = %"PRIu32", max = %"PRIu32")\n", + vsession->name, qid, task_cnt, SPDK_VHOST_MAX_VQ_SIZE); + free_task_pool(bvsession); + return -1; + } + vq->tasks = spdk_zmalloc(sizeof(struct spdk_vhost_user_blk_task) * task_cnt, + SPDK_CACHE_LINE_SIZE, NULL, + SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); + if (vq->tasks == NULL) { + SPDK_ERRLOG("%s: failed to allocate %"PRIu32" tasks for virtqueue %"PRIu16"\n", + vsession->name, task_cnt, qid); + free_task_pool(bvsession); + return -1; + } + + for (j = 0; j < task_cnt; j++) { + task = &((struct spdk_vhost_user_blk_task *)vq->tasks)[j]; + task->bvsession = bvsession; + task->req_idx = j; + task->vq = vq; } return 0; @@ -1313,12 +1314,6 @@ vhost_blk_start(struct spdk_vhost_dev *vdev, } } - rc = alloc_task_pool(bvsession); - if (rc != 0) { - SPDK_ERRLOG("%s: failed to alloc task pool.\n", vsession->name); - return rc; - } - if (bvdev->bdev) { bvsession->io_channel = vhost_blk_get_io_channel(vdev); if (!bvsession->io_channel) { @@ -1544,6 +1539,7 @@ static const struct spdk_vhost_user_dev_backend vhost_blk_user_device_backend = .session_ctx_size = sizeof(struct spdk_vhost_blk_session) - sizeof(struct spdk_vhost_session), .start_session = vhost_blk_start, .stop_session = vhost_blk_stop, + .alloc_vq_tasks = alloc_vq_task_pool, }; static const struct spdk_vhost_dev_backend vhost_blk_device_backend = { diff --git a/lib/vhost/vhost_internal.h b/lib/vhost/vhost_internal.h index 8a1f1ea61..26aa575f6 100644 --- a/lib/vhost/vhost_internal.h +++ b/lib/vhost/vhost_internal.h @@ -219,6 +219,7 @@ struct spdk_vhost_user_dev_backend { spdk_vhost_session_fn start_session; int (*stop_session)(struct spdk_vhost_session *vsession); + int (*alloc_vq_tasks)(struct spdk_vhost_session *vsession, uint16_t qid); }; enum vhost_backend_type { diff --git a/lib/vhost/vhost_scsi.c b/lib/vhost/vhost_scsi.c index 4fa8df7a0..ccdfc0ab7 100644 --- a/lib/vhost/vhost_scsi.c +++ b/lib/vhost/vhost_scsi.c @@ -122,11 +122,13 @@ static void vhost_scsi_write_config_json(struct spdk_vhost_dev *vdev, static int vhost_scsi_dev_remove(struct spdk_vhost_dev *vdev); static int vhost_scsi_dev_param_changed(struct spdk_vhost_dev *vdev, unsigned scsi_tgt_num); +static int alloc_vq_task_pool(struct spdk_vhost_session *vsession, uint16_t qid); static const struct spdk_vhost_user_dev_backend spdk_vhost_scsi_user_device_backend = { .session_ctx_size = sizeof(struct spdk_vhost_scsi_session) - sizeof(struct spdk_vhost_session), .start_session = vhost_scsi_start, .stop_session = vhost_scsi_stop, + .alloc_vq_tasks = alloc_vq_task_pool, }; static const struct spdk_vhost_dev_backend spdk_vhost_scsi_device_backend = { @@ -1307,45 +1309,46 @@ free_task_pool(struct spdk_vhost_scsi_session *svsession) } static int -alloc_task_pool(struct spdk_vhost_scsi_session *svsession) +alloc_vq_task_pool(struct spdk_vhost_session *vsession, uint16_t qid) { - struct spdk_vhost_session *vsession = &svsession->vsession; + struct spdk_vhost_scsi_session *svsession = to_scsi_session(vsession); struct spdk_vhost_virtqueue *vq; struct spdk_vhost_scsi_task *task; uint32_t task_cnt; - uint16_t i; uint32_t j; - for (i = 0; i < vsession->max_queues; i++) { - vq = &vsession->virtqueue[i]; - if (vq->vring.desc == NULL) { - continue; - } + if (qid >= SPDK_VHOST_MAX_VQUEUES) { + return -EINVAL; + } - task_cnt = vq->vring.size; - if (task_cnt > SPDK_VHOST_MAX_VQ_SIZE) { - /* sanity check */ - SPDK_ERRLOG("%s: virtqueue %"PRIu16" is too big. (size = %"PRIu32", max = %"PRIu32")\n", - vsession->name, i, task_cnt, SPDK_VHOST_MAX_VQ_SIZE); - free_task_pool(svsession); - return -1; - } - vq->tasks = spdk_zmalloc(sizeof(struct spdk_vhost_scsi_task) * task_cnt, - SPDK_CACHE_LINE_SIZE, NULL, - SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); - if (vq->tasks == NULL) { - SPDK_ERRLOG("%s: failed to allocate %"PRIu32" tasks for virtqueue %"PRIu16"\n", - vsession->name, task_cnt, i); - free_task_pool(svsession); - return -1; - } + vq = &vsession->virtqueue[qid]; + if (vq->vring.desc == NULL) { + return 0; + } - for (j = 0; j < task_cnt; j++) { - task = &((struct spdk_vhost_scsi_task *)vq->tasks)[j]; - task->svsession = svsession; - task->vq = vq; - task->req_idx = j; - } + task_cnt = vq->vring.size; + if (task_cnt > SPDK_VHOST_MAX_VQ_SIZE) { + /* sanity check */ + SPDK_ERRLOG("%s: virtqueue %"PRIu16" is too big. (size = %"PRIu32", max = %"PRIu32")\n", + vsession->name, qid, task_cnt, SPDK_VHOST_MAX_VQ_SIZE); + free_task_pool(svsession); + return -1; + } + vq->tasks = spdk_zmalloc(sizeof(struct spdk_vhost_scsi_task) * task_cnt, + SPDK_CACHE_LINE_SIZE, NULL, + SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); + if (vq->tasks == NULL) { + SPDK_ERRLOG("%s: failed to allocate %"PRIu32" tasks for virtqueue %"PRIu16"\n", + vsession->name, task_cnt, qid); + free_task_pool(svsession); + return -1; + } + + for (j = 0; j < task_cnt; j++) { + task = &((struct spdk_vhost_scsi_task *)vq->tasks)[j]; + task->svsession = svsession; + task->vq = vq; + task->req_idx = j; } return 0; @@ -1373,12 +1376,6 @@ vhost_scsi_start(struct spdk_vhost_dev *vdev, } } - rc = alloc_task_pool(svsession); - if (rc != 0) { - SPDK_ERRLOG("%s: failed to alloc task pool.\n", vsession->name); - return rc; - } - for (i = 0; i < SPDK_VHOST_SCSI_CTRLR_MAX_DEVS; i++) { state = &svdev->scsi_dev_state[i]; if (state->dev == NULL || state->status == VHOST_SCSI_DEV_REMOVING) {