diff --git a/lib/vhost/Makefile b/lib/vhost/Makefile index 50899b2fa..5cc76ff76 100644 --- a/lib/vhost/Makefile +++ b/lib/vhost/Makefile @@ -38,7 +38,7 @@ CFLAGS += -I. CFLAGS += -Irte_vhost CFLAGS += $(ENV_CFLAGS) -C_SRCS = task.c vhost.c vhost_rpc.c vhost_iommu.c vhost_scsi.c vhost_blk.c +C_SRCS = vhost.c vhost_rpc.c vhost_iommu.c vhost_scsi.c vhost_blk.c LIBNAME = vhost diff --git a/lib/vhost/task.c b/lib/vhost/task.c deleted file mode 100644 index 828aa931d..000000000 --- a/lib/vhost/task.c +++ /dev/null @@ -1,110 +0,0 @@ -/*- - * BSD LICENSE - * - * Copyright (c) Intel Corporation. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "spdk/stdinc.h" - -#include -#include - -#include "spdk_internal/log.h" -#include "spdk_internal/event.h" -#include "spdk/env.h" -#include "spdk/queue.h" -#include "spdk/vhost.h" -#include "vhost_internal.h" -#include "task.h" - -static struct rte_mempool *g_task_pool; - -void -spdk_vhost_task_put(struct spdk_vhost_task *task) -{ - spdk_scsi_task_put(&task->scsi); -} - -static void -spdk_vhost_task_free_cb(struct spdk_scsi_task *scsi_task) -{ - struct spdk_vhost_task *task = container_of(scsi_task, struct spdk_vhost_task, scsi); - - assert(((struct spdk_vhost_dev *) task->svdev)->task_cnt > 0); - ((struct spdk_vhost_dev *) task->svdev)->task_cnt--; - rte_mempool_put(g_task_pool, task); -} - -void -spdk_vhost_task_get(struct spdk_vhost_scsi_dev *svdev, void **tasks, int count, - spdk_scsi_task_cpl cpl_fn) -{ - struct spdk_vhost_task *task; - int rc, i; - - rc = rte_mempool_get_bulk(g_task_pool, tasks, count); - if (rc < 0) { - SPDK_ERRLOG("Unable to get task\n"); - rte_panic("no memory\n"); - } - - assert(((struct spdk_vhost_dev *) svdev)->task_cnt <= INT_MAX - count); - ((struct spdk_vhost_dev *) svdev)->task_cnt += count; - - for (i = 0; i < count; ++i) { - task = tasks[i]; - memset(task, 0, sizeof(*task)); - - task->svdev = svdev; - spdk_scsi_task_construct(&task->scsi, - cpl_fn, - spdk_vhost_task_free_cb, - NULL); - } -} - -int -spdk_vhost_init(void) -{ - g_task_pool = rte_mempool_create("vhost task pool", 16384, sizeof(struct spdk_vhost_task), - 128, 0, NULL, NULL, NULL, NULL, SOCKET_ID_ANY, 0); - if (!g_task_pool) { - SPDK_ERRLOG("create task pool failed\n"); - return -1; - } - - return 0; -} - -int -spdk_vhost_fini(void) -{ - return 0; -} diff --git a/lib/vhost/task.h b/lib/vhost/task.h deleted file mode 100644 index 421fbc2ea..000000000 --- a/lib/vhost/task.h +++ /dev/null @@ -1,74 +0,0 @@ -/*- - * BSD LICENSE - * - * Copyright (c) Intel Corporation. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SPDK_VHOST_TASK_H -#define SPDK_VHOST_TASK_H - -#include "spdk/scsi.h" - -#undef container_of -#define container_of(ptr, type, member) ({ \ - typeof(((type *)0)->member) *__mptr = (ptr); \ - (type *)((char *)__mptr - offsetof(type, member)); }) - -/* Allocated iovec buffer len */ -#define VHOST_SCSI_IOVS_LEN 128 - -struct spdk_vhost_dev; - -struct spdk_vhost_task { - struct spdk_scsi_task scsi; - struct iovec iovs[VHOST_SCSI_IOVS_LEN]; - - union { - struct virtio_scsi_cmd_resp *resp; - struct virtio_scsi_ctrl_tmf_resp *tmf_resp; - }; - - struct spdk_vhost_scsi_dev *svdev; - struct spdk_scsi_dev *scsi_dev; - - int req_idx; - - struct rte_vhost_vring *vq; -}; - -void spdk_vhost_task_put(struct spdk_vhost_task *task); -void spdk_vhost_task_get(struct spdk_vhost_scsi_dev *svdev, void **tasks, int count, - spdk_scsi_task_cpl cpl_fn); - -void spdk_vhost_task_cpl(struct spdk_scsi_task *scsi_task); -void spdk_vhost_task_mgmt_cpl(struct spdk_scsi_task *scsi_task); - - -#endif /* SPDK_VHOST_TASK_H */ diff --git a/lib/vhost/vhost.c b/lib/vhost/vhost.c index f433836fa..c361dc99f 100644 --- a/lib/vhost/vhost.c +++ b/lib/vhost/vhost.c @@ -39,7 +39,6 @@ #include "spdk/vhost.h" #include "vhost_internal.h" -#include "task.h" #include "vhost_iommu.h" static uint32_t g_num_ctrlrs[RTE_MAX_LCORE]; diff --git a/lib/vhost/vhost_rpc.c b/lib/vhost/vhost_rpc.c index 40002cc88..878e54cd2 100644 --- a/lib/vhost/vhost_rpc.c +++ b/lib/vhost/vhost_rpc.c @@ -37,8 +37,8 @@ #include "spdk/rpc.h" #include "spdk/util.h" +#include "spdk/scsi.h" #include "spdk/vhost.h" -#include "task.h" #include "vhost_internal.h" static void diff --git a/lib/vhost/vhost_scsi.c b/lib/vhost/vhost_scsi.c index dd7c4d9d1..18d73071e 100644 --- a/lib/vhost/vhost_scsi.c +++ b/lib/vhost/vhost_scsi.c @@ -44,7 +44,6 @@ #include "spdk/vhost.h" #include "vhost_internal.h" -#include "task.h" /* Features supported by SPDK VHOST lib. */ #define SPDK_VHOST_SCSI_FEATURES ((1ULL << VIRTIO_F_VERSION_1) | \ @@ -69,6 +68,11 @@ #define VIRTIO_SCSI_EVENTQ 1 #define VIRTIO_SCSI_REQUESTQ 2 +/* Allocated iovec buffer len */ +#define SPDK_VHOST_SCSI_IOVS_LEN 128 + +#define SPDK_VHOST_SCSI_TASK_POOL_SIZE 16384 + struct spdk_vhost_scsi_dev { struct spdk_vhost_dev vdev; @@ -79,6 +83,23 @@ struct spdk_vhost_scsi_dev { struct spdk_ring *eventq_ring; } __rte_cache_aligned; +struct spdk_vhost_task { + struct spdk_scsi_task scsi; + struct iovec iovs[SPDK_VHOST_SCSI_IOVS_LEN]; + + union { + struct virtio_scsi_cmd_resp *resp; + struct virtio_scsi_ctrl_tmf_resp *tmf_resp; + }; + + struct spdk_vhost_scsi_dev *svdev; + struct spdk_scsi_dev *scsi_dev; + + int req_idx; + + struct rte_vhost_vring *vq; +}; + static int new_device(int vid); static void destroy_device(int vid); @@ -91,6 +112,45 @@ const struct spdk_vhost_dev_backend spdk_vhost_scsi_device_backend = { } }; +static struct spdk_ring *g_task_pool; + +static void +spdk_vhost_task_put(struct spdk_vhost_task *task) +{ + spdk_scsi_task_put(&task->scsi); +} + +static void +spdk_vhost_task_free_cb(struct spdk_scsi_task *scsi_task) +{ + struct spdk_vhost_task *task = SPDK_CONTAINEROF(scsi_task, struct spdk_vhost_task, scsi); + + assert(task->svdev->vdev.task_cnt > 0); + task->svdev->vdev.task_cnt--; + spdk_ring_enqueue(g_task_pool, (void **) &task, 1); +} + +static void +spdk_vhost_get_tasks(struct spdk_vhost_scsi_dev *svdev, struct spdk_vhost_task **tasks, + size_t count, spdk_scsi_task_cpl cpl_fn) +{ + size_t res_count, i; + + res_count = spdk_ring_dequeue(g_task_pool, (void **)tasks, count); + if (res_count != count) { + SPDK_ERRLOG("%s: couldn't get %zu tasks from task_pool\n", svdev->vdev.name, count); + /* FIXME: we should never run out of tasks, but what if we do? */ + abort(); + } + + assert(svdev->vdev.task_cnt <= INT_MAX - (int) res_count); + svdev->vdev.task_cnt += res_count; + for (i = 0; i < res_count; ++i) { + memset(tasks[i], 0, sizeof(*tasks[i])); + spdk_scsi_task_construct(&tasks[i]->scsi, cpl_fn, spdk_vhost_task_free_cb, NULL); + } +} + static void process_eventq(struct spdk_vhost_scsi_dev *svdev) { @@ -180,18 +240,18 @@ submit_completion(struct spdk_vhost_task *task) spdk_vhost_task_put(task); } -void +static void spdk_vhost_task_mgmt_cpl(struct spdk_scsi_task *scsi_task) { - struct spdk_vhost_task *task = container_of(scsi_task, struct spdk_vhost_task, scsi); + struct spdk_vhost_task *task = SPDK_CONTAINEROF(scsi_task, struct spdk_vhost_task, scsi); submit_completion(task); } -void +static void spdk_vhost_task_cpl(struct spdk_scsi_task *scsi_task) { - struct spdk_vhost_task *task = container_of(scsi_task, struct spdk_vhost_task, scsi); + struct spdk_vhost_task *task = SPDK_CONTAINEROF(scsi_task, struct spdk_vhost_task, scsi); /* The SCSI task has completed. Do final processing and then post notification to the virtqueue's "used" ring. @@ -340,7 +400,7 @@ task_data_setup(struct spdk_vhost_task *task, struct spdk_vhost_dev *vdev = &task->svdev->vdev; struct vring_desc *desc = spdk_vhost_vq_get_desc(task->vq, task->req_idx); struct iovec *iovs = task->iovs; - uint16_t iovcnt = 0, iovcnt_max = VHOST_SCSI_IOVS_LEN; + uint16_t iovcnt = 0, iovcnt_max = SPDK_VHOST_SCSI_IOVS_LEN; uint32_t len = 0; /* Sanity check. First descriptor must be readable and must have next one. */ @@ -480,7 +540,7 @@ process_controlq(struct spdk_vhost_scsi_dev *svdev, struct rte_vhost_vring *vq) uint16_t reqs_cnt, i; reqs_cnt = spdk_vhost_vq_avail_ring_get(vq, reqs, RTE_DIM(reqs)); - spdk_vhost_task_get(svdev, (void **)tasks, reqs_cnt, spdk_vhost_task_mgmt_cpl); + spdk_vhost_get_tasks(svdev, tasks, reqs_cnt, spdk_vhost_task_mgmt_cpl); for (i = 0; i < reqs_cnt; i++) { task = tasks[i]; task->vq = vq; @@ -503,7 +563,7 @@ process_requestq(struct spdk_vhost_scsi_dev *svdev, struct rte_vhost_vring *vq) reqs_cnt = spdk_vhost_vq_avail_ring_get(vq, reqs, RTE_DIM(reqs)); assert(reqs_cnt <= 32); - spdk_vhost_task_get(svdev, (void **)tasks, reqs_cnt, spdk_vhost_task_cpl); + spdk_vhost_get_tasks(svdev, tasks, reqs_cnt, spdk_vhost_task_cpl); for (i = 0; i < reqs_cnt; i++) { SPDK_TRACELOG(SPDK_TRACE_VHOST_SCSI, "====== Starting processing request idx %"PRIu16"======\n", @@ -912,6 +972,44 @@ destroy_device(int vid) spdk_vhost_dev_unload(vdev); } +int +spdk_vhost_init(void) +{ + struct spdk_vhost_dev *task; + int rc, i; + + g_task_pool = spdk_ring_create(SPDK_RING_TYPE_MP_SC, SPDK_VHOST_SCSI_TASK_POOL_SIZE, SOCKET_ID_ANY); + if (g_task_pool == NULL) { + SPDK_ERRLOG("Failed to init vhost scsi task pool\n"); + return -1; + } + + for (i = 0; i < SPDK_VHOST_SCSI_TASK_POOL_SIZE - 1; ++i) { + task = spdk_dma_zmalloc(sizeof(*task), SPDK_CACHE_LINE_SIZE, NULL); + rc = spdk_ring_enqueue(g_task_pool, (void **)&task, 1); + if (rc != 1) { + SPDK_ERRLOG("Failed to alloc vhost scsi tasks\n"); + return -1; + } + } + + return 0; +} + +int +spdk_vhost_fini(void) +{ + struct spdk_vhost_dev *task; + + while (spdk_ring_dequeue(g_task_pool, (void **)&task, 1) == 1) { + spdk_dma_free(task); + } + + spdk_ring_free(g_task_pool); + + return 0; +} + SPDK_LOG_REGISTER_TRACE_FLAG("vhost_scsi", SPDK_TRACE_VHOST_SCSI) SPDK_LOG_REGISTER_TRACE_FLAG("vhost_scsi_queue", SPDK_TRACE_VHOST_SCSI_QUEUE) SPDK_LOG_REGISTER_TRACE_FLAG("vhost_scsi_data", SPDK_TRACE_VHOST_SCSI_DATA)