Commit bfd13617 authored by Dariusz Stojaczyk's avatar Dariusz Stojaczyk Committed by Ben Walker
Browse files

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: default avatarDariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/363342


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarPawel Wodkowski <pawelx.wodkowski@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
parent aff7e226
Loading
Loading
Loading
Loading
+0 −60
Original line number Diff line number Diff line
@@ -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);
}

+1 −8
Original line number Diff line number Diff line
@@ -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 */
+4 −69
Original line number Diff line number Diff line
@@ -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);