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:
parent
aff7e226f7
commit
bfd1361714
@ -47,18 +47,11 @@
|
|||||||
typeof(((type *)0)->member) *__mptr = (ptr); \
|
typeof(((type *)0)->member) *__mptr = (ptr); \
|
||||||
(type *)((char *)__mptr - offsetof(type, member)); })
|
(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_task_pool;
|
||||||
static struct rte_mempool *g_iov_buffer_pool;
|
|
||||||
|
|
||||||
static need_iovecs_tailq_t g_need_iovecs[RTE_MAX_LCORE];
|
|
||||||
|
|
||||||
void
|
void
|
||||||
spdk_vhost_task_put(struct spdk_vhost_task *task)
|
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);
|
spdk_scsi_task_put(&task->scsi);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,44 +84,6 @@ spdk_vhost_task_get(struct spdk_vhost_scsi_dev *vdev)
|
|||||||
return task;
|
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
|
static void
|
||||||
spdk_vhost_subsystem_init(void)
|
spdk_vhost_subsystem_init(void)
|
||||||
{
|
{
|
||||||
@ -139,23 +94,8 @@ spdk_vhost_subsystem_init(void)
|
|||||||
if (!g_task_pool) {
|
if (!g_task_pool) {
|
||||||
SPDK_ERRLOG("create task pool failed\n");
|
SPDK_ERRLOG("create task pool failed\n");
|
||||||
rc = -1;
|
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);
|
spdk_subsystem_init_next(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ struct spdk_vhost_dev;
|
|||||||
|
|
||||||
struct spdk_vhost_task {
|
struct spdk_vhost_task {
|
||||||
struct spdk_scsi_task scsi;
|
struct spdk_scsi_task scsi;
|
||||||
|
struct iovec iovs[VHOST_SCSI_IOVS_LEN];
|
||||||
|
|
||||||
union {
|
union {
|
||||||
struct virtio_scsi_cmd_resp *resp;
|
struct virtio_scsi_cmd_resp *resp;
|
||||||
@ -55,20 +56,12 @@ struct spdk_vhost_task {
|
|||||||
int req_idx;
|
int req_idx;
|
||||||
|
|
||||||
struct rte_vhost_vring *vq;
|
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);
|
void spdk_vhost_task_put(struct spdk_vhost_task *task);
|
||||||
struct spdk_vhost_task *spdk_vhost_task_get(struct spdk_vhost_scsi_dev *vdev);
|
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_ref(struct spdk_vhost_dev *vdev);
|
||||||
void spdk_vhost_dev_task_unref(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 */
|
#endif /* SPDK_VHOST_TASK_H */
|
||||||
|
@ -99,46 +99,11 @@ static void invalid_request(struct spdk_vhost_task *task);
|
|||||||
static void
|
static void
|
||||||
submit_completion(struct spdk_vhost_task *task)
|
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,
|
spdk_vhost_vq_used_ring_enqueue(&task->svdev->vdev, task->vq, task->req_idx,
|
||||||
task->scsi.data_transferred);
|
task->scsi.data_transferred);
|
||||||
SPDK_TRACELOG(SPDK_TRACE_VHOST, "Finished task (%p) req_idx=%d\n", task, task->req_idx);
|
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);
|
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
|
static void
|
||||||
@ -308,12 +273,10 @@ task_data_setup(struct spdk_vhost_task *task,
|
|||||||
struct rte_vhost_vring *vq = task->vq;
|
struct rte_vhost_vring *vq = task->vq;
|
||||||
struct spdk_vhost_dev *vdev = &task->svdev->vdev;
|
struct spdk_vhost_dev *vdev = &task->svdev->vdev;
|
||||||
struct vring_desc *desc = spdk_vhost_vq_get_desc(task->vq, task->req_idx);
|
struct vring_desc *desc = spdk_vhost_vq_get_desc(task->vq, task->req_idx);
|
||||||
struct iovec *iovs = task->scsi.iovs;
|
struct iovec *iovs = task->iovs;
|
||||||
uint16_t iovcnt = 0, iovcnt_max = task->scsi.iovcnt;
|
uint16_t iovcnt = 0, iovcnt_max = VHOST_SCSI_IOVS_LEN;
|
||||||
uint32_t len = 0;
|
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. */
|
/* 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))) {
|
if (unlikely(spdk_vhost_vring_desc_is_wr(desc) || !spdk_vhost_vring_desc_has_next(desc))) {
|
||||||
SPDK_WARNLOG("Invalid first (request) descriptor.\n");
|
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);
|
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 :
|
task->scsi.dxfer_dir = spdk_vhost_vring_desc_is_wr(desc) ? SPDK_SCSI_DIR_FROM_DEV :
|
||||||
SPDK_SCSI_DIR_TO_DEV;
|
SPDK_SCSI_DIR_TO_DEV;
|
||||||
|
task->scsi.iovs = iovs;
|
||||||
|
|
||||||
if (task->scsi.dxfer_dir == SPDK_SCSI_DIR_FROM_DEV) {
|
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);
|
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. */
|
/* All remaining descriptors are data. */
|
||||||
while (iovcnt < iovcnt_max) {
|
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.
|
* 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. */
|
/* Process descriptors up to response. */
|
||||||
while (!spdk_vhost_vring_desc_is_wr(desc) && iovcnt < iovcnt_max) {
|
while (!spdk_vhost_vring_desc_is_wr(desc) && iovcnt < iovcnt_max) {
|
||||||
spdk_vhost_vring_desc_to_iov(vdev, &iovs[iovcnt], desc);
|
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");
|
SPDK_WARNLOG("Too many IO vectors in chain!\n");
|
||||||
goto abort_task;
|
goto abort_task;
|
||||||
}
|
}
|
||||||
|
|
||||||
task->scsi.iovs = iovs;
|
|
||||||
task->scsi.iovcnt = iovcnt;
|
task->scsi.iovcnt = iovcnt;
|
||||||
task->scsi.length = len;
|
task->scsi.length = len;
|
||||||
task->scsi.transfer_len = len;
|
task->scsi.transfer_len = len;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
abort_task:
|
abort_task:
|
||||||
if (iovs != task->scsi.iovs) {
|
|
||||||
spdk_vhost_iovec_free(iovs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (task->resp) {
|
if (task->resp) {
|
||||||
task->resp->response = VIRTIO_SCSI_S_ABORTED;
|
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);
|
task_submit(task);
|
||||||
SPDK_TRACELOG(SPDK_TRACE_VHOST, "====== Task %p req_idx %d submitted ======\n", task,
|
SPDK_TRACELOG(SPDK_TRACE_VHOST, "====== Task %p req_idx %d submitted ======\n", task,
|
||||||
task->req_idx);
|
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 {
|
} else {
|
||||||
invalid_request(task);
|
invalid_request(task);
|
||||||
SPDK_TRACELOG(SPDK_TRACE_VHOST, "====== Task %p req_idx %d failed ======\n", task, task->req_idx);
|
SPDK_TRACELOG(SPDK_TRACE_VHOST, "====== Task %p req_idx %d failed ======\n", task, task->req_idx);
|
||||||
|
Loading…
Reference in New Issue
Block a user