diff --git a/app/nvmf_tgt/nvmf_tgt.c b/app/nvmf_tgt/nvmf_tgt.c index ecb634360..baec45b2e 100644 --- a/app/nvmf_tgt/nvmf_tgt.c +++ b/app/nvmf_tgt/nvmf_tgt.c @@ -372,9 +372,8 @@ This is the main file. \msc - c_runtime [label="C Runtime"], dpdk [label="DPDK"], nvmf [label="NVMf target"]; + c_runtime [label="C Runtime"], nvmf [label="NVMf target"]; c_runtime=>nvmf [label="main()"]; - nvmf=> [label="rte_eal_init()"]; nvmf=>nvmf [label="spdk_app_init()"]; nvmf=>nvmf [label="spdk_event_allocate()"]; nvmf=>nvmf [label="spdk_app_start()"]; diff --git a/examples/ioat/perf/perf.c b/examples/ioat/perf/perf.c index 12d970dac..ba756bacc 100644 --- a/examples/ioat/perf/perf.c +++ b/examples/ioat/perf/perf.c @@ -398,22 +398,12 @@ work_fn(void *arg) static int init(void) { - char *core_mask_conf; + struct spdk_env_opts opts; - core_mask_conf = spdk_sprintf_alloc("-c %s", g_user_config.core_mask); - if (!core_mask_conf) { - return 1; - } - - char *ealargs[] = {"perf", core_mask_conf, "-n 4"}; - - if (rte_eal_init(sizeof(ealargs) / sizeof(ealargs[0]), ealargs) < 0) { - free(core_mask_conf); - fprintf(stderr, "Could not init eal\n"); - return 1; - } - - free(core_mask_conf); + spdk_env_opts_init(&opts); + opts.name = "perf"; + opts.core_mask = g_user_config.core_mask; + spdk_env_init(&opts); return 0; } diff --git a/examples/ioat/verify/verify.c b/examples/ioat/verify/verify.c index 6ac538867..9a5948c68 100644 --- a/examples/ioat/verify/verify.c +++ b/examples/ioat/verify/verify.c @@ -379,21 +379,12 @@ init_src_buffer(void) static int init(void) { - char *core_mask_conf; + struct spdk_env_opts opts; - core_mask_conf = spdk_sprintf_alloc("-c %s", g_user_config.core_mask); - if (!core_mask_conf) { - return 1; - } - - char *ealargs[] = {"verify", core_mask_conf, "-n 4"}; - if (rte_eal_init(sizeof(ealargs) / sizeof(ealargs[0]), ealargs) < 0) { - free(core_mask_conf); - fprintf(stderr, "Could not init eal\n"); - return 1; - } - - free(core_mask_conf); + spdk_env_opts_init(&opts); + opts.name = "verify"; + opts.core_mask = g_user_config.core_mask; + spdk_env_init(&opts); if (init_src_buffer() != 0) { fprintf(stderr, "Could not init src buffer\n"); diff --git a/examples/nvme/arbitration/arbitration.c b/examples/nvme/arbitration/arbitration.c index f8f7e6b36..aa9536d02 100644 --- a/examples/nvme/arbitration/arbitration.c +++ b/examples/nvme/arbitration/arbitration.c @@ -133,6 +133,7 @@ static struct arb_context g_arbitration = { .arbitration_config = 0, .io_size_bytes = 131072, .max_completions = 0, + /* Default 4 cores for urgent/high/medium/low */ .core_mask = "0xf", .workload_type = "randrw", }; @@ -1080,18 +1081,6 @@ set_arb_feature(struct spdk_nvme_ctrlr *ctrlr) return 0; } - -static char *ealargs[] = { - "arb", - "-c 0xf", /* This must be the second parameter. It is overwritten by index in main(). */ - "-n 4", - "--proc-type=auto", -#ifdef __linux__ - "--base-virtaddr=0x1000000000", - "", /* May be replaced by --file-prefix */ -#endif -}; - int main(int argc, char **argv) { @@ -1099,45 +1088,18 @@ main(int argc, char **argv) struct worker_thread *worker; char task_pool_name[30]; uint32_t task_count; - size_t argcount; - char *core_mask = NULL; - char *file_prefix = NULL; + struct spdk_env_opts opts; rc = parse_args(argc, argv); if (rc != 0) { return rc; } - /* Default 4 cores for (urgent / high / medium / low) 4 kinds of queues respectively */ - ealargs[1] = core_mask = spdk_sprintf_alloc("-c %s", g_arbitration.core_mask); - if (ealargs[1] == NULL) { - perror("ealargs spdk_sprintf_alloc"); - return 1; - } - - - argcount = (sizeof(ealargs) / sizeof(ealargs[0])) - 1; - -#ifdef __linux__ - if (g_arbitration.shm_id >= 0) { - ealargs[5] = file_prefix = spdk_sprintf_alloc("--file-prefix=spdk%d", - g_arbitration.shm_id); - argcount++; - } -#endif - - rc = rte_eal_init(argcount, ealargs); - - free(core_mask); - - if (file_prefix) { - free(file_prefix); - } - - if (rc < 0) { - fprintf(stderr, "could not initialize dpdk\n"); - return 1; - } + spdk_env_opts_init(&opts); + opts.name = "arb"; + opts.core_mask = g_arbitration.core_mask; + opts.shm_id = g_arbitration.shm_id; + spdk_env_init(&opts); g_arbitration.tsc_rate = spdk_get_ticks_hz(); diff --git a/examples/nvme/fio_plugin/fio_plugin.c b/examples/nvme/fio_plugin/fio_plugin.c index cfc64eb94..23811266e 100644 --- a/examples/nvme/fio_plugin/fio_plugin.c +++ b/examples/nvme/fio_plugin/fio_plugin.c @@ -37,9 +37,6 @@ #include #include -#include "rte_config.h" -#include "rte_eal.h" - #include "spdk/nvme.h" #include "spdk/env.h" #include "spdk/string.h" @@ -175,19 +172,13 @@ attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid, } } -static char *ealargs[] = { - "fio", - "-n 4", - "--proc-type=auto", -}; - /* Called once at initialization. This is responsible for gathering the size of * each "file", which in our case are in the form * "05:00.0/0" (PCI bus:device.function/NVMe NSID) */ static int spdk_fio_setup(struct thread_data *td) { - int rc; struct spdk_fio_thread *fio_thread; + struct spdk_env_opts opts; fio_thread = calloc(1, sizeof(*fio_thread)); assert(fio_thread != NULL); @@ -198,11 +189,9 @@ static int spdk_fio_setup(struct thread_data *td) fio_thread->iocq = calloc(td->o.iodepth + 1, sizeof(struct io_u *)); assert(fio_thread->iocq != NULL); - rc = rte_eal_init(sizeof(ealargs) / sizeof(ealargs[0]), ealargs); - if (rc < 0) { - fprintf(stderr, "could not initialize dpdk\n"); - return 1; - } + spdk_env_opts_init(&opts); + opts.name = "fio"; + spdk_env_init(&opts); /* Enumerate all of the controllers */ if (spdk_nvme_probe(NULL, td, probe_cb, attach_cb, NULL) != 0) { diff --git a/examples/nvme/hello_world/hello_world.c b/examples/nvme/hello_world/hello_world.c index 6abe1d83d..994be679e 100644 --- a/examples/nvme/hello_world/hello_world.c +++ b/examples/nvme/hello_world/hello_world.c @@ -36,9 +36,6 @@ #include #include -#include -#include - #include "spdk/nvme.h" #include "spdk/env.h" @@ -304,32 +301,20 @@ cleanup(void) } } -static char *ealargs[] = { - "hello_world", - "-c 0x1", - "-n 4", - "--proc-type=auto", -}; - int main(int argc, char **argv) { int rc; + struct spdk_env_opts opts; /* - * By default, the SPDK NVMe driver uses DPDK for huge page-based - * memory management and NVMe request buffer pools. Huge pages can - * be either 2MB or 1GB in size (instead of 4KB) and are pinned in - * memory. Pinned memory is important to ensure DMA operations - * never target swapped out memory. + * SPDK relies on an abstraction around the local environment + * named env that handles memory allocation and PCI device operations. + * This library must be initialized first. * - * So first we must initialize DPDK. "-c 0x1" indicates to only use - * core 0. */ - rc = rte_eal_init(sizeof(ealargs) / sizeof(ealargs[0]), ealargs); - if (rc < 0) { - fprintf(stderr, "could not initialize dpdk\n"); - return 1; - } + spdk_env_opts_init(&opts); + opts.name = "hello_world"; + spdk_env_init(&opts); printf("Initializing NVMe Controllers\n"); diff --git a/examples/nvme/hotplug/hotplug.c b/examples/nvme/hotplug/hotplug.c index 1cf11bdf7..6948f3143 100644 --- a/examples/nvme/hotplug/hotplug.c +++ b/examples/nvme/hotplug/hotplug.c @@ -81,6 +81,7 @@ static int g_expected_insert_times = -1; static int g_expected_removal_times = -1; static int g_insert_times; static int g_removal_times; +static int g_shm_id = -1; static void task_complete(struct perf_task *task); @@ -376,7 +377,8 @@ static void usage(char *program_name) { printf("%s options", program_name); printf("\n"); - printf("\t[-i expected hot insert times]\n"); + printf("\t[-i shm id (optional)]\n"); + printf("\t[-n expected hot insert times]\n"); printf("\t[-r expected hot removal times]\n"); printf("\t[-t time in seconds]\n"); } @@ -389,9 +391,12 @@ parse_args(int argc, char **argv) /* default value*/ g_time_in_sec = 0; - while ((op = getopt(argc, argv, "i:r:t:")) != -1) { + while ((op = getopt(argc, argv, "i:n:r:t:")) != -1) { switch (op) { case 'i': + g_shm_id = atoi(optarg); + break; + case 'n': g_expected_insert_times = atoi(optarg); break; case 'r': @@ -430,26 +435,23 @@ register_controllers(void) return 0; } -static char *ealargs[] = { - "hotplug", - "-c 0x1", - "-n 4", -}; - int main(int argc, char **argv) { int rc; + struct spdk_env_opts opts; rc = parse_args(argc, argv); if (rc != 0) { return rc; } - rc = rte_eal_init(sizeof(ealargs) / sizeof(ealargs[0]), ealargs); - if (rc < 0) { - fprintf(stderr, "could not initialize dpdk\n"); - return 1; + spdk_env_opts_init(&opts); + opts.name = "hotplug"; + opts.core_mask = "0x1"; + if (g_shm_id > -1) { + opts.shm_id = g_shm_id; } + spdk_env_init(&opts); task_pool = rte_mempool_create("task_pool", 8192, sizeof(struct perf_task), diff --git a/examples/nvme/identify/identify.c b/examples/nvme/identify/identify.c index a725952bc..ebe16f686 100644 --- a/examples/nvme/identify/identify.c +++ b/examples/nvme/identify/identify.c @@ -950,31 +950,21 @@ attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid, spdk_nvme_detach(ctrlr); } -static const char *ealargs[] = { - "identify", - "-c 0x1", - "-n 4", - "-m 512", - "--proc-type=auto", -}; - int main(int argc, char **argv) { int rc; + struct spdk_env_opts opts; + + spdk_env_opts_init(&opts); + opts.name = "identify"; + opts.core_mask = "0x1"; + spdk_env_init(&opts); rc = parse_args(argc, argv); if (rc != 0) { return rc; } - rc = rte_eal_init(sizeof(ealargs) / sizeof(ealargs[0]), - (char **)(void *)(uintptr_t)ealargs); - - if (rc < 0) { - fprintf(stderr, "could not initialize dpdk\n"); - exit(1); - } - rc = 0; if (spdk_nvme_probe(&g_trid, NULL, probe_cb, attach_cb, NULL) != 0) { fprintf(stderr, "spdk_nvme_probe() failed\n"); diff --git a/examples/nvme/nvme_manage/nvme_manage.c b/examples/nvme/nvme_manage/nvme_manage.c index 1bdfebd0e..f04f6222e 100644 --- a/examples/nvme/nvme_manage/nvme_manage.c +++ b/examples/nvme/nvme_manage/nvme_manage.c @@ -138,13 +138,6 @@ attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid, } } -static const char *ealargs[] = { - "nvme_manage", - "-c 0x1", - "-n 4", - "--proc-type=auto", -}; - static void usage(void) { printf("NVMe Management Options"); @@ -843,15 +836,13 @@ update_firmware_image(void) int main(int argc, char **argv) { - int rc, i; + int i; + struct spdk_env_opts opts; - rc = rte_eal_init(sizeof(ealargs) / sizeof(ealargs[0]), - (char **)(void *)(uintptr_t)ealargs); - - if (rc < 0) { - fprintf(stderr, "could not initialize dpdk\n"); - exit(1); - } + spdk_env_opts_init(&opts); + opts.name = "nvme_manage"; + opts.core_mask = "0x1"; + spdk_env_init(&opts); if (spdk_nvme_probe(NULL, NULL, probe_cb, attach_cb, NULL) != 0) { fprintf(stderr, "spdk_nvme_probe() failed\n"); @@ -917,5 +908,5 @@ int main(int argc, char **argv) spdk_nvme_detach(dev->ctrlr); } - return rc; + return 0; } diff --git a/examples/nvme/perf/perf.c b/examples/nvme/perf/perf.c index b1f6a2a81..994157122 100644 --- a/examples/nvme/perf/perf.c +++ b/examples/nvme/perf/perf.c @@ -1193,71 +1193,30 @@ associate_workers_with_ns(void) return 0; } -static char *ealargs[] = { - "perf", - "-c 0x1", /* This must be the second parameter. It is overwritten by index in main(). */ - "-n 4", - "-m 512", /* This can be overwritten by index in main(). */ - "--proc-type=auto", -#ifdef __linux__ - "--base-virtaddr=0x1000000000", - "", /* May be replaced by --file-prefix */ -#endif - -}; - int main(int argc, char **argv) { int rc; struct worker_thread *worker; char task_pool_name[30]; uint32_t task_count; - size_t argcount; - char *core_mask = NULL; - char *mem_size = NULL; - char *file_prefix = NULL; + struct spdk_env_opts opts; rc = parse_args(argc, argv); if (rc != 0) { return rc; } - ealargs[1] = core_mask = spdk_sprintf_alloc("-c %s", g_core_mask ? g_core_mask : "0x1"); - if (ealargs[1] == NULL) { - perror("ealargs spdk_sprintf_alloc"); - return 1; + spdk_env_opts_init(&opts); + opts.name = "perf"; + opts.shm_id = g_shm_id; + if (g_core_mask) { + opts.core_mask = g_core_mask; } - ealargs[3] = mem_size = spdk_sprintf_alloc("-m %d", g_dpdk_mem ? g_dpdk_mem : 512); - if (ealargs[3] == NULL) { - free(ealargs[1]); - perror("ealargs spdk_sprintf_alloc"); - return 1; - } - - argcount = (sizeof(ealargs) / sizeof(ealargs[0])) - 1; - -#ifdef __linux__ - if (g_shm_id >= 0) { - ealargs[6] = file_prefix = spdk_sprintf_alloc("--file-prefix=spdk%d", - g_shm_id); - argcount++; - } -#endif - - rc = rte_eal_init(argcount, ealargs); - - free(core_mask); - free(mem_size); - - if (file_prefix) { - free(file_prefix); - } - - if (rc < 0) { - fprintf(stderr, "could not initialize dpdk\n"); - return 1; + if (g_dpdk_mem) { + opts.dpdk_mem_size = g_dpdk_mem; } + spdk_env_init(&opts); g_tsc_rate = spdk_get_ticks_hz(); diff --git a/examples/nvme/reserve/reserve.c b/examples/nvme/reserve/reserve.c index 90a329c9f..687018155 100644 --- a/examples/nvme/reserve/reserve.c +++ b/examples/nvme/reserve/reserve.c @@ -380,25 +380,16 @@ attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid, dev->ctrlr = ctrlr; } -static const char *ealargs[] = { - "reserve", - "-c 0x1", - "-n 4", - "--proc-type=auto", -}; - int main(int argc, char **argv) { - struct dev *iter; - int rc, i; + struct dev *iter; + int rc, i; + struct spdk_env_opts opts; - rc = rte_eal_init(sizeof(ealargs) / sizeof(ealargs[0]), - (char **)(void *)(uintptr_t)ealargs); - - if (rc < 0) { - fprintf(stderr, "could not initialize dpdk\n"); - exit(1); - } + spdk_env_opts_init(&opts); + opts.name = "reserve"; + opts.core_mask = "0x1"; + spdk_env_init(&opts); if (spdk_nvme_probe(NULL, NULL, probe_cb, attach_cb, NULL) != 0) { fprintf(stderr, "spdk_nvme_probe() failed\n"); diff --git a/include/spdk/env.h b/include/spdk/env.h index 35b2a3ce8..7fc65c3c1 100644 --- a/include/spdk/env.h +++ b/include/spdk/env.h @@ -51,6 +51,29 @@ extern "C" { struct spdk_pci_device; +/** + * \brief Environment initialization options + */ +struct spdk_env_opts { + const char *name; + const char *core_mask; + int shm_id; + int dpdk_mem_channel; + int dpdk_master_core; + int dpdk_mem_size; +}; + +/** + * \brief Initialize the default value of opts +*/ +void spdk_env_opts_init(struct spdk_env_opts *opts); + +/** + * \brief Initialize the environment library. This must be called prior to using + * any other functions in this library. +*/ +void spdk_env_init(const struct spdk_env_opts *opts); + /** * Allocate a pinned, physically contiguous memory buffer with the * given size and alignment. diff --git a/include/spdk/event.h b/include/spdk/event.h index cf412dbae..853f12b76 100644 --- a/include/spdk/event.h +++ b/include/spdk/event.h @@ -81,8 +81,8 @@ struct spdk_app_opts { spdk_sighandler_t usr1_handler; bool enable_coredump; - uint32_t dpdk_mem_channel; - uint32_t dpdk_master_core; + int dpdk_mem_channel; + int dpdk_master_core; int dpdk_mem_size; /* The maximum latency allowed when passing an event @@ -98,11 +98,6 @@ struct spdk_app_opts { */ void spdk_app_opts_init(struct spdk_app_opts *opts); -/** - * \brief Initialize DPDK via opts. -*/ -void spdk_dpdk_framework_init(struct spdk_app_opts *opts); - /** * \brief Initialize an application to use the event framework. This must be called prior to using * any other functions in this library. diff --git a/lib/env_dpdk/Makefile b/lib/env_dpdk/Makefile index 250b533f3..484624c58 100644 --- a/lib/env_dpdk/Makefile +++ b/lib/env_dpdk/Makefile @@ -34,8 +34,8 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..) include $(SPDK_ROOT_DIR)/mk/spdk.common.mk -CFLAGS += $(DPDK_INC) -C_SRCS = env.c pci.c vtophys.c +CFLAGS += $(ENV_CFLAGS) +C_SRCS = env.c pci.c vtophys.c init.c C_SRCS += pci_nvme.c pci_ioat.c LIBNAME = env_dpdk diff --git a/lib/env_dpdk/init.c b/lib/env_dpdk/init.c new file mode 100644 index 000000000..5a904369f --- /dev/null +++ b/lib/env_dpdk/init.c @@ -0,0 +1,312 @@ +/*- + * BSD LICENSE + * + * Copyright (c) Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spdk/env.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define SPDK_ENV_DPDK_DEFAULT_NAME "spdk" +#define SPDK_ENV_DPDK_DEFAULT_SHM_ID -1 +#define SPDK_ENV_DPDK_DEFAULT_MEM_SIZE -1 +#define SPDK_ENV_DPDK_DEFAULT_MASTER_CORE -1 +#define SPDK_ENV_DPDK_DEFAULT_MEM_CHANNEL -1 +#define SPDK_ENV_DPDK_DEFAULT_CORE_MASK "0x1" + +static char * +_sprintf_alloc(const char *format, ...) +{ + va_list args; + va_list args_copy; + char *buf; + size_t bufsize; + int rc; + + va_start(args, format); + + /* Try with a small buffer first. */ + bufsize = 32; + + /* Limit maximum buffer size to something reasonable so we don't loop forever. */ + while (bufsize <= 1024 * 1024) { + buf = malloc(bufsize); + if (buf == NULL) { + va_end(args); + return NULL; + } + + va_copy(args_copy, args); + rc = vsnprintf(buf, bufsize, format, args_copy); + va_end(args_copy); + + /* + * If vsnprintf() returned a count within our current buffer size, we are done. + * The count does not include the \0 terminator, so rc == bufsize is not OK. + */ + if (rc >= 0 && (size_t)rc < bufsize) { + va_end(args); + return buf; + } + + /* + * vsnprintf() should return the required space, but some libc versions do not + * implement this correctly, so just double the buffer size and try again. + * + * We don't need the data in buf, so rather than realloc(), use free() and malloc() + * again to avoid a copy. + */ + free(buf); + bufsize *= 2; + } + + va_end(args); + return NULL; +} + +void +spdk_env_opts_init(struct spdk_env_opts *opts) +{ + if (!opts) { + return; + } + + memset(opts, 0, sizeof(*opts)); + + opts->name = SPDK_ENV_DPDK_DEFAULT_NAME; + opts->core_mask = SPDK_ENV_DPDK_DEFAULT_CORE_MASK; + opts->shm_id = SPDK_ENV_DPDK_DEFAULT_SHM_ID; + opts->dpdk_mem_size = SPDK_ENV_DPDK_DEFAULT_MEM_SIZE; + opts->dpdk_master_core = SPDK_ENV_DPDK_DEFAULT_MASTER_CORE; + opts->dpdk_mem_channel = SPDK_ENV_DPDK_DEFAULT_MEM_CHANNEL; +} + +static void +spdk_free_args(char **args, int argcount) +{ + int i; + + assert(args != NULL); + + for (i = 0; i < argcount; i++) { + assert(args[i] != NULL); + free(args[i]); + } + + free(args); +} + +static char ** +spdk_push_arg(char *args[], int *argcount, char *arg) +{ + char **tmp; + + if (arg == NULL) { + return NULL; + } + + tmp = realloc(args, sizeof(char *) * (*argcount + 1)); + if (tmp == NULL) { + spdk_free_args(args, *argcount); + return NULL; + } + + tmp[*argcount] = arg; + (*argcount)++; + + return tmp; +} + +static unsigned long long +spdk_get_coremask(const char *coremask) +{ + unsigned long long core_mask, max_coremask = 0; + int num_cores_online; + + num_cores_online = sysconf(_SC_NPROCESSORS_ONLN); + if (num_cores_online > 0) { + if (num_cores_online > RTE_MAX_LCORE) { + num_cores_online = RTE_MAX_LCORE; + } + if (num_cores_online >= 64) { + max_coremask = ~0ULL; + } else { + max_coremask = (1ULL << num_cores_online) - 1; + } + } + + core_mask = strtoull(coremask, NULL, 16); + core_mask &= max_coremask; + + return core_mask; +} + +static int +spdk_build_eal_cmdline(const struct spdk_env_opts *opts, char **out[]) +{ + unsigned long long core_mask; + int argcount = 0; + char **args; + + if (out == NULL) { + return -1; + } + + *out = NULL; + args = NULL; + + /* set the program name */ + args = spdk_push_arg(args, &argcount, _sprintf_alloc("%s", opts->name)); + if (args == NULL) { + return -1; + } + + /* set the coremask */ + core_mask = spdk_get_coremask(opts->core_mask); + if (core_mask == 0) { + spdk_free_args(args, argcount); + return -1; + } + args = spdk_push_arg(args, &argcount, _sprintf_alloc("-c %llx", core_mask)); + if (args == NULL) { + return -1; + } + + /* set the memory channel number */ + if (opts->dpdk_mem_channel > 0) { + args = spdk_push_arg(args, &argcount, _sprintf_alloc("-n %d", opts->dpdk_mem_channel)); + if (args == NULL) { + return -1; + } + } + + /* set the memory size */ + if (opts->dpdk_mem_size > 0) { + args = spdk_push_arg(args, &argcount, _sprintf_alloc("-m %d", opts->dpdk_mem_size)); + if (args == NULL) { + return -1; + } + } + + /* set the master core */ + if (opts->dpdk_master_core > 0) { + args = spdk_push_arg(args, &argcount, _sprintf_alloc("--master-lcore=%d", + opts->dpdk_master_core)); + if (args == NULL) { + return -1; + } + } + +#ifdef __linux__ + if (opts->shm_id < 0) { + args = spdk_push_arg(args, &argcount, _sprintf_alloc("--file-prefix=spdk_pid%d", + getpid())); + if (args == NULL) { + return -1; + } + } else { + args = spdk_push_arg(args, &argcount, _sprintf_alloc("--file-prefix=spdk%d", + opts->shm_id)); + if (args == NULL) { + return -1; + } + } + + /* set the base virtual address */ + args = spdk_push_arg(args, &argcount, _sprintf_alloc("--base-virtaddr=0x1000000000")); + if (args == NULL) { + return -1; + } + + /* set the process type */ + args = spdk_push_arg(args, &argcount, _sprintf_alloc("--proc-type=auto")); + if (args == NULL) { + return -1; + } +#endif + + *out = args; + + return argcount; +} + +void spdk_env_init(const struct spdk_env_opts *opts) +{ + char **args = NULL; + char **dpdk_args = NULL; + int argcount, i, rc; + + argcount = spdk_build_eal_cmdline(opts, &args); + if (argcount <= 0) { + fprintf(stderr, "Invalid arguments to initialize DPDK\n"); + exit(-1); + } + + printf("Starting Intel(R) DPDK initialization ... \n"); + printf("[ DPDK EAL parameters: "); + for (i = 0; i < argcount; i++) { + printf("%s ", args[i]); + } + printf("]\n"); + + /* DPDK rearranges the array we pass to it, so make a copy + * before passing so we can still free the individual strings + * correctly. + */ + dpdk_args = calloc(argcount, sizeof(char *)); + memcpy(dpdk_args, args, sizeof(char *) * argcount); + + fflush(stdout); + rc = rte_eal_init(argcount, dpdk_args); + + spdk_free_args(args, argcount); + free(dpdk_args); + + if (rc < 0) { + fprintf(stderr, "Failed to initialize DPDK\n"); + exit(-1); + } +} diff --git a/lib/env_dpdk/vtophys.c b/lib/env_dpdk/vtophys.c index fdba1044d..266aab9e1 100644 --- a/lib/env_dpdk/vtophys.c +++ b/lib/env_dpdk/vtophys.c @@ -38,7 +38,6 @@ #include #include -#include #include #include "spdk/env.h" diff --git a/lib/event/Makefile b/lib/event/Makefile index 9606b46b6..0e6419fd1 100644 --- a/lib/event/Makefile +++ b/lib/event/Makefile @@ -36,7 +36,7 @@ include $(SPDK_ROOT_DIR)/mk/spdk.common.mk CFLAGS += $(ENV_CFLAGS) LIBNAME = event -C_SRCS = app.c dpdk_init.c reactor.c subsystem.c +C_SRCS = app.c reactor.c subsystem.c DIRS-y = rpc diff --git a/lib/event/app.c b/lib/event/app.c index 295e39cbd..1125ad461 100644 --- a/lib/event/app.c +++ b/lib/event/app.c @@ -49,6 +49,7 @@ #include #include +#include "spdk/env.h" #include "spdk/log.h" #include "spdk/conf.h" #include "spdk/trace.h" @@ -56,9 +57,9 @@ #define SPDK_APP_DEFAULT_LOG_FACILITY "local7" #define SPDK_APP_DEFAULT_LOG_PRIORITY "info" -#define SPDK_APP_DPDK_DEFAULT_MEM_SIZE 2048 -#define SPDK_APP_DPDK_DEFAULT_MASTER_CORE 0 -#define SPDK_APP_DPDK_DEFAULT_MEM_CHANNEL 4 +#define SPDK_APP_DPDK_DEFAULT_MEM_SIZE -1 +#define SPDK_APP_DPDK_DEFAULT_MASTER_CORE -1 +#define SPDK_APP_DPDK_DEFAULT_MEM_CHANNEL -1 #define SPDK_APP_DPDK_DEFAULT_CORE_MASK "0x1" /* Add enough here to append ".pid" plus 2 digit instance ID */ @@ -243,6 +244,7 @@ spdk_app_init(struct spdk_app_opts *opts) int rc; uint64_t tpoint_group_mask; char *end; + struct spdk_env_opts env_opts = {}; if (opts->enable_coredump) { struct rlimit core_limits; @@ -279,6 +281,13 @@ spdk_app_init(struct spdk_app_opts *opts) opts->shm_id = getpid(); } + if (opts->shm_id == -1) { + sp = spdk_conf_find_section(config, "Global"); + if (sp != NULL) { + opts->shm_id = spdk_conf_section_get_intval(sp, "MultiprocessGroupID"); + } + } + memset(&g_spdk_app, 0, sizeof(g_spdk_app)); g_spdk_app.config = config; g_spdk_app.shm_id = opts->shm_id; @@ -324,7 +333,16 @@ spdk_app_init(struct spdk_app_opts *opts) } } - spdk_dpdk_framework_init(opts); + spdk_env_opts_init(&env_opts); + + env_opts.name = opts->name; + env_opts.core_mask = opts->reactor_mask; + env_opts.shm_id = opts->shm_id; + env_opts.dpdk_mem_channel = opts->dpdk_mem_channel; + env_opts.dpdk_master_core = opts->dpdk_master_core; + env_opts.dpdk_mem_size = opts->dpdk_mem_size; + + spdk_env_init(&env_opts); /* * If mask not specified on command line or in configuration file, diff --git a/lib/event/dpdk_init.c b/lib/event/dpdk_init.c deleted file mode 100644 index 9ed068cde..000000000 --- a/lib/event/dpdk_init.c +++ /dev/null @@ -1,211 +0,0 @@ -/*- - * BSD LICENSE - * - * Copyright (c) Intel Corporation. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "spdk/event.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "spdk/string.h" - -enum dpdk_eal_args { - EAL_PROGNAME_ARG = 0, - EAL_COREMASK_ARG, - EAL_MEMCHAN_ARG, - EAL_MEMSIZE_ARG, - EAL_MASTER_CORE_ARG, - EAL_FILE_PREFIX_ARG, - EAL_PROC_TYPE_ARG, - EAL_ARG_COUNT -}; - -/* g_arg_strings contains the original pointers allocated via - * spdk_sprintf_alloc(). These pointers are copied to g_ealargs - * for passing to DPDK rte_eal_init(). Since DPDK may modify the - * pointer values, we use g_arg_strings() to free the strings after - * rte_eal_init() completes. - */ -static char *g_arg_strings[EAL_ARG_COUNT]; -static char *g_ealargs[EAL_ARG_COUNT]; - -static void -spdk_free_ealargs(void) -{ - int i; - - for (i = 0; i < EAL_ARG_COUNT; i++) - free(g_arg_strings[i]); -} - -static unsigned long long -spdk_get_eal_coremask(const char *coremask) -{ - unsigned long long core_mask, max_coremask = 0; - int num_cores_online; - - num_cores_online = sysconf(_SC_NPROCESSORS_ONLN); - if (num_cores_online > 0) { - if (num_cores_online > RTE_MAX_LCORE) { - num_cores_online = RTE_MAX_LCORE; - } - if (num_cores_online >= 64) { - max_coremask = ~0ULL; - } else { - max_coremask = (1ULL << num_cores_online) - 1; - } - } - - core_mask = strtoull(coremask, NULL, 16); - core_mask &= max_coremask; - - return core_mask; -} - -static void -spdk_build_eal_cmdline(struct spdk_app_opts *opts) -{ - unsigned long long core_mask; - - /* set the program name */ - g_arg_strings[EAL_PROGNAME_ARG] = spdk_sprintf_alloc("%s", opts->name); - if (g_arg_strings[EAL_PROGNAME_ARG] == NULL) { - rte_exit(EXIT_FAILURE, "g_arg_strings spdk_sprintf_alloc"); - } - - /*set the coremask */ - core_mask = spdk_get_eal_coremask(opts->reactor_mask); - g_arg_strings[EAL_COREMASK_ARG] = spdk_sprintf_alloc("-c %llx", core_mask); - if (g_arg_strings[EAL_COREMASK_ARG] == NULL) { - spdk_free_ealargs(); - rte_exit(EXIT_FAILURE, "g_arg_strings spdk_sprintf_alloc"); - } - - /* set the memory channel number */ - g_arg_strings[EAL_MEMCHAN_ARG] = spdk_sprintf_alloc("-n %d", opts->dpdk_mem_channel); - if (g_arg_strings[EAL_MEMCHAN_ARG] == NULL) { - spdk_free_ealargs(); - rte_exit(EXIT_FAILURE, "g_arg_strings spdk_sprintf_alloc"); - } - - /* set the memory size */ - g_arg_strings[EAL_MEMSIZE_ARG] = spdk_sprintf_alloc("-m %d", opts->dpdk_mem_size); - if (g_arg_strings[EAL_MEMSIZE_ARG] == NULL) { - spdk_free_ealargs(); - rte_exit(EXIT_FAILURE, "g_arg_strings spdk_sprintf_alloc"); - } - - /* set the master core */ - g_arg_strings[EAL_MASTER_CORE_ARG] = spdk_sprintf_alloc("--master-lcore=%d", - opts->dpdk_master_core); - if (g_arg_strings[EAL_MASTER_CORE_ARG] == NULL) { - spdk_free_ealargs(); - rte_exit(EXIT_FAILURE, "g_arg_strings spdk_sprintf_alloc"); - } - -#ifdef __linux__ - /* set the hugepage file prefix */ - g_arg_strings[EAL_FILE_PREFIX_ARG] = spdk_sprintf_alloc("--file-prefix=spdk%d", - opts->shm_id); -#else - /* --file-prefix is not required on FreeBSD */ - g_arg_strings[EAL_FILE_PREFIX_ARG] = strdup(""); -#endif - if (g_arg_strings[EAL_FILE_PREFIX_ARG] == NULL) { - spdk_free_ealargs(); - rte_exit(EXIT_FAILURE, "ealargs spdk_sprintf_alloc"); - } - -#ifdef __linux__ - /* set the process type */ - g_arg_strings[EAL_PROC_TYPE_ARG] = spdk_sprintf_alloc("--proc-type=auto"); -#else - /* --proc-type is not required on FreeBSD */ - /* TODO: to enable the support on FreeBSD once it supports process shared mutex */ - g_arg_strings[EAL_PROC_TYPE_ARG] = strdup(""); -#endif - if (g_arg_strings[EAL_PROC_TYPE_ARG] == NULL) { - spdk_free_ealargs(); - rte_exit(EXIT_FAILURE, "ealargs spdk_sprintf_alloc"); - } - - memcpy(g_ealargs, g_arg_strings, sizeof(g_arg_strings)); -} - -static void -spdk_init_dpdk(struct spdk_app_opts *opts) -{ - int i, rc; - static bool g_dpdk_initialized = false; - - /* to make sure DPDK is only initialized once */ - if (g_dpdk_initialized) - rte_exit(EXIT_FAILURE, "DPDK is already initialized\n"); - - spdk_build_eal_cmdline(opts); - - printf("Starting Intel(R) DPDK initialization ... \n"); - printf("[ DPDK EAL parameters: "); - for (i = 0; i < EAL_ARG_COUNT; i++) { - printf("%s ", g_ealargs[i]); - } - printf("]\n"); - - fflush(stdout); - rc = rte_eal_init(EAL_ARG_COUNT, g_ealargs); - spdk_free_ealargs(); - - if (rc < 0) - rte_exit(EXIT_FAILURE, "Invalid EAL arguments for DPDK\n"); - - g_dpdk_initialized = true; - - printf("done.\n"); -} - -__attribute__((weak)) -void spdk_dpdk_framework_init(struct spdk_app_opts *opts) -{ - spdk_init_dpdk(opts); -} diff --git a/test/lib/env/vtophys/vtophys.c b/test/lib/env/vtophys/vtophys.c index 806038529..e3ca0523b 100644 --- a/test/lib/env/vtophys/vtophys.c +++ b/test/lib/env/vtophys/vtophys.c @@ -36,17 +36,8 @@ #include #include -#include -#include - #include "spdk/env.h" -static const char *ealargs[] = { - "vtophys", - "-c 0x1", - "-n 4", -}; - static int vtophys_negative_test(void) { @@ -122,15 +113,13 @@ vtophys_positive_test(void) int main(int argc, char **argv) { - int rc; + int rc; + struct spdk_env_opts opts; - rc = rte_eal_init(sizeof(ealargs) / sizeof(ealargs[0]), - (char **)(void *)(uintptr_t)ealargs); - - if (rc < 0) { - fprintf(stderr, "Could not init eal\n"); - exit(1); - } + spdk_env_opts_init(&opts); + opts.name = "vtophys"; + opts.core_mask = "0x1"; + spdk_env_init(&opts); rc = vtophys_negative_test(); if (rc < 0) diff --git a/test/lib/event/event_perf/event_perf.c b/test/lib/event/event_perf/event_perf.c index dcd114539..f0aedfa85 100644 --- a/test/lib/event/event_perf/event_perf.c +++ b/test/lib/event/event_perf/event_perf.c @@ -38,7 +38,6 @@ #include #include -#include #include #include diff --git a/test/lib/nvme/aer/aer.c b/test/lib/nvme/aer/aer.c index 2b02aa4b3..7088a92ab 100644 --- a/test/lib/nvme/aer/aer.c +++ b/test/lib/nvme/aer/aer.c @@ -216,27 +216,19 @@ attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid, } } -static const char *ealargs[] = { - "aer", - "-c 0x1", - "-n 4", -}; - int main(int argc, char **argv) { - struct dev *dev; - int rc, i; + struct dev *dev; + int i; + struct spdk_env_opts opts; + + spdk_env_opts_init(&opts); + opts.name = "aer"; + opts.core_mask = "0x1"; + spdk_env_init(&opts); printf("Asynchronous Event Request test\n"); - rc = rte_eal_init(sizeof(ealargs) / sizeof(ealargs[0]), - (char **)(void *)(uintptr_t)ealargs); - - if (rc < 0) { - fprintf(stderr, "could not initialize dpdk\n"); - exit(1); - } - if (spdk_nvme_probe(NULL, NULL, probe_cb, attach_cb, NULL) != 0) { fprintf(stderr, "spdk_nvme_probe() failed\n"); return 1; diff --git a/test/lib/nvme/e2edp/nvme_dp.c b/test/lib/nvme/e2edp/nvme_dp.c index 3dca90781..f73426786 100644 --- a/test/lib/nvme/e2edp/nvme_dp.c +++ b/test/lib/nvme/e2edp/nvme_dp.c @@ -631,28 +631,19 @@ attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid, printf("Attached to %s\n", dev->name); } - -static const char *ealargs[] = { - "nvme_dp", - "-c 0x1", - "-n 4", -}; - int main(int argc, char **argv) { - struct dev *iter; - int rc, i; + struct dev *iter; + int rc, i; + struct spdk_env_opts opts; + + spdk_env_opts_init(&opts); + opts.name = "nvme_dp"; + opts.core_mask = "0x1"; + spdk_env_init(&opts); printf("NVMe Write/Read with End-to-End data protection test\n"); - rc = rte_eal_init(sizeof(ealargs) / sizeof(ealargs[0]), - (char **)(void *)(uintptr_t)ealargs); - - if (rc < 0) { - fprintf(stderr, "could not initialize dpdk\n"); - exit(1); - } - if (spdk_nvme_probe(NULL, NULL, probe_cb, attach_cb, NULL) != 0) { fprintf(stderr, "nvme_probe() failed\n"); exit(1); diff --git a/test/lib/nvme/hotplug.sh b/test/lib/nvme/hotplug.sh index e8974fbc1..5fa0f6a86 100755 --- a/test/lib/nvme/hotplug.sh +++ b/test/lib/nvme/hotplug.sh @@ -100,7 +100,7 @@ insert_devices timing_enter hotplug_test -ssh_vm "examples/nvme/hotplug/hotplug -t 10 -i 4 -r 8" & +ssh_vm "examples/nvme/hotplug/hotplug -i 0 -t 10 -n 4 -r 8" & example_pid=$! sleep 2 diff --git a/test/lib/nvme/overhead/overhead.c b/test/lib/nvme/overhead/overhead.c index 4c78221e9..9ba9f8746 100644 --- a/test/lib/nvme/overhead/overhead.c +++ b/test/lib/nvme/overhead/overhead.c @@ -570,28 +570,21 @@ register_controllers(void) return 0; } -static char *ealargs[] = { - "perf", - "-c 0x1", - "-n 4", -}; - int main(int argc, char **argv) { - int rc; + int rc; + struct spdk_env_opts opts; + + spdk_env_opts_init(&opts); + opts.name = "overhead"; + opts.core_mask = "0x1"; + spdk_env_init(&opts); rc = parse_args(argc, argv); if (rc != 0) { return rc; } - rc = rte_eal_init(sizeof(ealargs) / sizeof(ealargs[0]), ealargs); - - if (rc < 0) { - fprintf(stderr, "could not initialize dpdk\n"); - return 1; - } - g_task = spdk_zmalloc(sizeof(struct perf_task), 0, NULL); if (g_task == NULL) { fprintf(stderr, "g_task alloc failed\n"); diff --git a/test/lib/nvme/reset/reset.c b/test/lib/nvme/reset/reset.c index cc148d420..2b35fdccb 100644 --- a/test/lib/nvme/reset/reset.c +++ b/test/lib/nvme/reset/reset.c @@ -612,29 +612,22 @@ run_nvme_reset_cycle(int retry_count) return 0; } -static char *ealargs[] = { - "reset", - "-c 0x1", - "-n 4", -}; - int main(int argc, char **argv) { - int rc; - int i; + int rc; + int i; + struct spdk_env_opts opts; + + spdk_env_opts_init(&opts); + opts.name = "reset"; + opts.core_mask = "0x1"; + spdk_env_init(&opts); rc = parse_args(argc, argv); if (rc != 0) { return rc; } - rc = rte_eal_init(sizeof(ealargs) / sizeof(ealargs[0]), ealargs); - - if (rc < 0) { - fprintf(stderr, "could not initialize dpdk\n"); - return 1; - } - task_pool = rte_mempool_create("task_pool", 8192, sizeof(struct reset_task), 64, 0, NULL, NULL, task_ctor, NULL, diff --git a/test/lib/nvme/sgl/sgl.c b/test/lib/nvme/sgl/sgl.c index 9511e0559..8bcd4935b 100644 --- a/test/lib/nvme/sgl/sgl.c +++ b/test/lib/nvme/sgl/sgl.c @@ -37,9 +37,6 @@ #include #include -#include -#include - #include "spdk/nvme.h" #include "spdk/env.h" @@ -447,28 +444,19 @@ attach_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid, printf("Attached to %s\n", dev->name); } - -static const char *ealargs[] = { - "nvme_sgl", - "-c 0x1", - "-n 4", -}; - int main(int argc, char **argv) { - struct dev *iter; - int rc, i; + struct dev *iter; + int rc, i; + struct spdk_env_opts opts; + + spdk_env_opts_init(&opts); + opts.name = "nvme_sgl"; + opts.core_mask = "0x1"; + spdk_env_init(&opts); printf("NVMe Readv/Writev Request test\n"); - rc = rte_eal_init(sizeof(ealargs) / sizeof(ealargs[0]), - (char **)(void *)(uintptr_t)ealargs); - - if (rc < 0) { - fprintf(stderr, "could not initialize dpdk\n"); - exit(1); - } - if (spdk_nvme_probe(NULL, NULL, probe_cb, attach_cb, NULL) != 0) { fprintf(stderr, "nvme_probe() failed\n"); exit(1);