diff --git a/etc/spdk/nvmf.conf.in b/etc/spdk/nvmf.conf.in index 835229f6d..f222b1d01 100644 --- a/etc/spdk/nvmf.conf.in +++ b/etc/spdk/nvmf.conf.in @@ -20,6 +20,12 @@ # Set to 0xFFFFFFFFFFFFFFFF to enable all tracepoint groups. #TpointGroupMask 0x0 + # PciBlacklist and PciWhitelist cannot be used at the same time + #PciBlacklist 0000:01:00.0 + #PciBlacklist 0000:02:00.0 + #PciWhitelist 0000:03:00.0 + #PciWhitelist 0000:04:00.0 + # Users may change this section to create a different number or size of # malloc LUNs. # This will generate 8 LUNs with a malloc-allocated backend. diff --git a/include/spdk/env.h b/include/spdk/env.h index bf6ba459c..d68fb7093 100644 --- a/include/spdk/env.h +++ b/include/spdk/env.h @@ -72,6 +72,9 @@ struct spdk_env_opts { int mem_size; bool no_pci; bool hugepage_single_segments; + size_t num_pci_addr; + struct spdk_pci_addr *pci_blacklist; + struct spdk_pci_addr *pci_whitelist; /** Opaque context for use of the env implementation. */ void *env_context; diff --git a/include/spdk/event.h b/include/spdk/event.h index fdcf86edb..0688efc72 100644 --- a/include/spdk/event.h +++ b/include/spdk/event.h @@ -90,6 +90,9 @@ struct spdk_app_opts { bool no_pci; bool hugepage_single_segments; enum spdk_log_level print_level; + size_t num_pci_addr; + struct spdk_pci_addr *pci_blacklist; + struct spdk_pci_addr *pci_whitelist; /* The maximum latency allowed when passing an event * from one core to another. A value of 0 @@ -186,7 +189,7 @@ int spdk_app_parse_core_mask(const char *mask, struct spdk_cpuset *cpumask); */ struct spdk_cpuset *spdk_app_get_core_mask(void); -#define SPDK_APP_GETOPT_STRING "c:de:ghi:m:n:p:qr:s:t:u" +#define SPDK_APP_GETOPT_STRING "c:de:ghi:m:n:p:qr:s:t:uB:W:" enum spdk_app_parse_args_rvals { SPDK_APP_PARSE_ARGS_HELP = 0, diff --git a/lib/env_dpdk/init.c b/lib/env_dpdk/init.c index ec16a003d..948d98105 100644 --- a/lib/env_dpdk/init.c +++ b/lib/env_dpdk/init.c @@ -250,6 +250,22 @@ spdk_build_eal_cmdline(const struct spdk_env_opts *opts) } } + if (opts->num_pci_addr) { + size_t i; + char bdf[32]; + struct spdk_pci_addr *pci_addr = + opts->pci_blacklist ? opts->pci_blacklist : opts->pci_whitelist; + + for (i = 0; i < opts->num_pci_addr; i++) { + spdk_pci_addr_fmt(bdf, 32, &pci_addr[i]); + args = spdk_push_arg(args, &argcount, _sprintf_alloc("%s %s", + (opts->pci_blacklist ? "-b" : "-w"), bdf)); + 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", diff --git a/lib/event/app.c b/lib/event/app.c index 8e41884d9..e51e829e9 100644 --- a/lib/event/app.c +++ b/lib/event/app.c @@ -301,10 +301,34 @@ error: return NULL; } -static void +static int +spdk_app_opts_add_pci_addr(struct spdk_app_opts *opts, struct spdk_pci_addr **list, char *bdf) +{ + struct spdk_pci_addr *tmp = *list; + size_t i = opts->num_pci_addr; + + tmp = realloc(tmp, sizeof(*tmp) * (i + 1)); + if (tmp == NULL) { + SPDK_ERRLOG("realloc error\n"); + return -ENOMEM; + } + + *list = tmp; + if (spdk_pci_addr_parse(*list + i, bdf) < 0) { + SPDK_ERRLOG("Invalid address %s\n", bdf); + return -EINVAL; + } + + opts->num_pci_addr++; + return 0; +} + +static int spdk_app_read_config_file_global_params(struct spdk_app_opts *opts) { struct spdk_conf_section *sp; + char *bdf; + int i, rc = 0; sp = spdk_conf_find_section(NULL, "Global"); @@ -331,6 +355,43 @@ spdk_app_read_config_file_global_params(struct spdk_app_opts *opts) opts->tpoint_group_mask = spdk_conf_section_get_val(sp, "TpointGroupMask"); } } + + if (sp == NULL) { + return 0; + } + + for (i = 0; ; i++) { + bdf = spdk_conf_section_get_nmval(sp, "PciBlacklist", i, 0); + if (!bdf) { + break; + } + + rc = spdk_app_opts_add_pci_addr(opts, &opts->pci_blacklist, bdf); + if (rc != 0) { + free(opts->pci_blacklist); + return rc; + } + } + + for (i = 0; ; i++) { + bdf = spdk_conf_section_get_nmval(sp, "PciWhitelist", i, 0); + if (!bdf) { + break; + } + + if (opts->pci_blacklist != NULL) { + SPDK_ERRLOG("PciBlacklist and PciWhitelist cannot be used at the same time\n"); + free(opts->pci_blacklist); + return -EINVAL; + } + + rc = spdk_app_opts_add_pci_addr(opts, &opts->pci_whitelist, bdf); + if (rc != 0) { + free(opts->pci_whitelist); + return rc; + } + } + return 0; } static int @@ -348,8 +409,14 @@ spdk_app_setup_env(struct spdk_app_opts *opts) env_opts.master_core = opts->master_core; env_opts.mem_size = opts->mem_size; env_opts.no_pci = opts->no_pci; + env_opts.num_pci_addr = opts->num_pci_addr; + env_opts.pci_blacklist = opts->pci_blacklist; + env_opts.pci_whitelist = opts->pci_whitelist; rc = spdk_env_init(&env_opts); + free(env_opts.pci_blacklist); + free(env_opts.pci_whitelist); + if (rc < 0) { SPDK_ERRLOG("Unable to initialize SPDK env\n"); } @@ -431,7 +498,9 @@ spdk_app_start(struct spdk_app_opts *opts, spdk_event_fn start_fn, goto app_start_setup_conf_err; } - spdk_app_read_config_file_global_params(opts); + if (spdk_app_read_config_file_global_params(opts) < 0) { + goto app_start_setup_conf_err; + } spdk_log_set_level(SPDK_APP_DEFAULT_LOG_LEVEL); spdk_log_open(); @@ -552,6 +621,8 @@ usage(char *executable_name, struct spdk_app_opts *default_opts, void (*app_usag printf("all hugepage memory)\n"); } printf(" -u disable PCI access.\n"); + printf(" -B addr pci addr to blacklist\n"); + printf(" -W addr pci addr to whitelist (-B and -W cannot be used at the same time)\n"); spdk_tracelog_usage(stdout, "-t"); app_usage(); } @@ -677,6 +748,38 @@ spdk_app_parse_args(int argc, char **argv, struct spdk_app_opts *opts, case 'u': opts->no_pci = true; break; + case 'B': + if (opts->pci_whitelist) { + free(opts->pci_whitelist); + fprintf(stderr, "-B and -W cannot be used at the same time\n"); + usage(argv[0], &default_opts, app_usage); + rval = SPDK_APP_PARSE_ARGS_FAIL; + goto parse_done; + } + + rc = spdk_app_opts_add_pci_addr(opts, &opts->pci_blacklist, optarg); + if (rc != 0) { + free(opts->pci_blacklist); + rval = SPDK_APP_PARSE_ARGS_FAIL; + goto parse_done; + } + break; + case 'W': + if (opts->pci_blacklist) { + free(opts->pci_blacklist); + fprintf(stderr, "-B and -W cannot be used at the same time\n"); + usage(argv[0], &default_opts, app_usage); + rval = SPDK_APP_PARSE_ARGS_FAIL; + goto parse_done; + } + + rc = spdk_app_opts_add_pci_addr(opts, &opts->pci_whitelist, optarg); + if (rc != 0) { + free(opts->pci_whitelist); + rval = SPDK_APP_PARSE_ARGS_FAIL; + goto parse_done; + } + break; case '?': /* * In the event getopt() above detects an option