Commit 2d30d9f8 authored by Jacek Kalwas's avatar Jacek Kalwas Committed by Tomasz Zawadzki
Browse files

accel: introduce tasks in sequence limit



Sequence cannot be allocated if number of available task objects cannot
satisfy required limit. This is to prevent potential dead lock when few
requests are pending task resource and none can advance the processing.
This solution should work only if there is single async operation after
sequence obj obtained, so assume that is possible to happen with io
buffer allocation now. If there are more async operations then solution
should be improved.

Change-Id: I45165dd96539b00849dc67d5bd1bfea206ca5ed2
Signed-off-by: default avatarJacek Kalwas <jacek.kalwas@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/24040


Community-CI: Mellanox Build Bot
Reviewed-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
parent 2728651e
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#define ACCEL_BUFFER_OFFSET_MASK	((uintptr_t)ACCEL_BUFFER_BASE - 1)

#define ACCEL_CRYPTO_TWEAK_MODE_DEFAULT	SPDK_ACCEL_CRYPTO_TWEAK_MODE_SIMPLE_LBA
#define ACCEL_TASKS_IN_SEQUENCE_LIMIT	8

struct accel_module {
	struct spdk_accel_module_if	*module;
@@ -283,6 +284,7 @@ _get_task(struct accel_io_channel *accel_ch, spdk_accel_completion_cb cb_fn, voi
		return NULL;
	}

	accel_update_stats(accel_ch, task_outstanding, 1);
	STAILQ_REMOVE_HEAD(&accel_ch->task_pool, link);
	accel_task->link.stqe_next = NULL;

@@ -299,6 +301,7 @@ static void
_put_task(struct accel_io_channel *ch, struct spdk_accel_task *task)
{
	STAILQ_INSERT_HEAD(&ch->task_pool, task, link);
	accel_update_stats(ch, task_outstanding, -1);
}

void
@@ -960,6 +963,17 @@ accel_sequence_get(struct accel_io_channel *ch)
{
	struct spdk_accel_sequence *seq;

	assert(g_opts.task_count >= ch->stats.task_outstanding);

	/* Sequence cannot be allocated if number of available task objects cannot satisfy required limit.
	 * This is to prevent potential dead lock when few requests are pending task resource and none can
	 * advance the processing. This solution should work only if there is single async operation after
	 * sequence obj obtained, so assume that is possible to happen with io buffer allocation now, if
	 * there are more async operations then solution should be improved. */
	if (spdk_unlikely(g_opts.task_count - ch->stats.task_outstanding < ACCEL_TASKS_IN_SEQUENCE_LIMIT)) {
		return NULL;
	}

	seq = SLIST_FIRST(&ch->seq_pool);
	if (spdk_unlikely(seq == NULL)) {
		accel_update_stats(ch, retry.sequence, 1);
@@ -2635,6 +2649,7 @@ accel_add_stats(struct accel_stats *total, struct accel_stats *stats)
	total->sequence_executed += stats->sequence_executed;
	total->sequence_failed += stats->sequence_failed;
	total->sequence_outstanding += stats->sequence_outstanding;
	total->task_outstanding += stats->task_outstanding;
	total->retry.task += stats->retry.task;
	total->retry.sequence += stats->retry.sequence;
	total->retry.iobuf += stats->retry.iobuf;
@@ -3110,6 +3125,11 @@ spdk_accel_set_opts(const struct spdk_accel_opts *opts)
		return -1;
	}

	if (SPDK_GET_FIELD(opts, task_count, g_opts.task_count,
			   opts->opts_size) < ACCEL_TASKS_IN_SEQUENCE_LIMIT) {
		return -EINVAL;
	}

#define SET_FIELD(field) \
        if (offsetof(struct spdk_accel_opts, field) + sizeof(opts->field) <= opts->opts_size) { \
                g_opts.field = opts->field; \
+1 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ struct accel_stats {
	uint64_t			sequence_executed;
	uint64_t			sequence_failed;
	uint32_t			sequence_outstanding;
	uint32_t			task_outstanding;

	struct {
		uint64_t task;
+1 −0
Original line number Diff line number Diff line
@@ -424,6 +424,7 @@ rpc_accel_get_stats_done(struct accel_stats *stats, void *cb_arg)
	spdk_json_write_named_uint64(w, "sequence_executed", stats->sequence_executed);
	spdk_json_write_named_uint64(w, "sequence_failed", stats->sequence_failed);
	spdk_json_write_named_uint64(w, "sequence_outstanding", stats->sequence_outstanding);
	spdk_json_write_named_uint64(w, "task_outstanding", stats->task_outstanding);
	spdk_json_write_named_array_begin(w, "operations");
	for (i = 0; i < SPDK_ACCEL_OPC_LAST; ++i) {
		if (stats->operations[i].executed + stats->operations[i].failed == 0) {