vhost_scsi: removed deferred tasks

Removed deferred tasks and dynamic memory management in task processing
in vhost_scsi. Each vhost task will now have it's own iovec array

Change-Id: Ie51a2404e9cd3c4e03bcea5a8d5b16498dd4d093
Signed-off-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/363342
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Pawel Wodkowski <pawelx.wodkowski@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Dariusz Stojaczyk 2017-06-01 15:15:54 +02:00 committed by Ben Walker
parent aff7e226f7
commit bfd1361714
3 changed files with 5 additions and 137 deletions

View File

@ -47,18 +47,11 @@
typeof(((type *)0)->member) *__mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); })
typedef TAILQ_HEAD(, spdk_vhost_task) need_iovecs_tailq_t;
static struct rte_mempool *g_task_pool;
static struct rte_mempool *g_iov_buffer_pool;
static need_iovecs_tailq_t g_need_iovecs[RTE_MAX_LCORE];
void
spdk_vhost_task_put(struct spdk_vhost_task *task)
{
assert(&task->scsi.iov == task->scsi.iovs);
assert(task->scsi.iovcnt == 1);
spdk_scsi_task_put(&task->scsi);
}
@ -91,44 +84,6 @@ spdk_vhost_task_get(struct spdk_vhost_scsi_dev *vdev)
return task;
}
void
spdk_vhost_enqueue_task(struct spdk_vhost_task *task)
{
need_iovecs_tailq_t *tailq = &g_need_iovecs[rte_lcore_id()];
TAILQ_INSERT_TAIL(tailq, task, iovecs_link);
}
struct spdk_vhost_task *
spdk_vhost_dequeue_task(void)
{
need_iovecs_tailq_t *tailq = &g_need_iovecs[rte_lcore_id()];
struct spdk_vhost_task *task;
if (TAILQ_EMPTY(tailq))
return NULL;
task = TAILQ_FIRST(tailq);
TAILQ_REMOVE(tailq, task, iovecs_link);
return task;
}
struct iovec *
spdk_vhost_iovec_alloc(void)
{
struct iovec *iov = NULL;
rte_mempool_get(g_iov_buffer_pool, (void **)&iov);
return iov;
}
void
spdk_vhost_iovec_free(struct iovec *iov)
{
rte_mempool_put(g_iov_buffer_pool, iov);
}
static void
spdk_vhost_subsystem_init(void)
{
@ -139,23 +94,8 @@ spdk_vhost_subsystem_init(void)
if (!g_task_pool) {
SPDK_ERRLOG("create task pool failed\n");
rc = -1;
goto end;
}
g_iov_buffer_pool = rte_mempool_create("vhost iov buffer pool", 2048,
VHOST_SCSI_IOVS_LEN * sizeof(struct iovec),
128, 0, NULL, NULL, NULL, NULL, SOCKET_ID_ANY, 0);
if (!g_iov_buffer_pool) {
SPDK_ERRLOG("create iov buffer pool failed\n");
rc = -1;
goto end;
}
for (int i = 0; i < RTE_MAX_LCORE; i++) {
TAILQ_INIT(&g_need_iovecs[i]);
}
end:
spdk_subsystem_init_next(rc);
}

View File

@ -43,6 +43,7 @@ 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;
@ -55,20 +56,12 @@ struct spdk_vhost_task {
int req_idx;
struct rte_vhost_vring *vq;
TAILQ_ENTRY(spdk_vhost_task) iovecs_link;
};
void spdk_vhost_enqueue_task(struct spdk_vhost_task *task);
struct spdk_vhost_task *spdk_vhost_dequeue_task(void);
void spdk_vhost_task_put(struct spdk_vhost_task *task);
struct spdk_vhost_task *spdk_vhost_task_get(struct spdk_vhost_scsi_dev *vdev);
void spdk_vhost_dev_task_ref(struct spdk_vhost_dev *vdev);
void spdk_vhost_dev_task_unref(struct spdk_vhost_dev *vdev);
void spdk_vhost_iovec_free(struct iovec *iov);
struct iovec *spdk_vhost_iovec_alloc(void);
#endif /* SPDK_VHOST_TASK_H */

View File

@ -99,46 +99,11 @@ static void invalid_request(struct spdk_vhost_task *task);
static void
submit_completion(struct spdk_vhost_task *task)
{
struct iovec *iovs = NULL;
int result;
spdk_vhost_vq_used_ring_enqueue(&task->svdev->vdev, task->vq, task->req_idx,
task->scsi.data_transferred);
SPDK_TRACELOG(SPDK_TRACE_VHOST, "Finished task (%p) req_idx=%d\n", task, task->req_idx);
if (task->scsi.iovs != &task->scsi.iov) {
iovs = task->scsi.iovs;
task->scsi.iovs = &task->scsi.iov;
task->scsi.iovcnt = 1;
}
spdk_vhost_task_put(task);
if (!iovs) {
return;
}
while (1) {
task = spdk_vhost_dequeue_task();
if (!task) {
spdk_vhost_iovec_free(iovs);
break;
}
/* Set iovs so underlying functions will not try to alloc IOV */
task->scsi.iovs = iovs;
task->scsi.iovcnt = VHOST_SCSI_IOVS_LEN;
result = process_request(task);
if (result == 0) {
task_submit(task);
break;
} else {
task->scsi.iovs = &task->scsi.iov;
task->scsi.iovcnt = 1;
invalid_request(task);
}
}
}
static void
@ -308,12 +273,10 @@ task_data_setup(struct spdk_vhost_task *task,
struct rte_vhost_vring *vq = task->vq;
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->scsi.iovs;
uint16_t iovcnt = 0, iovcnt_max = task->scsi.iovcnt;
struct iovec *iovs = task->iovs;
uint16_t iovcnt = 0, iovcnt_max = VHOST_SCSI_IOVS_LEN;
uint32_t len = 0;
assert(iovcnt_max == 1 || iovcnt_max == VHOST_SCSI_IOVS_LEN);
/* Sanity check. First descriptor must be readable and must have next one. */
if (unlikely(spdk_vhost_vring_desc_is_wr(desc) || !spdk_vhost_vring_desc_has_next(desc))) {
SPDK_WARNLOG("Invalid first (request) descriptor.\n");
@ -326,6 +289,7 @@ task_data_setup(struct spdk_vhost_task *task,
desc = spdk_vhost_vring_desc_get_next(vq->desc, desc);
task->scsi.dxfer_dir = spdk_vhost_vring_desc_is_wr(desc) ? SPDK_SCSI_DIR_FROM_DEV :
SPDK_SCSI_DIR_TO_DEV;
task->scsi.iovs = iovs;
if (task->scsi.dxfer_dir == SPDK_SCSI_DIR_FROM_DEV) {
/*
@ -347,14 +311,6 @@ task_data_setup(struct spdk_vhost_task *task,
}
desc = spdk_vhost_vring_desc_get_next(vq->desc, desc);
if (iovcnt_max != VHOST_SCSI_IOVS_LEN && spdk_vhost_vring_desc_has_next(desc)) {
iovs = spdk_vhost_iovec_alloc();
if (iovs == NULL) {
return 1;
}
iovcnt_max = VHOST_SCSI_IOVS_LEN;
}
/* All remaining descriptors are data. */
while (iovcnt < iovcnt_max) {
@ -379,19 +335,6 @@ task_data_setup(struct spdk_vhost_task *task,
* No need to check descriptor WR flag as this is done while setting scsi.dxfer_dir.
*/
if (iovcnt_max != VHOST_SCSI_IOVS_LEN && spdk_vhost_vring_desc_has_next(desc)) {
/* If next descriptor is not for response, allocate iovs. */
if (!spdk_vhost_vring_desc_is_wr(spdk_vhost_vring_desc_get_next(vq->desc, desc))) {
iovs = spdk_vhost_iovec_alloc();
if (iovs == NULL) {
return 1;
}
iovcnt_max = VHOST_SCSI_IOVS_LEN;
}
}
/* Process descriptors up to response. */
while (!spdk_vhost_vring_desc_is_wr(desc) && iovcnt < iovcnt_max) {
spdk_vhost_vring_desc_to_iov(vdev, &iovs[iovcnt], desc);
@ -413,22 +356,17 @@ task_data_setup(struct spdk_vhost_task *task,
}
}
if (iovcnt_max > 1 && iovcnt == iovcnt_max) {
if (iovcnt == iovcnt_max) {
SPDK_WARNLOG("Too many IO vectors in chain!\n");
goto abort_task;
}
task->scsi.iovs = iovs;
task->scsi.iovcnt = iovcnt;
task->scsi.length = len;
task->scsi.transfer_len = len;
return 0;
abort_task:
if (iovs != task->scsi.iovs) {
spdk_vhost_iovec_free(iovs);
}
if (task->resp) {
task->resp->response = VIRTIO_SCSI_S_ABORTED;
}
@ -496,9 +434,6 @@ process_requestq(struct spdk_vhost_scsi_dev *svdev, struct rte_vhost_vring *vq)
task_submit(task);
SPDK_TRACELOG(SPDK_TRACE_VHOST, "====== Task %p req_idx %d submitted ======\n", task,
task->req_idx);
} else if (result > 0) {
spdk_vhost_enqueue_task(task);
SPDK_TRACELOG(SPDK_TRACE_VHOST, "====== Task %p req_idx %d deferred ======\n", task, task->req_idx);
} else {
invalid_request(task);
SPDK_TRACELOG(SPDK_TRACE_VHOST, "====== Task %p req_idx %d failed ======\n", task, task->req_idx);