accel: add support for reversing a sequence
Reversing a sequence means that the order of its operations is reversed, i.e. the first operation becomes last and vice versa. It's especially useful in read paths, as it makes it possible to build the sequence during submission, then, once the data is read from storage, reverse the sequence and execute it. Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com> Change-Id: I93d617c1e6d251f8c59b94c50dc4300e51908096 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/15636 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
This commit is contained in:
parent
f778e8e53a
commit
7b36fe5238
@ -929,7 +929,17 @@ spdk_accel_sequence_finish(struct spdk_accel_sequence *seq,
|
||||
void
|
||||
spdk_accel_sequence_reverse(struct spdk_accel_sequence *seq)
|
||||
{
|
||||
assert(0 && "unsupported");
|
||||
struct accel_sequence_tasks tasks = TAILQ_HEAD_INITIALIZER(tasks);
|
||||
struct spdk_accel_task *task;
|
||||
|
||||
assert(TAILQ_EMPTY(&seq->completed));
|
||||
TAILQ_SWAP(&tasks, &seq->tasks, spdk_accel_task, seq_link);
|
||||
|
||||
while (!TAILQ_EMPTY(&tasks)) {
|
||||
task = TAILQ_FIRST(&tasks);
|
||||
TAILQ_REMOVE(&tasks, task, seq_link);
|
||||
TAILQ_INSERT_HEAD(&seq->tasks, task, seq_link);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1207,6 +1207,188 @@ test_sequence_decompress(void)
|
||||
spdk_put_io_channel(ioch);
|
||||
poll_threads();
|
||||
}
|
||||
|
||||
static void
|
||||
test_sequence_reverse(void)
|
||||
{
|
||||
struct spdk_accel_sequence *seq = NULL;
|
||||
struct spdk_io_channel *ioch;
|
||||
struct ut_sequence ut_seq;
|
||||
char buf[4096], tmp[2][4096], expected[4096];
|
||||
struct iovec src_iovs[2], dst_iovs[2];
|
||||
uint32_t compressed_size;
|
||||
int rc, completed = 0;
|
||||
|
||||
ioch = spdk_accel_get_io_channel();
|
||||
SPDK_CU_ASSERT_FATAL(ioch != NULL);
|
||||
|
||||
memset(expected, 0xa5, sizeof(expected));
|
||||
src_iovs[0].iov_base = expected;
|
||||
src_iovs[0].iov_len = sizeof(expected);
|
||||
rc = spdk_accel_submit_compress(ioch, tmp[0], sizeof(tmp[0]), &src_iovs[0], 1,
|
||||
&compressed_size, 0, ut_compress_cb, &completed);
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
|
||||
while (!completed) {
|
||||
poll_threads();
|
||||
}
|
||||
|
||||
/* First check that reversing a sequnce with a single operation is a no-op */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
seq = NULL;
|
||||
completed = 0;
|
||||
|
||||
dst_iovs[0].iov_base = buf;
|
||||
dst_iovs[0].iov_len = sizeof(buf);
|
||||
src_iovs[0].iov_base = tmp[0];
|
||||
src_iovs[0].iov_len = compressed_size;
|
||||
rc = spdk_accel_append_decompress(&seq, ioch, &dst_iovs[0], 1, NULL, NULL,
|
||||
&src_iovs[0], 1, NULL, NULL, 0,
|
||||
ut_sequence_step_cb, &completed);
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
|
||||
spdk_accel_sequence_reverse(seq);
|
||||
|
||||
ut_seq.complete = false;
|
||||
rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq);
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
|
||||
poll_threads();
|
||||
|
||||
CU_ASSERT_EQUAL(completed, 1);
|
||||
CU_ASSERT(ut_seq.complete);
|
||||
CU_ASSERT_EQUAL(ut_seq.status, 0);
|
||||
CU_ASSERT_EQUAL(memcmp(buf, expected, sizeof(buf)), 0);
|
||||
|
||||
/* Add a copy operation at the end with src set to the compressed data. After reverse(),
|
||||
* that copy operation should be first, so decompress() should receive compressed data in
|
||||
* its src buffer.
|
||||
*/
|
||||
memset(buf, 0, sizeof(buf));
|
||||
memset(tmp[1], 0, sizeof(tmp[1]));
|
||||
seq = NULL;
|
||||
completed = 0;
|
||||
|
||||
dst_iovs[0].iov_base = buf;
|
||||
dst_iovs[0].iov_len = sizeof(buf);
|
||||
src_iovs[0].iov_base = tmp[1];
|
||||
src_iovs[0].iov_len = compressed_size;
|
||||
rc = spdk_accel_append_decompress(&seq, ioch, &dst_iovs[0], 1, NULL, NULL,
|
||||
&src_iovs[0], 1, NULL, NULL, 0,
|
||||
ut_sequence_step_cb, &completed);
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
|
||||
dst_iovs[1].iov_base = tmp[1];
|
||||
dst_iovs[1].iov_len = compressed_size;
|
||||
src_iovs[1].iov_base = tmp[0];
|
||||
src_iovs[1].iov_len = compressed_size;
|
||||
rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[1], 1, NULL, NULL,
|
||||
&src_iovs[1], 1, NULL, NULL, 0,
|
||||
ut_sequence_step_cb, &completed);
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
|
||||
spdk_accel_sequence_reverse(seq);
|
||||
|
||||
ut_seq.complete = false;
|
||||
rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq);
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
|
||||
poll_threads();
|
||||
|
||||
CU_ASSERT_EQUAL(completed, 2);
|
||||
CU_ASSERT(ut_seq.complete);
|
||||
CU_ASSERT_EQUAL(ut_seq.status, 0);
|
||||
CU_ASSERT_EQUAL(memcmp(buf, expected, sizeof(buf)), 0);
|
||||
|
||||
/* Check the same, but add an extra fill operation at the beginning that should execute last
|
||||
* after reverse().
|
||||
*/
|
||||
memset(buf, 0, sizeof(buf));
|
||||
memset(tmp[1], 0, sizeof(tmp[1]));
|
||||
memset(expected, 0xfe, 2048);
|
||||
seq = NULL;
|
||||
completed = 0;
|
||||
|
||||
rc = spdk_accel_append_fill(&seq, ioch, buf, 2048, NULL, NULL, 0xfe, 0,
|
||||
ut_sequence_step_cb, &completed);
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
|
||||
dst_iovs[0].iov_base = buf;
|
||||
dst_iovs[0].iov_len = sizeof(buf);
|
||||
src_iovs[0].iov_base = tmp[1];
|
||||
src_iovs[0].iov_len = compressed_size;
|
||||
rc = spdk_accel_append_decompress(&seq, ioch, &dst_iovs[0], 1, NULL, NULL,
|
||||
&src_iovs[0], 1, NULL, NULL, 0,
|
||||
ut_sequence_step_cb, &completed);
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
|
||||
dst_iovs[1].iov_base = tmp[1];
|
||||
dst_iovs[1].iov_len = compressed_size;
|
||||
src_iovs[1].iov_base = tmp[0];
|
||||
src_iovs[1].iov_len = compressed_size;
|
||||
rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[1], 1, NULL, NULL,
|
||||
&src_iovs[1], 1, NULL, NULL, 0,
|
||||
ut_sequence_step_cb, &completed);
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
|
||||
spdk_accel_sequence_reverse(seq);
|
||||
|
||||
ut_seq.complete = false;
|
||||
rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq);
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
|
||||
poll_threads();
|
||||
|
||||
CU_ASSERT_EQUAL(completed, 3);
|
||||
CU_ASSERT(ut_seq.complete);
|
||||
CU_ASSERT_EQUAL(ut_seq.status, 0);
|
||||
CU_ASSERT_EQUAL(memcmp(buf, expected, sizeof(buf)), 0);
|
||||
|
||||
/* Build the sequence in order and then reverse it twice */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
memset(tmp[1], 0, sizeof(tmp[1]));
|
||||
seq = NULL;
|
||||
completed = 0;
|
||||
|
||||
dst_iovs[0].iov_base = tmp[1];
|
||||
dst_iovs[0].iov_len = compressed_size;
|
||||
src_iovs[0].iov_base = tmp[0];
|
||||
src_iovs[0].iov_len = compressed_size;
|
||||
rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[0], 1, NULL, NULL,
|
||||
&src_iovs[0], 1, NULL, NULL, 0,
|
||||
ut_sequence_step_cb, &completed);
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
|
||||
dst_iovs[1].iov_base = buf;
|
||||
dst_iovs[1].iov_len = sizeof(buf);
|
||||
src_iovs[1].iov_base = tmp[1];
|
||||
src_iovs[1].iov_len = compressed_size;
|
||||
rc = spdk_accel_append_decompress(&seq, ioch, &dst_iovs[1], 1, NULL, NULL,
|
||||
&src_iovs[1], 1, NULL, NULL, 0,
|
||||
ut_sequence_step_cb, &completed);
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
|
||||
rc = spdk_accel_append_fill(&seq, ioch, buf, 2048, NULL, NULL, 0xfe, 0,
|
||||
ut_sequence_step_cb, &completed);
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
|
||||
spdk_accel_sequence_reverse(seq);
|
||||
spdk_accel_sequence_reverse(seq);
|
||||
|
||||
ut_seq.complete = false;
|
||||
rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq);
|
||||
CU_ASSERT_EQUAL(rc, 0);
|
||||
|
||||
poll_threads();
|
||||
|
||||
CU_ASSERT_EQUAL(completed, 3);
|
||||
CU_ASSERT(ut_seq.complete);
|
||||
CU_ASSERT_EQUAL(ut_seq.status, 0);
|
||||
CU_ASSERT_EQUAL(memcmp(buf, expected, sizeof(buf)), 0);
|
||||
|
||||
spdk_put_io_channel(ioch);
|
||||
poll_threads();
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
@ -1535,6 +1717,7 @@ main(int argc, char **argv)
|
||||
CU_ADD_TEST(seq_suite, test_sequence_completion_error);
|
||||
#ifdef SPDK_CONFIG_ISAL /* accel_sw requires isa-l for compression */
|
||||
CU_ADD_TEST(seq_suite, test_sequence_decompress);
|
||||
CU_ADD_TEST(seq_suite, test_sequence_reverse);
|
||||
#endif
|
||||
CU_ADD_TEST(seq_suite, test_sequence_copy_elision);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user