From ff3c2e3c846edcc11029c3f7f8e3bb13f4a868e7 Mon Sep 17 00:00:00 2001 From: Shuhei Matsumoto Date: Wed, 16 Jan 2019 08:03:38 +0900 Subject: [PATCH] nvme_perf: Relocate functions only for NVMe to introduce abstraction Subsequent patches will introduce function pointer table for IO type depenedent operations. This patch doesn't cause any functional change and just tries to make them easier. Change-Id: Ib612be43b9cf4bbb620739b29913cd05151bc872 Signed-off-by: Shuhei Matsumoto Reviewed-on: https://review.gerrithub.io/c/439805 Tested-by: SPDK CI Jenkins Reviewed-by: wuzhouhui Reviewed-by: Paul Luse Reviewed-by: Jim Harris Reviewed-by: Changpeng Liu --- examples/nvme/perf/perf.c | 354 +++++++++++++++++++------------------- 1 file changed, 177 insertions(+), 177 deletions(-) diff --git a/examples/nvme/perf/perf.c b/examples/nvme/perf/perf.c index 6f5c8b6e3..281f50a0b 100644 --- a/examples/nvme/perf/perf.c +++ b/examples/nvme/perf/perf.c @@ -199,183 +199,6 @@ static int g_aio_optind; /* Index of first AIO filename in argv */ static void task_complete(struct perf_task *task); -static void -register_ns(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns) -{ - struct ns_entry *entry; - const struct spdk_nvme_ctrlr_data *cdata; - uint32_t max_xfer_size, entries; - struct spdk_nvme_io_qpair_opts opts; - - cdata = spdk_nvme_ctrlr_get_data(ctrlr); - - if (!spdk_nvme_ns_is_active(ns)) { - printf("Controller %-20.20s (%-20.20s): Skipping inactive NS %u\n", - cdata->mn, cdata->sn, - spdk_nvme_ns_get_id(ns)); - g_warn = true; - return; - } - - if (spdk_nvme_ns_get_size(ns) < g_io_size_bytes || - spdk_nvme_ns_get_sector_size(ns) > g_io_size_bytes) { - printf("WARNING: controller %-20.20s (%-20.20s) ns %u has invalid " - "ns size %" PRIu64 " / block size %u for I/O size %u\n", - cdata->mn, cdata->sn, spdk_nvme_ns_get_id(ns), - spdk_nvme_ns_get_size(ns), spdk_nvme_ns_get_sector_size(ns), g_io_size_bytes); - g_warn = true; - return; - } - - max_xfer_size = spdk_nvme_ns_get_max_io_xfer_size(ns); - spdk_nvme_ctrlr_get_default_io_qpair_opts(ctrlr, &opts, sizeof(opts)); - /* NVMe driver may add additional entries based on - * stripe size and maximum transfer size, we assume - * 1 more entry be used for stripe. - */ - entries = (g_io_size_bytes - 1) / max_xfer_size + 2; - if ((g_queue_depth * entries) > opts.io_queue_size) { - printf("controller IO queue size %u less than required\n", - opts.io_queue_size); - printf("Consider using lower queue depth or small IO size because " - "IO requests may be queued at the NVMe driver.\n"); - g_warn = true; - } - - entry = calloc(1, sizeof(struct ns_entry)); - if (entry == NULL) { - perror("ns_entry malloc"); - exit(1); - } - - entry->type = ENTRY_TYPE_NVME_NS; - entry->u.nvme.ctrlr = ctrlr; - entry->u.nvme.ns = ns; - entry->num_io_requests = entries; - - entry->size_in_ios = spdk_nvme_ns_get_size(ns) / - g_io_size_bytes; - entry->io_size_blocks = g_io_size_bytes / spdk_nvme_ns_get_sector_size(ns); - - if (spdk_nvme_ns_get_flags(ns) & SPDK_NVME_NS_DPS_PI_SUPPORTED) { - entry->io_flags = g_metacfg_pract_flag | g_metacfg_prchk_flags; - } - - if (g_max_io_md_size < spdk_nvme_ns_get_md_size(ns)) { - g_max_io_md_size = spdk_nvme_ns_get_md_size(ns); - } - - if (g_max_io_size_blocks < entry->io_size_blocks) { - g_max_io_size_blocks = entry->io_size_blocks; - } - - entry->nsdata = spdk_nvme_ns_get_data(ns); - - snprintf(entry->name, 44, "%-20.20s (%-20.20s)", cdata->mn, cdata->sn); - - g_num_namespaces++; - entry->next = g_namespaces; - g_namespaces = entry; -} - -static void -unregister_namespaces(void) -{ - struct ns_entry *entry = g_namespaces; - - while (entry) { - struct ns_entry *next = entry->next; - free(entry); - entry = next; - } -} - -static void -enable_latency_tracking_complete(void *cb_arg, const struct spdk_nvme_cpl *cpl) -{ - if (spdk_nvme_cpl_is_error(cpl)) { - printf("enable_latency_tracking_complete failed\n"); - } - g_outstanding_commands--; -} - -static void -set_latency_tracking_feature(struct spdk_nvme_ctrlr *ctrlr, bool enable) -{ - int res; - union spdk_nvme_intel_feat_latency_tracking latency_tracking; - - if (enable) { - latency_tracking.bits.enable = 0x01; - } else { - latency_tracking.bits.enable = 0x00; - } - - res = spdk_nvme_ctrlr_cmd_set_feature(ctrlr, SPDK_NVME_INTEL_FEAT_LATENCY_TRACKING, - latency_tracking.raw, 0, NULL, 0, enable_latency_tracking_complete, NULL); - if (res) { - printf("fail to allocate nvme request.\n"); - return; - } - g_outstanding_commands++; - - while (g_outstanding_commands) { - spdk_nvme_ctrlr_process_admin_completions(ctrlr); - } -} - -static void -register_ctrlr(struct spdk_nvme_ctrlr *ctrlr, struct trid_entry *trid_entry) -{ - struct spdk_nvme_ns *ns; - struct ctrlr_entry *entry = malloc(sizeof(struct ctrlr_entry)); - const struct spdk_nvme_ctrlr_data *cdata = spdk_nvme_ctrlr_get_data(ctrlr); - uint32_t nsid; - - if (entry == NULL) { - perror("ctrlr_entry malloc"); - exit(1); - } - - entry->latency_page = spdk_dma_zmalloc(sizeof(struct spdk_nvme_intel_rw_latency_page), - 4096, NULL); - if (entry->latency_page == NULL) { - printf("Allocation error (latency page)\n"); - exit(1); - } - - snprintf(entry->name, sizeof(entry->name), "%-20.20s (%-20.20s)", cdata->mn, cdata->sn); - - entry->ctrlr = ctrlr; - entry->next = g_controllers; - g_controllers = entry; - - if (g_latency_ssd_tracking_enable && - spdk_nvme_ctrlr_is_feature_supported(ctrlr, SPDK_NVME_INTEL_FEAT_LATENCY_TRACKING)) { - set_latency_tracking_feature(ctrlr, true); - } - - if (trid_entry->nsid == 0) { - for (nsid = spdk_nvme_ctrlr_get_first_active_ns(ctrlr); - nsid != 0; nsid = spdk_nvme_ctrlr_get_next_active_ns(ctrlr, nsid)) { - ns = spdk_nvme_ctrlr_get_ns(ctrlr, nsid); - if (ns == NULL) { - continue; - } - register_ns(ctrlr, ns); - } - } else { - ns = spdk_nvme_ctrlr_get_ns(ctrlr, trid_entry->nsid); - if (!ns) { - perror("Namespace does not exist."); - exit(1); - } - - register_ns(ctrlr, ns); - } - -} - #if HAVE_LIBAIO static int aio_submit(io_context_t aio_ctx, struct iocb *iocb, int fd, enum io_iocb_cmd cmd, void *buf, @@ -636,6 +459,183 @@ 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 +register_ns(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns) +{ + struct ns_entry *entry; + const struct spdk_nvme_ctrlr_data *cdata; + uint32_t max_xfer_size, entries; + struct spdk_nvme_io_qpair_opts opts; + + cdata = spdk_nvme_ctrlr_get_data(ctrlr); + + if (!spdk_nvme_ns_is_active(ns)) { + printf("Controller %-20.20s (%-20.20s): Skipping inactive NS %u\n", + cdata->mn, cdata->sn, + spdk_nvme_ns_get_id(ns)); + g_warn = true; + return; + } + + if (spdk_nvme_ns_get_size(ns) < g_io_size_bytes || + spdk_nvme_ns_get_sector_size(ns) > g_io_size_bytes) { + printf("WARNING: controller %-20.20s (%-20.20s) ns %u has invalid " + "ns size %" PRIu64 " / block size %u for I/O size %u\n", + cdata->mn, cdata->sn, spdk_nvme_ns_get_id(ns), + spdk_nvme_ns_get_size(ns), spdk_nvme_ns_get_sector_size(ns), g_io_size_bytes); + g_warn = true; + return; + } + + max_xfer_size = spdk_nvme_ns_get_max_io_xfer_size(ns); + spdk_nvme_ctrlr_get_default_io_qpair_opts(ctrlr, &opts, sizeof(opts)); + /* NVMe driver may add additional entries based on + * stripe size and maximum transfer size, we assume + * 1 more entry be used for stripe. + */ + entries = (g_io_size_bytes - 1) / max_xfer_size + 2; + if ((g_queue_depth * entries) > opts.io_queue_size) { + printf("controller IO queue size %u less than required\n", + opts.io_queue_size); + printf("Consider using lower queue depth or small IO size because " + "IO requests may be queued at the NVMe driver.\n"); + g_warn = true; + } + + entry = calloc(1, sizeof(struct ns_entry)); + if (entry == NULL) { + perror("ns_entry malloc"); + exit(1); + } + + entry->type = ENTRY_TYPE_NVME_NS; + entry->u.nvme.ctrlr = ctrlr; + entry->u.nvme.ns = ns; + entry->num_io_requests = entries; + + entry->size_in_ios = spdk_nvme_ns_get_size(ns) / + g_io_size_bytes; + entry->io_size_blocks = g_io_size_bytes / spdk_nvme_ns_get_sector_size(ns); + + if (spdk_nvme_ns_get_flags(ns) & SPDK_NVME_NS_DPS_PI_SUPPORTED) { + entry->io_flags = g_metacfg_pract_flag | g_metacfg_prchk_flags; + } + + if (g_max_io_md_size < spdk_nvme_ns_get_md_size(ns)) { + g_max_io_md_size = spdk_nvme_ns_get_md_size(ns); + } + + if (g_max_io_size_blocks < entry->io_size_blocks) { + g_max_io_size_blocks = entry->io_size_blocks; + } + + entry->nsdata = spdk_nvme_ns_get_data(ns); + + snprintf(entry->name, 44, "%-20.20s (%-20.20s)", cdata->mn, cdata->sn); + + g_num_namespaces++; + entry->next = g_namespaces; + g_namespaces = entry; +} + +static void +unregister_namespaces(void) +{ + struct ns_entry *entry = g_namespaces; + + while (entry) { + struct ns_entry *next = entry->next; + free(entry); + entry = next; + } +} + +static void +enable_latency_tracking_complete(void *cb_arg, const struct spdk_nvme_cpl *cpl) +{ + if (spdk_nvme_cpl_is_error(cpl)) { + printf("enable_latency_tracking_complete failed\n"); + } + g_outstanding_commands--; +} + +static void +set_latency_tracking_feature(struct spdk_nvme_ctrlr *ctrlr, bool enable) +{ + int res; + union spdk_nvme_intel_feat_latency_tracking latency_tracking; + + if (enable) { + latency_tracking.bits.enable = 0x01; + } else { + latency_tracking.bits.enable = 0x00; + } + + res = spdk_nvme_ctrlr_cmd_set_feature(ctrlr, SPDK_NVME_INTEL_FEAT_LATENCY_TRACKING, + latency_tracking.raw, 0, NULL, 0, enable_latency_tracking_complete, NULL); + if (res) { + printf("fail to allocate nvme request.\n"); + return; + } + g_outstanding_commands++; + + while (g_outstanding_commands) { + spdk_nvme_ctrlr_process_admin_completions(ctrlr); + } +} + +static void +register_ctrlr(struct spdk_nvme_ctrlr *ctrlr, struct trid_entry *trid_entry) +{ + struct spdk_nvme_ns *ns; + struct ctrlr_entry *entry = malloc(sizeof(struct ctrlr_entry)); + const struct spdk_nvme_ctrlr_data *cdata = spdk_nvme_ctrlr_get_data(ctrlr); + uint32_t nsid; + + if (entry == NULL) { + perror("ctrlr_entry malloc"); + exit(1); + } + + entry->latency_page = spdk_dma_zmalloc(sizeof(struct spdk_nvme_intel_rw_latency_page), + 4096, NULL); + if (entry->latency_page == NULL) { + printf("Allocation error (latency page)\n"); + exit(1); + } + + snprintf(entry->name, sizeof(entry->name), "%-20.20s (%-20.20s)", cdata->mn, cdata->sn); + + entry->ctrlr = ctrlr; + entry->next = g_controllers; + g_controllers = entry; + + if (g_latency_ssd_tracking_enable && + spdk_nvme_ctrlr_is_feature_supported(ctrlr, SPDK_NVME_INTEL_FEAT_LATENCY_TRACKING)) { + set_latency_tracking_feature(ctrlr, true); + } + + if (trid_entry->nsid == 0) { + for (nsid = spdk_nvme_ctrlr_get_first_active_ns(ctrlr); + nsid != 0; nsid = spdk_nvme_ctrlr_get_next_active_ns(ctrlr, nsid)) { + ns = spdk_nvme_ctrlr_get_ns(ctrlr, nsid); + if (ns == NULL) { + continue; + } + register_ns(ctrlr, ns); + } + } else { + ns = spdk_nvme_ctrlr_get_ns(ctrlr, trid_entry->nsid); + if (!ns) { + perror("Namespace does not exist."); + exit(1); + } + + register_ns(ctrlr, ns); + } + +} + static __thread unsigned int seed = 0; static void