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) {