Commit 0732c143 authored by Konrad Sztyber's avatar Konrad Sztyber
Browse files

accel/error: don't submit tasks intended to fail



There's no point in executing a task if it's going to be reported as
failed.  Instead, such tasks are kept on a list and are completed in
poller.

Signed-off-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Change-Id: Ifbd296d3524ce1c9ba112b4c7d8a383f52cc91cf
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/25284


Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Community-CI: Mellanox Build Bot
Community-CI: Community CI Samsung <spdk.community.ci.samsung@gmail.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarAleksey Marchuk <alexeymar@nvidia.com>
parent b53b961c
Loading
Loading
Loading
Loading
+65 −19
Original line number Diff line number Diff line
@@ -17,15 +17,21 @@ struct accel_error_inject_info {
	uint64_t			interval;
};

struct accel_error_task;

struct accel_error_channel {
	struct spdk_io_channel		*swch;
	struct spdk_poller		*poller;
	struct accel_error_inject_info	injects[SPDK_ACCEL_OPC_LAST];
	STAILQ_HEAD(, accel_error_task)	tasks;
};

struct accel_error_task {
	struct accel_error_channel	*ch;
	spdk_accel_completion_cb	cb_fn;
	void				*cb_arg;
	int				status;
	STAILQ_ENTRY(accel_error_task)	link;
};

static struct spdk_accel_module_if *g_sw_module;
@@ -38,6 +44,12 @@ accel_error_get_task_ctx(struct spdk_accel_task *task)
	return (void *)((uint8_t *)task + g_task_offset);
}

static struct spdk_accel_task *
accel_error_get_task_from_ctx(struct accel_error_task *errtask)
{
	return (void *)((uint8_t *)errtask - g_task_offset);
}

static void
accel_error_corrupt_task(struct spdk_accel_task *task)
{
@@ -51,26 +63,14 @@ accel_error_corrupt_task(struct spdk_accel_task *task)
}

static void
accel_error_task_complete_cb(void *arg, int status)
accel_error_corrupt_cb(void *arg, int status)
{
	struct spdk_accel_task *task = arg;
	struct accel_error_task *errtask = accel_error_get_task_ctx(task);
	struct accel_error_channel *ch = errtask->ch;
	struct accel_error_inject_info *info = &ch->injects[task->op_code];
	spdk_accel_completion_cb cb_fn = errtask->cb_fn;
	void *cb_arg = errtask->cb_arg;

	switch (info->opts.type) {
	case ACCEL_ERROR_INJECT_CORRUPT:
	accel_error_corrupt_task(task);
		break;
	case ACCEL_ERROR_INJECT_FAILURE:
		status = info->opts.errcode;
		break;
	default:
		break;
	}

	cb_fn(cb_arg, status);
}

@@ -106,20 +106,57 @@ accel_error_submit_tasks(struct spdk_io_channel *ch, struct spdk_accel_task *tas
{
	struct accel_error_channel *errch = spdk_io_channel_get_ctx(ch);
	struct accel_error_task *errtask = accel_error_get_task_ctx(task);
	struct accel_error_inject_info *info = &errch->injects[task->op_code];

	if (!accel_error_should_inject(ch, task)) {
		goto submit;
	}

	switch (info->opts.type) {
	case ACCEL_ERROR_INJECT_CORRUPT:
		errtask->ch = errch;
		errtask->cb_fn = task->cb_fn;
		errtask->cb_arg = task->cb_arg;
	task->cb_fn = accel_error_task_complete_cb;
		task->cb_fn = accel_error_corrupt_cb;
		task->cb_arg = task;
		break;
	case ACCEL_ERROR_INJECT_FAILURE:
		errtask->status = info->opts.errcode;
		STAILQ_INSERT_TAIL(&errch->tasks, errtask, link);
		return 0;
	default:
		break;
	}
submit:
	return g_sw_module->submit_tasks(errch->swch, task);
}

static int
accel_error_poller(void *arg)
{
	struct accel_error_channel *errch = arg;
	struct accel_error_task *errtask;
	STAILQ_HEAD(, accel_error_task) tasks;
	struct spdk_accel_task *task;

	if (STAILQ_EMPTY(&errch->tasks)) {
		return SPDK_POLLER_IDLE;
	}

	STAILQ_INIT(&tasks);
	STAILQ_SWAP(&tasks, &errch->tasks, accel_error_task);

	while (!STAILQ_EMPTY(&tasks)) {
		errtask = STAILQ_FIRST(&tasks);
		STAILQ_REMOVE_HEAD(&tasks, link);

		task = accel_error_get_task_from_ctx(errtask);
		spdk_accel_task_complete(task, errtask->status);
	}

	return SPDK_POLLER_BUSY;
}

static void
accel_error_inject_channel(struct spdk_io_channel_iter *iter)
{
@@ -164,8 +201,15 @@ accel_error_channel_create_cb(void *io_device, void *ctx)
	struct accel_error_channel *errch = ctx;
	size_t i;

	STAILQ_INIT(&errch->tasks);
	errch->poller = SPDK_POLLER_REGISTER(accel_error_poller, errch, 0);
	if (errch->poller == NULL) {
		return -ENOMEM;
	}

	errch->swch = g_sw_module->get_io_channel();
	if (errch->swch == NULL) {
		spdk_poller_unregister(&errch->poller);
		return -ENOMEM;
	}

@@ -182,6 +226,8 @@ accel_error_channel_destroy_cb(void *io_device, void *ctx)
{
	struct accel_error_channel *errch = ctx;

	assert(STAILQ_EMPTY(&errch->tasks));
	spdk_poller_unregister(&errch->poller);
	spdk_put_io_channel(errch->swch);
}