nvme_perf: Introduce function pointer table for IO type dependent operations
Introduce a function pointer table to ns_entry to remove if-else sequence in every operation depending on the type, AIO or NVMe. This will simplify upcoming DIF and DIX support in the Perf tool. Change-Id: Ibbd9a9ac3a0b5df529d5b60706ce750a746114c3 Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-on: https://review.gerrithub.io/c/439630 Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
This commit is contained in:
parent
f75128a943
commit
07fa7327df
@ -59,8 +59,11 @@ enum entry_type {
|
|||||||
ENTRY_TYPE_AIO_FILE,
|
ENTRY_TYPE_AIO_FILE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ns_fn_table;
|
||||||
|
|
||||||
struct ns_entry {
|
struct ns_entry {
|
||||||
enum entry_type type;
|
enum entry_type type;
|
||||||
|
const struct ns_fn_table *fn_table;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
@ -151,6 +154,21 @@ struct worker_thread {
|
|||||||
unsigned lcore;
|
unsigned lcore;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ns_fn_table {
|
||||||
|
void (*setup_payload)(struct perf_task *task, uint8_t pattern);
|
||||||
|
|
||||||
|
int (*submit_io)(struct perf_task *task, struct ns_worker_ctx *ns_ctx,
|
||||||
|
struct ns_entry *entry, uint64_t offset_in_ios);
|
||||||
|
|
||||||
|
void (*check_io)(struct ns_worker_ctx *ns_ctx);
|
||||||
|
|
||||||
|
void (*verify_io)(struct perf_task *task, struct ns_entry *entry);
|
||||||
|
|
||||||
|
int (*init_ns_worker_ctx)(struct ns_worker_ctx *ns_ctx);
|
||||||
|
|
||||||
|
void (*cleanup_ns_worker_ctx)(struct ns_worker_ctx *ns_ctx);
|
||||||
|
};
|
||||||
|
|
||||||
static int g_outstanding_commands;
|
static int g_outstanding_commands;
|
||||||
|
|
||||||
static bool g_latency_ssd_tracking_enable = false;
|
static bool g_latency_ssd_tracking_enable = false;
|
||||||
@ -200,6 +218,17 @@ static void
|
|||||||
task_complete(struct perf_task *task);
|
task_complete(struct perf_task *task);
|
||||||
|
|
||||||
#if HAVE_LIBAIO
|
#if HAVE_LIBAIO
|
||||||
|
static void
|
||||||
|
aio_setup_payload(struct perf_task *task, uint8_t pattern)
|
||||||
|
{
|
||||||
|
task->buf = spdk_dma_zmalloc(g_io_size_bytes, g_io_align, NULL);
|
||||||
|
if (task->buf == NULL) {
|
||||||
|
fprintf(stderr, "spdk_dma_zmalloc() for task->buf failed\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
memset(task->buf, pattern, g_io_size_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
aio_submit(io_context_t aio_ctx, struct iocb *iocb, int fd, enum io_iocb_cmd cmd, void *buf,
|
aio_submit(io_context_t aio_ctx, struct iocb *iocb, int fd, enum io_iocb_cmd cmd, void *buf,
|
||||||
unsigned long nbytes, uint64_t offset, void *cb_ctx)
|
unsigned long nbytes, uint64_t offset, void *cb_ctx)
|
||||||
@ -220,6 +249,19 @@ aio_submit(io_context_t aio_ctx, struct iocb *iocb, int fd, enum io_iocb_cmd cmd
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
aio_submit_io(struct perf_task *task, struct ns_worker_ctx *ns_ctx,
|
||||||
|
struct ns_entry *entry, uint64_t offset_in_ios)
|
||||||
|
{
|
||||||
|
if (task->is_read) {
|
||||||
|
return aio_submit(ns_ctx->u.aio.ctx, &task->iocb, entry->u.aio.fd, IO_CMD_PREAD, task->buf,
|
||||||
|
g_io_size_bytes, offset_in_ios * g_io_size_bytes, task);
|
||||||
|
} else {
|
||||||
|
return aio_submit(ns_ctx->u.aio.ctx, &task->iocb, entry->u.aio.fd, IO_CMD_PWRITE, task->buf,
|
||||||
|
g_io_size_bytes, offset_in_ios * g_io_size_bytes, task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
aio_check_io(struct ns_worker_ctx *ns_ctx)
|
aio_check_io(struct ns_worker_ctx *ns_ctx)
|
||||||
{
|
{
|
||||||
@ -240,6 +282,43 @@ aio_check_io(struct ns_worker_ctx *ns_ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
aio_verify_io(struct perf_task *task, struct ns_entry *entry)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
aio_init_ns_worker_ctx(struct ns_worker_ctx *ns_ctx)
|
||||||
|
{
|
||||||
|
ns_ctx->u.aio.events = calloc(g_queue_depth, sizeof(struct io_event));
|
||||||
|
if (!ns_ctx->u.aio.events) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ns_ctx->u.aio.ctx = 0;
|
||||||
|
if (io_setup(g_queue_depth, &ns_ctx->u.aio.ctx) < 0) {
|
||||||
|
free(ns_ctx->u.aio.events);
|
||||||
|
perror("io_setup");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
aio_cleanup_ns_worker_ctx(struct ns_worker_ctx *ns_ctx)
|
||||||
|
{
|
||||||
|
io_destroy(ns_ctx->u.aio.ctx);
|
||||||
|
free(ns_ctx->u.aio.events);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct ns_fn_table aio_fn_table = {
|
||||||
|
.setup_payload = aio_setup_payload,
|
||||||
|
.submit_io = aio_submit_io,
|
||||||
|
.check_io = aio_check_io,
|
||||||
|
.verify_io = aio_verify_io,
|
||||||
|
.init_ns_worker_ctx = aio_init_ns_worker_ctx,
|
||||||
|
.cleanup_ns_worker_ctx = aio_cleanup_ns_worker_ctx,
|
||||||
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
register_aio_file(const char *path)
|
register_aio_file(const char *path)
|
||||||
{
|
{
|
||||||
@ -295,6 +374,7 @@ register_aio_file(const char *path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
entry->type = ENTRY_TYPE_AIO_FILE;
|
entry->type = ENTRY_TYPE_AIO_FILE;
|
||||||
|
entry->fn_table = &aio_fn_table;
|
||||||
entry->u.aio.fd = fd;
|
entry->u.aio.fd = fd;
|
||||||
entry->size_in_ios = size / g_io_size_bytes;
|
entry->size_in_ios = size / g_io_size_bytes;
|
||||||
entry->io_size_blocks = g_io_size_bytes / blklen;
|
entry->io_size_blocks = g_io_size_bytes / blklen;
|
||||||
@ -459,6 +539,105 @@ task_extended_lba_pi_verify(struct ns_entry *entry, struct perf_task *task,
|
|||||||
|
|
||||||
static void io_complete(void *ctx, const struct spdk_nvme_cpl *cpl);
|
static void io_complete(void *ctx, const struct spdk_nvme_cpl *cpl);
|
||||||
|
|
||||||
|
static void
|
||||||
|
nvme_setup_payload(struct perf_task *task, uint8_t pattern)
|
||||||
|
{
|
||||||
|
uint32_t max_io_size_bytes;
|
||||||
|
|
||||||
|
/* maximum extended lba format size from all active namespace,
|
||||||
|
* it's same with g_io_size_bytes for namespace without metadata.
|
||||||
|
*/
|
||||||
|
max_io_size_bytes = g_io_size_bytes + g_max_io_md_size * g_max_io_size_blocks;
|
||||||
|
task->buf = spdk_dma_zmalloc(max_io_size_bytes, g_io_align, NULL);
|
||||||
|
if (task->buf == NULL) {
|
||||||
|
fprintf(stderr, "task->buf spdk_dma_zmalloc failed\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
memset(task->buf, pattern, max_io_size_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
nvme_submit_io(struct perf_task *task, struct ns_worker_ctx *ns_ctx,
|
||||||
|
struct ns_entry *entry, uint64_t offset_in_ios)
|
||||||
|
{
|
||||||
|
task->lba = offset_in_ios * entry->io_size_blocks;
|
||||||
|
|
||||||
|
task_extended_lba_setup_pi(entry, task, task->lba,
|
||||||
|
entry->io_size_blocks, !task->is_read);
|
||||||
|
|
||||||
|
if (task->is_read) {
|
||||||
|
return spdk_nvme_ns_cmd_read_with_md(entry->u.nvme.ns, ns_ctx->u.nvme.qpair,
|
||||||
|
task->buf, NULL,
|
||||||
|
task->lba,
|
||||||
|
entry->io_size_blocks, io_complete,
|
||||||
|
task, entry->io_flags,
|
||||||
|
task->appmask, task->apptag);
|
||||||
|
} else {
|
||||||
|
return spdk_nvme_ns_cmd_write_with_md(entry->u.nvme.ns, ns_ctx->u.nvme.qpair,
|
||||||
|
task->buf, NULL,
|
||||||
|
task->lba,
|
||||||
|
entry->io_size_blocks, io_complete,
|
||||||
|
task, entry->io_flags,
|
||||||
|
task->appmask, task->apptag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nvme_check_io(struct ns_worker_ctx *ns_ctx)
|
||||||
|
{
|
||||||
|
spdk_nvme_qpair_process_completions(ns_ctx->u.nvme.qpair, g_max_completions);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nvme_verify_io(struct perf_task *task, struct ns_entry *entry)
|
||||||
|
{
|
||||||
|
if (spdk_nvme_ns_supports_extended_lba(entry->u.nvme.ns) &&
|
||||||
|
task->is_read && !g_metacfg_pract_flag) {
|
||||||
|
task_extended_lba_pi_verify(entry, task, task->lba,
|
||||||
|
entry->io_size_blocks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: If a controller has multiple namespaces, they could all use the same queue.
|
||||||
|
* For now, give each namespace/thread combination its own queue.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
nvme_init_ns_worker_ctx(struct ns_worker_ctx *ns_ctx)
|
||||||
|
{
|
||||||
|
struct spdk_nvme_io_qpair_opts opts;
|
||||||
|
struct ns_entry *entry = ns_ctx->entry;
|
||||||
|
|
||||||
|
spdk_nvme_ctrlr_get_default_io_qpair_opts(entry->u.nvme.ctrlr, &opts, sizeof(opts));
|
||||||
|
if (opts.io_queue_requests < entry->num_io_requests) {
|
||||||
|
opts.io_queue_requests = entry->num_io_requests;
|
||||||
|
}
|
||||||
|
|
||||||
|
ns_ctx->u.nvme.qpair = spdk_nvme_ctrlr_alloc_io_qpair(entry->u.nvme.ctrlr, &opts,
|
||||||
|
sizeof(opts));
|
||||||
|
if (!ns_ctx->u.nvme.qpair) {
|
||||||
|
printf("ERROR: spdk_nvme_ctrlr_alloc_io_qpair failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nvme_cleanup_ns_worker_ctx(struct ns_worker_ctx *ns_ctx)
|
||||||
|
{
|
||||||
|
spdk_nvme_ctrlr_free_io_qpair(ns_ctx->u.nvme.qpair);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct ns_fn_table nvme_fn_table = {
|
||||||
|
.setup_payload = nvme_setup_payload,
|
||||||
|
.submit_io = nvme_submit_io,
|
||||||
|
.check_io = nvme_check_io,
|
||||||
|
.verify_io = nvme_verify_io,
|
||||||
|
.init_ns_worker_ctx = nvme_init_ns_worker_ctx,
|
||||||
|
.cleanup_ns_worker_ctx = nvme_cleanup_ns_worker_ctx,
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
register_ns(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns)
|
register_ns(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns)
|
||||||
{
|
{
|
||||||
@ -509,6 +688,7 @@ register_ns(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns)
|
|||||||
}
|
}
|
||||||
|
|
||||||
entry->type = ENTRY_TYPE_NVME_NS;
|
entry->type = ENTRY_TYPE_NVME_NS;
|
||||||
|
entry->fn_table = &nvme_fn_table;
|
||||||
entry->u.nvme.ctrlr = ctrlr;
|
entry->u.nvme.ctrlr = ctrlr;
|
||||||
entry->u.nvme.ns = ns;
|
entry->u.nvme.ns = ns;
|
||||||
entry->num_io_requests = entries;
|
entry->num_io_requests = entries;
|
||||||
@ -655,50 +835,17 @@ submit_single_io(struct perf_task *task)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task->is_read = false;
|
|
||||||
task->submit_tsc = spdk_get_ticks();
|
task->submit_tsc = spdk_get_ticks();
|
||||||
task->lba = offset_in_ios * entry->io_size_blocks;
|
|
||||||
|
|
||||||
if ((g_rw_percentage == 100) ||
|
if ((g_rw_percentage == 100) ||
|
||||||
(g_rw_percentage != 0 && ((rand_r(&seed) % 100) < g_rw_percentage))) {
|
(g_rw_percentage != 0 && ((rand_r(&seed) % 100) < g_rw_percentage))) {
|
||||||
#if HAVE_LIBAIO
|
task->is_read = true;
|
||||||
if (entry->type == ENTRY_TYPE_AIO_FILE) {
|
|
||||||
rc = aio_submit(ns_ctx->u.aio.ctx, &task->iocb, entry->u.aio.fd, IO_CMD_PREAD, task->buf,
|
|
||||||
g_io_size_bytes, offset_in_ios * g_io_size_bytes, task);
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
task_extended_lba_setup_pi(entry, task, task->lba,
|
|
||||||
entry->io_size_blocks, false);
|
|
||||||
task->is_read = true;
|
|
||||||
|
|
||||||
rc = spdk_nvme_ns_cmd_read_with_md(entry->u.nvme.ns, ns_ctx->u.nvme.qpair,
|
|
||||||
task->buf, NULL,
|
|
||||||
task->lba,
|
|
||||||
entry->io_size_blocks, io_complete,
|
|
||||||
task, entry->io_flags,
|
|
||||||
task->appmask, task->apptag);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
#if HAVE_LIBAIO
|
task->is_read = false;
|
||||||
if (entry->type == ENTRY_TYPE_AIO_FILE) {
|
|
||||||
rc = aio_submit(ns_ctx->u.aio.ctx, &task->iocb, entry->u.aio.fd, IO_CMD_PWRITE, task->buf,
|
|
||||||
g_io_size_bytes, offset_in_ios * g_io_size_bytes, task);
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
task_extended_lba_setup_pi(entry, task, task->lba,
|
|
||||||
entry->io_size_blocks, true);
|
|
||||||
|
|
||||||
rc = spdk_nvme_ns_cmd_write_with_md(entry->u.nvme.ns, ns_ctx->u.nvme.qpair,
|
|
||||||
task->buf, NULL,
|
|
||||||
task->lba,
|
|
||||||
entry->io_size_blocks, io_complete,
|
|
||||||
task, entry->io_flags,
|
|
||||||
task->appmask, task->apptag);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = entry->fn_table->submit_io(task, ns_ctx, entry, offset_in_ios);
|
||||||
|
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
fprintf(stderr, "starting I/O failed\n");
|
fprintf(stderr, "starting I/O failed\n");
|
||||||
} else {
|
} else {
|
||||||
@ -730,13 +877,7 @@ task_complete(struct perf_task *task)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* add application level verification for end-to-end data protection */
|
/* add application level verification for end-to-end data protection */
|
||||||
if (entry->type == ENTRY_TYPE_NVME_NS) {
|
entry->fn_table->verify_io(task, entry);
|
||||||
if (spdk_nvme_ns_supports_extended_lba(entry->u.nvme.ns) &&
|
|
||||||
task->is_read && !g_metacfg_pract_flag) {
|
|
||||||
task_extended_lba_pi_verify(entry, task, task->lba,
|
|
||||||
entry->io_size_blocks);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* is_draining indicates when time has expired for the test run
|
* is_draining indicates when time has expired for the test run
|
||||||
@ -769,21 +910,13 @@ io_complete(void *ctx, const struct spdk_nvme_cpl *cpl)
|
|||||||
static void
|
static void
|
||||||
check_io(struct ns_worker_ctx *ns_ctx)
|
check_io(struct ns_worker_ctx *ns_ctx)
|
||||||
{
|
{
|
||||||
#if HAVE_LIBAIO
|
ns_ctx->entry->fn_table->check_io(ns_ctx);
|
||||||
if (ns_ctx->entry->type == ENTRY_TYPE_AIO_FILE) {
|
|
||||||
aio_check_io(ns_ctx);
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
spdk_nvme_qpair_process_completions(ns_ctx->u.nvme.qpair, g_max_completions);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct perf_task *
|
static struct perf_task *
|
||||||
allocate_task(struct ns_worker_ctx *ns_ctx, int queue_depth)
|
allocate_task(struct ns_worker_ctx *ns_ctx, int queue_depth)
|
||||||
{
|
{
|
||||||
struct perf_task *task;
|
struct perf_task *task;
|
||||||
uint32_t max_io_size_bytes;
|
|
||||||
|
|
||||||
task = calloc(1, sizeof(*task));
|
task = calloc(1, sizeof(*task));
|
||||||
if (task == NULL) {
|
if (task == NULL) {
|
||||||
@ -791,16 +924,7 @@ allocate_task(struct ns_worker_ctx *ns_ctx, int queue_depth)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* maximum extended lba format size from all active namespace,
|
ns_ctx->entry->fn_table->setup_payload(task, queue_depth % 8 + 1);
|
||||||
* it's same with g_io_size_bytes for namespace without metadata.
|
|
||||||
*/
|
|
||||||
max_io_size_bytes = g_io_size_bytes + g_max_io_md_size * g_max_io_size_blocks;
|
|
||||||
task->buf = spdk_dma_zmalloc(max_io_size_bytes, g_io_align, NULL);
|
|
||||||
if (task->buf == NULL) {
|
|
||||||
fprintf(stderr, "task->buf spdk_dma_zmalloc failed\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
memset(task->buf, queue_depth % 8 + 1, max_io_size_bytes);
|
|
||||||
|
|
||||||
task->ns_ctx = ns_ctx;
|
task->ns_ctx = ns_ctx;
|
||||||
|
|
||||||
@ -821,53 +945,13 @@ submit_io(struct ns_worker_ctx *ns_ctx, int queue_depth)
|
|||||||
static int
|
static int
|
||||||
init_ns_worker_ctx(struct ns_worker_ctx *ns_ctx)
|
init_ns_worker_ctx(struct ns_worker_ctx *ns_ctx)
|
||||||
{
|
{
|
||||||
if (ns_ctx->entry->type == ENTRY_TYPE_AIO_FILE) {
|
return ns_ctx->entry->fn_table->init_ns_worker_ctx(ns_ctx);
|
||||||
#ifdef HAVE_LIBAIO
|
|
||||||
ns_ctx->u.aio.events = calloc(g_queue_depth, sizeof(struct io_event));
|
|
||||||
if (!ns_ctx->u.aio.events) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ns_ctx->u.aio.ctx = 0;
|
|
||||||
if (io_setup(g_queue_depth, &ns_ctx->u.aio.ctx) < 0) {
|
|
||||||
free(ns_ctx->u.aio.events);
|
|
||||||
perror("io_setup");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* TODO: If a controller has multiple namespaces, they could all use the same queue.
|
|
||||||
* For now, give each namespace/thread combination its own queue.
|
|
||||||
*/
|
|
||||||
struct spdk_nvme_io_qpair_opts opts;
|
|
||||||
|
|
||||||
spdk_nvme_ctrlr_get_default_io_qpair_opts(ns_ctx->entry->u.nvme.ctrlr, &opts, sizeof(opts));
|
|
||||||
if (opts.io_queue_requests < ns_ctx->entry->num_io_requests) {
|
|
||||||
opts.io_queue_requests = ns_ctx->entry->num_io_requests;
|
|
||||||
}
|
|
||||||
|
|
||||||
ns_ctx->u.nvme.qpair = spdk_nvme_ctrlr_alloc_io_qpair(ns_ctx->entry->u.nvme.ctrlr, &opts,
|
|
||||||
sizeof(opts));
|
|
||||||
if (!ns_ctx->u.nvme.qpair) {
|
|
||||||
printf("ERROR: spdk_nvme_ctrlr_alloc_io_qpair failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cleanup_ns_worker_ctx(struct ns_worker_ctx *ns_ctx)
|
cleanup_ns_worker_ctx(struct ns_worker_ctx *ns_ctx)
|
||||||
{
|
{
|
||||||
if (ns_ctx->entry->type == ENTRY_TYPE_AIO_FILE) {
|
ns_ctx->entry->fn_table->cleanup_ns_worker_ctx(ns_ctx);
|
||||||
#ifdef HAVE_LIBAIO
|
|
||||||
io_destroy(ns_ctx->u.aio.ctx);
|
|
||||||
free(ns_ctx->u.aio.events);
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
spdk_nvme_ctrlr_free_io_qpair(ns_ctx->u.nvme.qpair);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
Loading…
Reference in New Issue
Block a user