Commit d207237f authored by paul luse's avatar paul luse Committed by Jim Harris
Browse files

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: default avatarpaul luse <paul.e.luse@intel.com>
Change-Id: Ib54311c1fb98abd2fb61df6603cf3c5300b71161
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/2952


Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
parent a7dfca5b
Loading
Loading
Loading
Loading
+18 −1
Original line number Diff line number Diff line
@@ -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) {

+20 −0
Original line number Diff line number Diff line
@@ -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.
 *
+2 −0
Original line number Diff line number Diff line
@@ -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,
+42 −0
Original line number Diff line number Diff line
@@ -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,
+1 −0
Original line number Diff line number Diff line
@@ -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;