lib/accel: add batch functionality for fill command
Also as a minor drive-by, added verify capability for fill that wasn't there before, useful in making sure the prep function was working and really should have been there anyway. idxd support for prep fill will follow. Signed-off-by: paul luse <paul.e.luse@intel.com> Change-Id: Ib54311c1fb98abd2fb61df6603cf3c5300b71161 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/2952 Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Community-CI: Mellanox Build Bot
This commit is contained in:
parent
a7dfca5b45
commit
d207237fc4
@ -290,6 +290,12 @@ _accel_done(void *arg1)
|
||||
worker->xfer_failed++;
|
||||
}
|
||||
break;
|
||||
case ACCEL_FILL:
|
||||
if (memcmp(task->dst, task->src, g_xfer_size_bytes)) {
|
||||
SPDK_NOTICELOG("Data miscompare\n");
|
||||
worker->xfer_failed++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
@ -438,6 +444,11 @@ _get_task_data_bufs(struct ap_task *task)
|
||||
memset(task->dst, ~DATA_PATTERN, g_xfer_size_bytes);
|
||||
}
|
||||
|
||||
/* For fill, set the entire src buffer so we can check if verify is enabled. */
|
||||
if (g_workload_selection == ACCEL_FILL) {
|
||||
memset(task->src, g_fill_pattern, g_xfer_size_bytes);
|
||||
}
|
||||
|
||||
if (g_workload_selection == ACCEL_DUALCAST) {
|
||||
task->dst2 = spdk_dma_zmalloc(g_xfer_size_bytes, align, NULL);
|
||||
if (task->dst2 == NULL) {
|
||||
@ -471,6 +482,11 @@ _batch_prep_cmd(struct worker_thread *worker, struct ap_task *task, struct spdk_
|
||||
worker->ch, batch, task->dst, task->src,
|
||||
g_xfer_size_bytes, accel_done);
|
||||
break;
|
||||
case ACCEL_FILL:
|
||||
rc = spdk_accel_batch_prep_fill(__accel_task_from_ap_task(task),
|
||||
worker->ch, batch, task->dst, *(uint8_t *)task->src,
|
||||
g_xfer_size_bytes, accel_done);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
@ -524,7 +540,8 @@ _init_thread(void *arg1)
|
||||
/* TODO: remove the workload selection checks once all are added. */
|
||||
if ((g_workload_selection == ACCEL_COPY ||
|
||||
g_workload_selection == ACCEL_DUALCAST ||
|
||||
g_workload_selection == ACCEL_COMPARE)
|
||||
g_workload_selection == ACCEL_COMPARE ||
|
||||
g_workload_selection == ACCEL_FILL)
|
||||
&& ((g_capabilites & ACCEL_BATCH) == ACCEL_BATCH) &&
|
||||
g_queue_depth > 1) {
|
||||
|
||||
|
@ -262,6 +262,26 @@ int spdk_accel_submit_compare(struct spdk_accel_task *accel_req, struct spdk_io_
|
||||
void *src1, void *src2, uint64_t nbytes,
|
||||
spdk_accel_completion_cb cb);
|
||||
|
||||
/**
|
||||
* Synchronous call to prepare a fill request into a previously initialized batch
|
||||
* created with spdk_accel_batch_create(). The callback will be called when the fill
|
||||
* completes after the batch has been submitted by an asynchronous call to
|
||||
* spdk_accel_batch_submit().
|
||||
*
|
||||
* \param accel_req Accel request task.
|
||||
* \param ch I/O channel to submit request to the accel engine.
|
||||
* \param batch Handle provided when the batch was started with spdk_accel_batch_create().
|
||||
* \param dst Destination to fill.
|
||||
* \param fill Constant byte to fill to the destination.
|
||||
* \param nbytes Length in bytes to fill.
|
||||
* \param cb Called when this operation completes.
|
||||
*
|
||||
* \return 0 on success, negative errno on failure.
|
||||
*/
|
||||
int spdk_accel_batch_prep_fill(struct spdk_accel_task *accel_req, struct spdk_io_channel *ch,
|
||||
struct spdk_accel_batch *batch, void *dst, uint8_t fill,
|
||||
uint64_t nbytes, spdk_accel_completion_cb cb);
|
||||
|
||||
/**
|
||||
* Submit a fill request.
|
||||
*
|
||||
|
@ -58,6 +58,8 @@ struct spdk_accel_engine {
|
||||
void *dst1, void *dst2, void *src, uint64_t nbytes, spdk_accel_completion_cb cb);
|
||||
int (*batch_prep_compare)(void *cb_arg, struct spdk_io_channel *ch, struct spdk_accel_batch *batch,
|
||||
void *src1, void *src2, uint64_t nbytes, spdk_accel_completion_cb cb);
|
||||
int (*batch_prep_fill)(void *cb_arg, struct spdk_io_channel *ch, struct spdk_accel_batch *batch,
|
||||
void *dst, uint8_t fill, uint64_t nbytes, spdk_accel_completion_cb cb);
|
||||
int (*batch_submit)(void *cb_arg, struct spdk_io_channel *ch, struct spdk_accel_batch *batch,
|
||||
spdk_accel_completion_cb cb);
|
||||
int (*compare)(void *cb_arg, struct spdk_io_channel *ch, void *src1, void *src2,
|
||||
|
@ -255,6 +255,21 @@ spdk_accel_batch_prep_compare(struct spdk_accel_task *accel_req, struct spdk_io_
|
||||
batch, src1, src2, nbytes, _accel_engine_done);
|
||||
}
|
||||
|
||||
/* Accel framework public API for batch prep_fill function. All engines are
|
||||
* required to implement this API.
|
||||
*/
|
||||
int
|
||||
spdk_accel_batch_prep_fill(struct spdk_accel_task *accel_req, struct spdk_io_channel *ch,
|
||||
struct spdk_accel_batch *batch, void *dst, uint8_t fill, uint64_t nbytes,
|
||||
spdk_accel_completion_cb cb)
|
||||
{
|
||||
struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
|
||||
|
||||
accel_req->cb = cb;
|
||||
return accel_ch->engine->batch_prep_fill(accel_req->offload_ctx, accel_ch->ch,
|
||||
batch, dst, fill, nbytes, _accel_engine_done);
|
||||
}
|
||||
|
||||
/* Accel framework public API for compare function */
|
||||
int
|
||||
spdk_accel_submit_compare(struct spdk_accel_task *accel_req, struct spdk_io_channel *ch,
|
||||
@ -626,6 +641,29 @@ sw_accel_batch_prep_compare(void *cb_arg, struct spdk_io_channel *ch,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sw_accel_batch_prep_fill(void *cb_arg, struct spdk_io_channel *ch,
|
||||
struct spdk_accel_batch *batch, void *dst, uint8_t fill,
|
||||
uint64_t nbytes, spdk_accel_completion_cb cb)
|
||||
{
|
||||
struct sw_accel_op *op;
|
||||
struct sw_accel_io_channel *sw_ch = spdk_io_channel_get_ctx(ch);
|
||||
|
||||
op = _prep_op(cb_arg, sw_ch, batch, cb);
|
||||
if (op == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Command specific. */
|
||||
op->dst = dst;
|
||||
op->fill_pattern = fill;
|
||||
op->nbytes = nbytes;
|
||||
op->op_code = SW_ACCEL_OPCODE_MEMFILL;
|
||||
TAILQ_INSERT_TAIL(&sw_ch->batch, op, link);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sw_accel_batch_submit(void *cb_arg, struct spdk_io_channel *ch, struct spdk_accel_batch *batch,
|
||||
spdk_accel_completion_cb cb)
|
||||
@ -657,6 +695,9 @@ sw_accel_batch_submit(void *cb_arg, struct spdk_io_channel *ch, struct spdk_acce
|
||||
case SW_ACCEL_OPCODE_COMPARE:
|
||||
cmd_status = memcmp(op->src, op->src2, op->nbytes);
|
||||
break;
|
||||
case SW_ACCEL_OPCODE_MEMFILL:
|
||||
memset(op->dst, op->fill_pattern, op->nbytes);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
@ -759,6 +800,7 @@ static struct spdk_accel_engine sw_accel_engine = {
|
||||
.batch_prep_copy = sw_accel_batch_prep_copy,
|
||||
.batch_prep_dualcast = sw_accel_batch_prep_dualcast,
|
||||
.batch_prep_compare = sw_accel_batch_prep_compare,
|
||||
.batch_prep_fill = sw_accel_batch_prep_fill,
|
||||
.batch_submit = sw_accel_batch_submit,
|
||||
.compare = sw_accel_submit_compare,
|
||||
.fill = sw_accel_submit_fill,
|
||||
|
@ -13,6 +13,7 @@
|
||||
spdk_accel_batch_prep_copy;
|
||||
spdk_accel_batch_prep_dualcast;
|
||||
spdk_accel_batch_prep_compare;
|
||||
spdk_accel_batch_prep_fill;
|
||||
spdk_accel_batch_submit;
|
||||
spdk_accel_submit_copy;
|
||||
spdk_accel_submit_dualcast;
|
||||
|
Loading…
Reference in New Issue
Block a user