Commit 455525f5 authored by Daniel Verkamp's avatar Daniel Verkamp Committed by Jim Harris
Browse files

examples/nvme/hotplug: simplify buffer management



We don't need to allocate/free tasks on every I/O; we can just
allocate the tasks and buffers once in the initial submit_io() loop.

This also removes the remaining direct DPDK calls from the hotplug
example.

Change-Id: Ie8774b289e650b3fa64614f2da0efbefd013a610
Signed-off-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Reviewed-on: https://review.gerrithub.io/376864


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent 7fc4405c
Loading
Loading
Loading
Loading
+36 −29
Original line number Diff line number Diff line
@@ -33,9 +33,6 @@

#include "spdk/stdinc.h"

#include <rte_config.h>
#include <rte_mempool.h>

#include "spdk/nvme.h"
#include "spdk/queue.h"

@@ -61,8 +58,6 @@ struct perf_task {
	void			*buf;
};

static struct rte_mempool *task_pool;

static TAILQ_HEAD(, dev_ctx) g_devs = TAILQ_HEAD_INITIALIZER(g_devs);

static uint64_t g_tsc_rate;
@@ -144,33 +139,42 @@ unregister_dev(struct dev_ctx *dev)
	free(dev);
}

static void task_ctor(struct rte_mempool *mp, void *arg, void *__task, unsigned id)
static struct perf_task *
alloc_task(struct dev_ctx *dev)
{
	struct perf_task *task = __task;
	struct perf_task *task;

	task = calloc(1, sizeof(*task));
	if (task == NULL) {
		return NULL;
	}

	task->buf = spdk_dma_zmalloc(g_io_size_bytes, 0x200, NULL);
	if (task->buf == NULL) {
		fprintf(stderr, "task->buf rte_malloc failed\n");
		exit(1);
		return NULL;
	}
	memset(task->buf, id % 8, g_io_size_bytes);

	task->dev = dev;

	return task;
}

static void
free_task(struct perf_task *task)
{
	spdk_dma_free(task->buf);
	free(task);
}

static void io_complete(void *ctx, const struct spdk_nvme_cpl *completion);

static void
submit_single_io(struct dev_ctx *dev)
submit_single_io(struct perf_task *task)
{
	struct perf_task	*task = NULL;
	struct dev_ctx		*dev = task->dev;
	uint64_t		offset_in_ios;
	int			rc;

	if (rte_mempool_get(task_pool, (void **)&task) != 0) {
		fprintf(stderr, "task_pool rte_mempool_get failed\n");
		exit(1);
	}

	task->dev = dev;

	offset_in_ios = dev->offset_in_ios++;
	if (dev->offset_in_ios == dev->size_in_ios) {
		dev->offset_in_ios = 0;
@@ -182,7 +186,7 @@ submit_single_io(struct dev_ctx *dev)

	if (rc != 0) {
		fprintf(stderr, "starting I/O failed\n");
		rte_mempool_put(task_pool, task);
		free_task(task);
	} else {
		dev->current_queue_depth++;
	}
@@ -197,8 +201,6 @@ task_complete(struct perf_task *task)
	dev->current_queue_depth--;
	dev->io_completed++;

	rte_mempool_put(task_pool, task);

	/*
	 * is_draining indicates when time has expired for the test run
	 * and we are just waiting for the previously submitted I/O
@@ -206,7 +208,9 @@ task_complete(struct perf_task *task)
	 * the one just completed.
	 */
	if (!dev->is_draining && !dev->is_removed) {
		submit_single_io(dev);
		submit_single_io(task);
	} else {
		free_task(task);
	}
}

@@ -225,8 +229,16 @@ check_io(struct dev_ctx *dev)
static void
submit_io(struct dev_ctx *dev, int queue_depth)
{
	struct perf_task *task;

	while (queue_depth-- > 0) {
		submit_single_io(dev);
		task = alloc_task(dev);
		if (task == NULL) {
			fprintf(stderr, "task allocation failed\n");
			exit(1);
		}

		submit_single_io(task);
	}
}

@@ -449,11 +461,6 @@ int main(int argc, char **argv)
	}
	spdk_env_init(&opts);

	task_pool = rte_mempool_create("task_pool", 8192,
				       sizeof(struct perf_task),
				       64, 0, NULL, NULL, task_ctor, NULL,
				       SOCKET_ID_ANY, 0);

	g_tsc_rate = spdk_get_ticks_hz();

	/* Detect the controllers that are plugged in at startup. */