diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ddf2c418..64f1f2c85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ Added API `spdk_accel_submit_copy_crc32c` to perform a CRC32C while copying data Added API `spdk_accel_batch_prep_copy_crc32c` to batch CRC32C + copy commands. +Added API `spdk_accel_submit_copy_crc32cv` to submit chained CRC32C + copy commands. + ### bdev Change `spdk_bdev_read_blocks_with_md` arg offset definiton from int64_t to uint64_t. diff --git a/include/spdk/accel_engine.h b/include/spdk/accel_engine.h index 051e2aadf..cedad215a 100644 --- a/include/spdk/accel_engine.h +++ b/include/spdk/accel_engine.h @@ -415,6 +415,26 @@ int spdk_accel_submit_copy_crc32c(struct spdk_io_channel *ch, void *dst, void *s uint32_t *crc_dst, uint32_t seed, uint64_t nbytes, spdk_accel_completion_cb cb_fn, void *cb_arg); +/** + * Submit a chained copy + CRC-32C calculation request. + * + * This operation will calculate the 4 byte CRC32-C for the given data. + * + * \param ch I/O channel associated with this call. + * \param dst Destination to write the data to. + * \param src_iovs The io vector array which stores the src data and len. + * \param iovcnt The size of the io vectors. + * \param crc_dst Destination to write the CRC-32C to. + * \param seed Four byte seed value. + * \param cb_fn Called when this CRC-32C operation completes. + * \param cb_arg Callback argument. + * + * \return 0 on success, negative errno on failure. + */ +int spdk_accel_submit_copy_crc32cv(struct spdk_io_channel *ch, void *dst, struct iovec *src_iovs, + uint32_t iovcnt, uint32_t *crc_dst, uint32_t seed, spdk_accel_completion_cb cb_fn, void *cb_arg); + + struct spdk_json_write_ctx; /** diff --git a/include/spdk_internal/accel_engine.h b/include/spdk_internal/accel_engine.h index a3cb56306..f307e9cbb 100644 --- a/include/spdk_internal/accel_engine.h +++ b/include/spdk_internal/accel_engine.h @@ -84,7 +84,7 @@ struct spdk_accel_task { struct { spdk_accel_completion_cb cb_fn; void *cb_arg; - } chained; + } chained; union { struct { struct iovec *iovs; /* iovs passed by the caller */ diff --git a/lib/accel/accel_engine.c b/lib/accel/accel_engine.c index 906ff4b17..37a08921d 100644 --- a/lib/accel/accel_engine.c +++ b/lib/accel/accel_engine.c @@ -338,9 +338,18 @@ crc32cv_done(void *cb_arg, int status) assert(accel_task->chained.cb_arg != NULL); if (spdk_likely(!status)) { - status = spdk_accel_submit_crc32cv(ch, accel_task->dst, ++accel_task->v.iovs, - accel_task->v.iovcnt - 1, ~(*((uint32_t *)accel_task->dst)), - accel_task->chained.cb_fn, accel_task->chained.cb_arg); + if (accel_task->op_code == ACCEL_OPCODE_COPY_CRC32C) { + accel_task->dst = (char *)accel_task->dst + accel_task->nbytes; + status = spdk_accel_submit_copy_crc32cv(ch, accel_task->dst, ++accel_task->v.iovs, + accel_task->v.iovcnt - 1, accel_task->crc_dst, + ~(*((uint32_t *)accel_task->crc_dst)), + accel_task->chained.cb_fn, accel_task->chained.cb_arg); + } else { + status = spdk_accel_submit_crc32cv(ch, accel_task->dst, ++accel_task->v.iovs, + accel_task->v.iovcnt - 1, ~(*((uint32_t *)accel_task->dst)), + accel_task->chained.cb_fn, accel_task->chained.cb_arg); + } + if (spdk_likely(!status)) { return; } @@ -433,6 +442,63 @@ spdk_accel_submit_copy_crc32c(struct spdk_io_channel *ch, void *dst, void *src, } } +/* Accel framework public API for chained copy + CRC-32C function */ +int +spdk_accel_submit_copy_crc32cv(struct spdk_io_channel *ch, void *dst, struct iovec *src_iovs, + uint32_t iov_cnt, uint32_t *crc_dst, uint32_t seed, + spdk_accel_completion_cb cb_fn, void *cb_arg) +{ + struct accel_io_channel *accel_ch; + struct spdk_accel_task *accel_task; + + if (src_iovs == NULL) { + SPDK_ERRLOG("iov should not be NULL"); + return -EINVAL; + } + + if (!iov_cnt) { + SPDK_ERRLOG("iovcnt should not be zero value\n"); + return -EINVAL; + } + + if (iov_cnt == 1) { + return spdk_accel_submit_copy_crc32c(ch, dst, src_iovs[0].iov_base, crc_dst, seed, + src_iovs[0].iov_len, cb_fn, cb_arg); + } + + accel_ch = spdk_io_channel_get_ctx(ch); + accel_task = _get_task(accel_ch, NULL, cb_fn, cb_arg); + if (accel_task == NULL) { + SPDK_ERRLOG("no memory\n"); + assert(0); + return -ENOMEM; + } + + accel_task->v.iovs = src_iovs; + accel_task->v.iovcnt = iov_cnt; + accel_task->dst = (void *)dst; + accel_task->crc_dst = crc_dst; + accel_task->seed = seed; + accel_task->op_code = ACCEL_OPCODE_COPY_CRC32C; + + if (_is_supported(accel_ch->engine, ACCEL_COPY_CRC32C)) { + accel_task->cb_fn = crc32cv_done; + accel_task->cb_arg = accel_task; + accel_task->chained.cb_fn = cb_fn; + accel_task->chained.cb_arg = cb_arg; + + accel_task->nbytes = src_iovs[0].iov_len; + + return accel_ch->engine->submit_tasks(accel_ch->engine_ch, accel_task); + } else { + _sw_accel_copy(dst, src_iovs[0].iov_base, src_iovs[0].iov_len); + _sw_accel_crc32cv(crc_dst, src_iovs, iov_cnt, seed); + spdk_accel_task_complete(accel_task, 0); + return 0; + } +} + + /* Accel framework public API for getting max operations for a batch. */ uint32_t spdk_accel_batch_get_max(struct spdk_io_channel *ch) diff --git a/lib/accel/spdk_accel.map b/lib/accel/spdk_accel.map index 35699f7fa..f85cc52ba 100644 --- a/lib/accel/spdk_accel.map +++ b/lib/accel/spdk_accel.map @@ -25,6 +25,7 @@ spdk_accel_submit_crc32c; spdk_accel_submit_crc32cv; spdk_accel_submit_copy_crc32c; + spdk_accel_submit_copy_crc32cv; spdk_accel_write_config_json; # functions needed by modules diff --git a/module/accel/idxd/accel_engine_idxd.c b/module/accel/idxd/accel_engine_idxd.c index d9a010ff3..107af77ae 100644 --- a/module/accel/idxd/accel_engine_idxd.c +++ b/module/accel/idxd/accel_engine_idxd.c @@ -168,7 +168,8 @@ _process_single_task(struct spdk_io_channel *ch, struct spdk_accel_task *task) task); break; case ACCEL_OPCODE_COPY_CRC32C: - rc = spdk_idxd_submit_copy_crc32c(chan->chan, task->dst, task->src, task->crc_dst, task->seed, + src = (task->v.iovcnt == 0) ? task->src : task->v.iovs[0].iov_base; + rc = spdk_idxd_submit_copy_crc32c(chan->chan, task->dst, src, task->crc_dst, task->seed, task->nbytes, idxd_done, task); break; default: