accel: use iovecs for copy operations

This patch is first in the series of patches aimed to make all accel
operations describe their buffers with iovecs.  The intention is to make
it easier to handle tasks in a generic way.

It doesn't mean that we change the API - all function signatures are
preserved.  If a function doesn't use iovecs, we use the aux_iovs array.
However, this does mean that each accel module that provides support for
a given operation will need to be adjusted to use iovecs.

Additionally, update the unit test checking copy elision to verify the
buffers of the copy operation that is left.

Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com>
Change-Id: I9e6d8d1be3b8b9706cb4a6222dad30e8c373d8fb
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/15937
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
This commit is contained in:
Konrad Sztyber 2022-12-09 13:59:50 +01:00 committed by Tomasz Zawadzki
parent 58b12fc4b9
commit dee8e1f4c0
6 changed files with 66 additions and 44 deletions

View File

@ -32,6 +32,14 @@ struct spdk_accel_crypto_key {
TAILQ_ENTRY(spdk_accel_crypto_key) link;
};
enum spdk_accel_aux_iov_type {
SPDK_ACCEL_AUX_IOV_SRC,
SPDK_ACCEL_AUX_IOV_DST,
SPDK_ACCEL_AUX_IOV_SRC2,
SPDK_ACCEL_AUX_IOV_DST2,
SPDK_ACCEL_AUX_IOV_MAX,
};
struct spdk_accel_task {
struct accel_io_channel *accel_ch;
spdk_accel_completion_cb cb_fn;
@ -76,6 +84,7 @@ struct spdk_accel_task {
};
int flags;
int status;
struct iovec aux_iovs[SPDK_ACCEL_AUX_IOV_MAX];
TAILQ_ENTRY(spdk_accel_task) link;
TAILQ_ENTRY(spdk_accel_task) seq_link;
};

View File

@ -215,10 +215,15 @@ spdk_accel_submit_copy(struct spdk_io_channel *ch, void *dst, void *src,
return -ENOMEM;
}
accel_task->dst = dst;
accel_task->src = src;
accel_task->s.iovs = &accel_task->aux_iovs[SPDK_ACCEL_AUX_IOV_SRC];
accel_task->d.iovs = &accel_task->aux_iovs[SPDK_ACCEL_AUX_IOV_DST];
accel_task->d.iovs[0].iov_base = dst;
accel_task->d.iovs[0].iov_len = nbytes;
accel_task->d.iovcnt = 1;
accel_task->s.iovs[0].iov_base = src;
accel_task->s.iovs[0].iov_len = nbytes;
accel_task->s.iovcnt = 1;
accel_task->op_code = ACCEL_OPC_COPY;
accel_task->nbytes = nbytes;
accel_task->flags = flags;
accel_task->src_domain = NULL;
accel_task->dst_domain = NULL;
@ -978,6 +983,7 @@ accel_sequence_set_virtbuf(struct spdk_accel_sequence *seq, struct accel_buffer
TAILQ_FOREACH(task, &seq->tasks, seq_link) {
switch (task->op_code) {
case ACCEL_OPC_DECOMPRESS:
case ACCEL_OPC_COPY:
if (task->src_domain == g_accel_domain && task->src_domain_ctx == buf) {
accel_update_iovs(task->s.iovs, task->s.iovcnt, buf);
task->src_domain = NULL;
@ -987,17 +993,6 @@ accel_sequence_set_virtbuf(struct spdk_accel_sequence *seq, struct accel_buffer
task->dst_domain = NULL;
}
break;
case ACCEL_OPC_COPY:
/* By the time we're here, we've already changed iovecs -> buf */
if (task->src_domain == g_accel_domain && task->src_domain_ctx == buf) {
accel_update_buf(&task->src, buf);
task->src_domain = NULL;
}
if (task->dst_domain == g_accel_domain && task->dst_domain_ctx == buf) {
accel_update_buf(&task->dst, buf);
task->dst_domain = NULL;
}
break;
case ACCEL_OPC_FILL:
/* Fill should have src_domain cleared */
assert(task->src_domain == NULL);
@ -1223,25 +1218,6 @@ spdk_accel_sequence_finish(struct spdk_accel_sequence *seq,
accel_sequence_merge_tasks(seq, task, &next);
}
/* Since we store copy operations' buffers as iovecs, we need to convert them to scalar
* buffers, as that's what accel modules expect
*/
TAILQ_FOREACH(task, &seq->tasks, seq_link) {
if (task->op_code != ACCEL_OPC_COPY) {
continue;
}
if (spdk_unlikely(task->s.iovcnt != 1 || task->d.iovcnt != 1)) {
SPDK_ERRLOG("Unable to set buffer of a copy operation due "
"to iovcnt!=1\n");
return -EINVAL;
}
task->nbytes = spdk_min(task->s.iovs[0].iov_len,
task->d.iovs[0].iov_len);
task->src = task->s.iovs[0].iov_base;
task->dst = task->d.iovs[0].iov_base;
}
seq->cb_fn = cb_fn;
seq->cb_arg = cb_arg;

View File

@ -141,6 +141,23 @@ _sw_accel_copy(void *dst, void *src, size_t nbytes, int flags)
}
}
static int
_sw_accel_copy_iovs(struct iovec *dst_iovs, uint32_t dst_iovcnt,
struct iovec *src_iovs, uint32_t src_iovcnt, int flags)
{
if (spdk_unlikely(dst_iovcnt != 1 || src_iovcnt != 1)) {
return -EINVAL;
}
if (spdk_unlikely(dst_iovs[0].iov_len != src_iovs[0].iov_len)) {
return -EINVAL;
}
_sw_accel_copy(dst_iovs[0].iov_base, src_iovs[0].iov_base, dst_iovs[0].iov_len, flags);
return 0;
}
static void
_sw_accel_copyv(void *dst, struct iovec *iov, uint32_t iovcnt, int flags)
{
@ -462,7 +479,9 @@ sw_accel_submit_tasks(struct spdk_io_channel *ch, struct spdk_accel_task *accel_
case ACCEL_OPC_COPY:
rc = _check_flags(accel_task->flags);
if (rc == 0) {
_sw_accel_copy(accel_task->dst, accel_task->src, accel_task->nbytes, accel_task->flags);
rc = _sw_accel_copy_iovs(accel_task->d.iovs, accel_task->d.iovcnt,
accel_task->s.iovs, accel_task->s.iovcnt,
accel_task->flags);
}
break;
case ACCEL_OPC_FILL:

View File

@ -135,15 +135,12 @@ _process_single_task(struct spdk_io_channel *ch, struct spdk_accel_task *task)
switch (task->op_code) {
case ACCEL_OPC_COPY:
siov.iov_base = task->src;
siov.iov_len = task->nbytes;
diov.iov_base = task->dst;
diov.iov_len = task->nbytes;
if (task->flags & ACCEL_FLAG_PERSISTENT) {
flags |= SPDK_IDXD_FLAG_PERSISTENT;
flags |= SPDK_IDXD_FLAG_NONTEMPORAL;
}
rc = spdk_idxd_submit_copy(chan->chan, &diov, 1, &siov, 1, flags, dsa_done, idxd_task);
rc = spdk_idxd_submit_copy(chan->chan, task->d.iovs, task->d.iovcnt,
task->s.iovs, task->s.iovcnt, flags, dsa_done, idxd_task);
break;
case ACCEL_OPC_DUALCAST:
if (task->flags & ACCEL_FLAG_PERSISTENT) {

View File

@ -9,6 +9,7 @@
#include "spdk_internal/accel_module.h"
#include "spdk/log.h"
#include "spdk/likely.h"
#include "spdk/env.h"
#include "spdk/event.h"
@ -128,6 +129,22 @@ ioat_supports_opcode(enum accel_opcode opc)
}
static int
ioat_submit_copy(struct ioat_io_channel *ioat_ch, struct spdk_accel_task *task)
{
if (spdk_unlikely(task->d.iovcnt != 1 || task->s.iovcnt != 1)) {
return -EINVAL;
}
if (spdk_unlikely(task->d.iovs[0].iov_len != task->s.iovs[0].iov_len)) {
return -EINVAL;
}
return spdk_ioat_build_copy(ioat_ch->ioat_ch, task, ioat_done,
task->d.iovs[0].iov_base, task->s.iovs[0].iov_base,
task->d.iovs[0].iov_len);
}
static int
ioat_submit_tasks(struct spdk_io_channel *ch, struct spdk_accel_task *accel_task)
{
@ -147,8 +164,7 @@ ioat_submit_tasks(struct spdk_io_channel *ch, struct spdk_accel_task *accel_task
accel_task->dst, accel_task->fill_pattern, accel_task->nbytes);
break;
case ACCEL_OPC_COPY:
rc = spdk_ioat_build_copy(ioat_ch->ioat_ch, accel_task, ioat_done,
accel_task->dst, accel_task->src, accel_task->nbytes);
rc = ioat_submit_copy(ioat_ch, accel_task);
break;
default:
assert(false);

View File

@ -187,10 +187,7 @@ test_spdk_accel_submit_copy(void)
/* submission OK. */
rc = spdk_accel_submit_copy(g_ch, dst, src, nbytes, flags, NULL, cb_arg);
CU_ASSERT(rc == 0);
CU_ASSERT(task.dst == dst);
CU_ASSERT(task.src == src);
CU_ASSERT(task.op_code == ACCEL_OPC_COPY);
CU_ASSERT(task.nbytes == nbytes);
CU_ASSERT(task.flags == 0);
CU_ASSERT(memcmp(dst, src, TEST_SUBMIT_SIZE) == 0);
expected_accel_task = TAILQ_FIRST(&g_sw_ch->tasks_to_complete);
@ -1636,6 +1633,14 @@ test_sequence_copy_elision(void)
seq = NULL;
completed = 0;
g_seq_operations[ACCEL_OPC_COPY].count = 0;
g_seq_operations[ACCEL_OPC_COPY].dst_iovcnt = 1;
g_seq_operations[ACCEL_OPC_COPY].src_iovcnt = 1;
g_seq_operations[ACCEL_OPC_COPY].src_iovs = &exp_iovs[0];
g_seq_operations[ACCEL_OPC_COPY].dst_iovs = &exp_iovs[1];
exp_iovs[0].iov_base = tmp[0];
exp_iovs[0].iov_len = sizeof(tmp[0]);
exp_iovs[1].iov_base = buf;
exp_iovs[1].iov_len = sizeof(buf);
dst_iovs[0].iov_base = tmp[1];
dst_iovs[0].iov_len = sizeof(tmp[1]);