From d5106b6960e59604bff8641c9aedc4361a41aeae Mon Sep 17 00:00:00 2001 From: Ben Walker Date: Wed, 12 Jan 2022 13:27:10 -0700 Subject: [PATCH] examples/idxd: Correctly handle -EBUSY Change-Id: I6e794c2355c845959fccc4f04ba588b8162be9bc Signed-off-by: Ben Walker Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/11060 Tested-by: SPDK CI Jenkins Community-CI: Broadcom CI Reviewed-by: Jim Harris Reviewed-by: Dong Yi Reviewed-by: Changpeng Liu --- examples/idxd/perf/perf.c | 56 ++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/examples/idxd/perf/perf.c b/examples/idxd/perf/perf.c index 2d3464cdb..3bbc33f44 100644 --- a/examples/idxd/perf/perf.c +++ b/examples/idxd/perf/perf.c @@ -108,6 +108,7 @@ struct idxd_chan_entry { uint64_t injected_miscompares; uint64_t current_queue_depth; TAILQ_HEAD(, idxd_task) tasks_pool_head; + TAILQ_HEAD(, idxd_task) resubmits; unsigned core; bool is_draining; void *task_base; @@ -522,6 +523,11 @@ _submit_single(struct idxd_chan_entry *t, struct idxd_task *task) t->current_queue_depth++; + if (!TAILQ_EMPTY(&t->resubmits)) { + rc = -EBUSY; + goto queue; + } + switch (g_workload_selection) { case IDXD_COPY: siov.iov_base = task->src; @@ -571,8 +577,14 @@ _submit_single(struct idxd_chan_entry *t, struct idxd_task *task) } +queue: if (rc) { - idxd_done(task, rc); + /* Queue the task to be resubmitted on the next poll. */ + if (rc != -EBUSY && rc != -EAGAIN) { + t->xfer_failed++; + } + + TAILQ_INSERT_TAIL(&t->resubmits, task, link); } } @@ -742,6 +754,35 @@ submit_all(struct idxd_chan_entry *t) return 0; } +static int +idxd_chan_poll(struct idxd_chan_entry *chan) +{ + int rc; + struct idxd_task *task, *tmp; + TAILQ_HEAD(, idxd_task) swap; + + rc = spdk_idxd_process_events(chan->ch); + if (rc < 0) { + return rc; + } + + if (!TAILQ_EMPTY(&chan->resubmits)) { + TAILQ_INIT(&swap); + TAILQ_SWAP(&swap, &chan->resubmits, idxd_task, link); + TAILQ_FOREACH_SAFE(task, &swap, link, tmp) { + TAILQ_REMOVE(&swap, task, link); + chan->current_queue_depth--; + if (!chan->is_draining) { + _submit_single(chan, task); + } else { + TAILQ_INSERT_TAIL(&chan->tasks_pool_head, task, link); + } + } + } + + return rc; +} + static int work_fn(void *arg) { @@ -764,7 +805,7 @@ work_fn(void *arg) while (1) { t = worker->ctx; while (t != NULL) { - spdk_idxd_process_events(t->ch); + idxd_chan_poll(t); t = t->next; } @@ -818,7 +859,6 @@ get_next_idxd(void) static int init_idxd_chan_entry(struct idxd_chan_entry *t, struct spdk_idxd_device *idxd) { - int local_qd; int num_tasks = g_allocate_depth; struct idxd_task *task; int i; @@ -826,21 +866,13 @@ init_idxd_chan_entry(struct idxd_chan_entry *t, struct spdk_idxd_device *idxd) assert(t != NULL); TAILQ_INIT(&t->tasks_pool_head); + TAILQ_INIT(&t->resubmits); t->ch = spdk_idxd_get_channel(idxd); if (t->ch == NULL) { fprintf(stderr, "Failed to get channel\n"); goto err; } - local_qd = spdk_idxd_chan_get_max_operations(t->ch); - if (g_queue_depth > local_qd) { - fprintf(stdout, - "g_queue_depth is changed from %d to %d because of idxd (%p)'s max operations per chan=%d\n", - g_queue_depth, local_qd, idxd, local_qd); - g_queue_depth = local_qd; - } - - t->task_base = calloc(g_allocate_depth, sizeof(struct idxd_task)); if (t->task_base == NULL) { fprintf(stderr, "Could not allocate task base.\n");