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

app: add spdk_app_parse_args()



This is a helper function that eliminates a lot of
duplicated code in our target applications, specifically
around common command line argument parsing and usage
messages.  This patch only moves the iscsi, nvmf and
vhost targets to use this function, but there are other
test/example applications that could also take advantage
of it to reduce duplicated code and improve consistency.

Signed-off-by: default avatarJim Harris <james.r.harris@intel.com>
Change-Id: I1903de3daed90ac6282b006a8283b9df07ce37e9

Reviewed-on: https://review.gerrithub.io/386542


Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
parent 246cdd08
Loading
Loading
Loading
Loading
+11 −86
Original line number Diff line number Diff line
@@ -57,31 +57,8 @@ spdk_sigusr1(int signo __attribute__((__unused__)))
}

static void
common_usage(const char *executable_name, struct spdk_app_opts *default_opts)
iscsi_usage(void)
{
	printf("%s [options]\n", executable_name);
	printf("options:\n");
	printf(" -c config  config file (default %s)\n", default_opts->config_file);
	printf(" -e mask    tracepoint group mask for spdk trace buffers (default 0x0)\n");
	printf(" -m mask    core mask for DPDK\n");
	printf(" -i shared memory ID (optional)\n");
	printf(" -n channel number of memory channels used for DPDK\n");
	printf(" -p core    master (primary) core for DPDK\n");
	printf(" -s size    memory size in MB for DPDK\n");
	spdk_tracelog_usage(stdout, "-t");
	printf(" -H         show this usage\n");
	printf(" -d         disable coredump file enabling\n");
	printf(" -q         disable notice level logging to stderr\n");
}

static void
usage(char *executable_name)
{
	struct spdk_app_opts default_opts;

	spdk_app_opts_init(&default_opts);
	default_opts.config_file = SPDK_ISCSI_DEFAULT_CONFIG;
	common_usage(executable_name, &default_opts);
	printf(" -b         run iscsi target background, the default is foreground\n");
}

@@ -95,62 +72,15 @@ spdk_startup(void *arg1, void *arg2)
}

static void
iscsi_parse_args(int argc, char **argv, struct spdk_app_opts *opts)
iscsi_parse_arg(int ch, char *arg)
{
	int ch, rc;

	while ((ch = getopt(argc, argv, "bc:de:i:m:n:p:qs:t:H")) != -1) {
	switch (ch) {
		case 'd':
			opts->enable_coredump = false;
			break;
		case 'c':
			opts->config_file = optarg;
			break;
		case 'i':
			opts->shm_id = atoi(optarg);
			break;
		case 't':
			rc = spdk_log_set_trace_flag(optarg);
			if (rc < 0) {
				fprintf(stderr, "unknown flag\n");
				usage(argv[0]);
				exit(EXIT_FAILURE);
			}
			opts->print_level = SPDK_LOG_DEBUG;
#ifndef DEBUG
			fprintf(stderr, "%s must be built with CONFIG_DEBUG=y for -t flag\n",
				argv[0]);
			usage(argv[0]);
			exit(EXIT_FAILURE);
#endif
			break;
		case 'e':
			opts->tpoint_group_mask = optarg;
			break;
		case 'q':
			opts->print_level = SPDK_LOG_WARN;
			break;
		case 'm':
			opts->reactor_mask = optarg;
			break;
		case 'n':
			opts->mem_channel = atoi(optarg);
			break;
		case 'p':
			opts->master_core = atoi(optarg);
			break;
		case 's':
			opts->mem_size = atoi(optarg);
			break;
	case 'b':
		g_daemon_mode = 1;
		break;
		case 'H':
	default:
			usage(argv[0]);
			exit(EXIT_SUCCESS);
		}
		assert(false);
		break;
	}
}

@@ -160,15 +90,10 @@ main(int argc, char **argv)
	int rc;
	struct spdk_app_opts opts = {};

	/* default value in opts structure */
	spdk_app_opts_init(&opts);

	if (access(SPDK_ISCSI_DEFAULT_CONFIG, F_OK) == 0) {
	opts.config_file = SPDK_ISCSI_DEFAULT_CONFIG;
	}
	opts.name = "iscsi";

	iscsi_parse_args(argc, argv, &opts);
	spdk_app_parse_args(argc, argv, &opts, "b", iscsi_parse_arg, iscsi_usage);

	if (g_daemon_mode) {
		if (daemon(1, 0) < 0) {
+4 −85
Original line number Diff line number Diff line
@@ -42,91 +42,13 @@
#define SPDK_NVMF_DEFAULT_CONFIG SPDK_NVMF_BUILD_ETC "/nvmf.conf"

static void
common_usage(const char *executable_name, struct spdk_app_opts *default_opts)
nvmf_usage(void)
{
	printf("%s [options]\n", executable_name);
	printf("options:\n");
	printf(" -c config  - config file (default %s)\n", default_opts->config_file);
	printf(" -e mask    - tracepoint group mask for spdk trace buffers (default 0x0)\n");
	printf(" -m mask    - core mask for DPDK\n");
	printf(" -i shared memory ID (optional)\n");
	printf(" -n channel number of memory channels used for DPDK\n");
	printf(" -p core    master (primary) core for DPDK\n");
	printf(" -s size    memory size in MB for DPDK\n");

	spdk_tracelog_usage(stdout, "-t");

	printf(" -v         - verbose (enable warnings)\n");
	printf(" -H         - show this usage\n");
	printf(" -d         - disable coredump file enabling\n");
}

static void
usage(const char *executable_name)
nvmf_parse_arg(int ch, char *arg)
{
	struct spdk_app_opts default_opts;

	spdk_app_opts_init(&default_opts);
	default_opts.config_file = SPDK_NVMF_DEFAULT_CONFIG;
	common_usage(executable_name, &default_opts);
}

static void
nvmf_parse_args(int argc, char **argv, struct spdk_app_opts *opts)
{
	int ch, rc;

	while ((ch = getopt(argc, argv, "c:de:i:m:n:p:qs:t:DH")) != -1) {
		switch (ch) {
		case 'd':
			opts->enable_coredump = false;
			break;
		case 'c':
			opts->config_file = optarg;
			break;
		case 'i':
			opts->shm_id = atoi(optarg);
			break;
		case 't':
			rc = spdk_log_set_trace_flag(optarg);
			if (rc < 0) {
				fprintf(stderr, "unknown flag\n");
				usage(argv[0]);
				exit(EXIT_FAILURE);
			}
			opts->print_level = SPDK_LOG_DEBUG;
#ifndef DEBUG
			fprintf(stderr, "%s must be rebuilt with CONFIG_DEBUG=y for -t flag.\n",
				argv[0]);
			usage(argv[0]);
			exit(EXIT_FAILURE);
#endif
			break;
		case 'm':
			opts->reactor_mask = optarg;
			break;
		case 'n':
			opts->mem_channel = atoi(optarg);
			break;
		case 'p':
			opts->master_core = atoi(optarg);
			break;
		case 's':
			opts->mem_size = atoi(optarg);
			break;
		case 'e':
			opts->tpoint_group_mask = optarg;
			break;
		case 'q':
			opts->print_level = SPDK_LOG_WARN;
			break;
		case 'D':
		case 'H':
		default:
			usage(argv[0]);
			exit(EXIT_SUCCESS);
		}
	}
}

int
@@ -138,12 +60,9 @@ main(int argc, char **argv)
	/* default value in opts */
	spdk_app_opts_init(&opts);
	opts.name = "nvmf";
	if (access(SPDK_NVMF_DEFAULT_CONFIG, F_OK) == 0) {
	opts.config_file = SPDK_NVMF_DEFAULT_CONFIG;
	}
	opts.max_delay_us = 1000; /* 1 ms */

	nvmf_parse_args(argc, argv, &opts);
	spdk_app_parse_args(argc, argv, &opts, "", nvmf_parse_arg, nvmf_usage);

	rc = spdk_nvmf_tgt_start(&opts);

+11 −90
Original line number Diff line number Diff line
@@ -52,37 +52,13 @@ vhost_app_opts_init(struct spdk_app_opts *opts)
{
	spdk_app_opts_init(opts);
	opts->name = "vhost";
	if (access(SPDK_VHOST_DEFAULT_CONFIG, F_OK) == 0) {
	opts->config_file = SPDK_VHOST_DEFAULT_CONFIG;
	}
	opts->mem_size = SPDK_VHOST_DEFAULT_MEM_SIZE;
}

static void
common_usage(char *executable_name, struct spdk_app_opts *default_opts)
{
	printf("%s [options]\n", executable_name);
	printf("options:\n");
	printf(" -c config  config file (default: %s)\n", default_opts->config_file);
	printf(" -e mask    tracepoint group mask for spdk trace buffers (default: 0x0)\n");
	printf(" -i shm_id  shared memory ID (optional)\n");
	printf(" -m mask    reactor core mask (default: 0x1)\n");
	printf(" -N         pass --no-pci to DPDK\n");
	printf(" -p core    master (primary) core for DPDK\n");
	printf(" -s size    memory size in MB for DPDK (default: %dMB)\n", default_opts->mem_size);
	spdk_tracelog_usage(stdout, "-t");
	printf(" -h         show this usage\n");
	printf(" -d         disable coredump file enabling\n");
	printf(" -q         disable notice level logging to stderr\n");
}

static void
usage(char *executable_name)
vhost_usage(void)
{
	struct spdk_app_opts defaults;

	vhost_app_opts_init(&defaults);
	common_usage(executable_name, &defaults);
	printf(" -f pidfile save pid to file under given path\n");
	printf(" -S dir     directory where to create vhost sockets (default: pwd)\n");
}
@@ -103,70 +79,15 @@ save_pid(const char *pid_path)
}

static void
vhost_parse_args(int argc, char **argv, struct spdk_app_opts *opts)
vhost_parse_arg(int ch, char *arg)
{
	int ch, rc;

	vhost_app_opts_init(opts);

	while ((ch = getopt(argc, argv, "c:de:f:i:m:Np:qs:S:t:h")) != -1) {
	switch (ch) {
		case 'c':
			opts->config_file = optarg;
			break;
		case 'd':
			opts->enable_coredump = false;
			break;
		case 'e':
			opts->tpoint_group_mask = optarg;
			break;
	case 'f':
			g_pid_path = optarg;
			break;
		case 'h':
			usage(argv[0]);
			exit(EXIT_SUCCESS);
		case 'i':
			opts->shm_id = strtoul(optarg, NULL, 10);
			break;
		case 'm':
			opts->reactor_mask = optarg;
			break;
		case 'N':
			opts->no_pci = true;
			break;
		case 'p':
			opts->master_core = strtoul(optarg, NULL, 10);
			break;
		case 'q':
			opts->print_level = SPDK_LOG_WARN;
			break;
		case 's':
			opts->mem_size = strtoul(optarg, NULL, 10);
		g_pid_path = arg;
		break;
	case 'S':
			g_socket_path = optarg;
		g_socket_path = arg;
		break;
		case 't':
			rc = spdk_log_set_trace_flag(optarg);
			if (rc < 0) {
				fprintf(stderr, "unknown flag\n");
				usage(argv[0]);
				exit(EXIT_FAILURE);
			}
			opts->print_level = SPDK_LOG_DEBUG;
#ifndef DEBUG
			fprintf(stderr, "%s must be rebuilt with CONFIG_DEBUG=y for -t flag.\n",
				argv[0]);
			usage(argv[0]);
			exit(EXIT_FAILURE);
#endif
			break;
		default:
			fprintf(stderr, "%s Unknown option '-%c'.\n", argv[0], ch);
			usage(argv[0]);
			exit(EXIT_FAILURE);
		}
	}
}

@@ -178,7 +99,7 @@ main(int argc, char *argv[])

	vhost_app_opts_init(&opts);

	vhost_parse_args(argc, argv, &opts);
	spdk_app_parse_args(argc, argv, &opts, "f:S:", vhost_parse_arg, vhost_usage);

	if (g_pid_path) {
		save_pid(g_pid_path);
+19 −0
Original line number Diff line number Diff line
@@ -152,6 +152,25 @@ int spdk_app_get_core_count(void) __attribute__((deprecated));
 */
uint32_t spdk_app_get_current_core(void) __attribute__((deprecated));

#define SPDK_APP_GETOPT_STRING "c:de:hi:m:n:p:qs:t:"

/**
 * \brief Helper function for parsing arguments and printing usage messages.
 *
 * \param argc Count of arguments in argv parameter array.
 * \param argv Array of command line arguments.
 * \param opts Default options for the application.
 * \param getopt_str String representing the app-specific command line parameters.
 *		     Characters in this string must not conflict with characters in
 *		     SPDK_APP_GETOPT_STRING.
 * \param parse Function pointer to call if an argument in getopt_str is found.
 * \param usage Function pointer to print usage messages for app-specific command
 *		line parameters.
 */
int spdk_app_parse_args(int argc, char **argv, struct spdk_app_opts *opts,
			const char *getopt_str, void (*parse)(int ch, char *arg),
			void (*usage)(void));

/**
 * \brief Allocate an event to be passed to \ref spdk_event_call
 */
+106 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@
#include "spdk/log.h"
#include "spdk/conf.h"
#include "spdk/trace.h"
#include "spdk/string.h"

#define SPDK_APP_DEFAULT_LOG_PRIORITY	SPDK_LOG_INFO

@@ -446,3 +447,108 @@ spdk_app_stop(int rc)
	 */
	spdk_event_call(spdk_event_allocate(g_init_lcore, _spdk_app_stop, NULL, NULL));
}

static void
usage(char *executable_name, struct spdk_app_opts *default_opts, void (*app_usage)(void))
{
	printf("%s [options]\n", executable_name);
	printf("options:\n");
	printf(" -c config  config file (default %s)\n", default_opts->config_file);
	printf(" -d         disable coredump file enabling\n");
	printf(" -e mask    tracepoint group mask for spdk trace buffers (default 0x0)\n");
	printf(" -h         show this usage\n");
	printf(" -i shared memory ID (optional)\n");
	printf(" -m mask    core mask for DPDK\n");
	printf(" -n channel number of memory channels used for DPDK\n");
	printf(" -p core    master (primary) core for DPDK\n");
	printf(" -q         disable notice level logging to stderr\n");
	printf(" -s size    memory size in MB for DPDK (default: ");
	if (default_opts->mem_size > 0) {
		printf("%dMB)\n", default_opts->mem_size);
	} else {
		printf("all hugepage memory)\n");
	}
	spdk_tracelog_usage(stdout, "-t");
	app_usage();
}

int
spdk_app_parse_args(int argc, char **argv, struct spdk_app_opts *opts,
		    const char *app_getopt_str, void (*app_parse)(int ch, char *arg),
		    void (*app_usage)(void))
{
	int ch, rc;
	struct spdk_app_opts default_opts;
	char *getopt_str;

	memcpy(&default_opts, opts, sizeof(default_opts));

	if (opts->config_file && access(opts->config_file, F_OK) != 0) {
		opts->config_file = NULL;
	}

	getopt_str = spdk_sprintf_alloc("%s%s", app_getopt_str, SPDK_APP_GETOPT_STRING);
	if (getopt_str == NULL) {
		fprintf(stderr, "Could not allocate getopt_str in %s()\n", __func__);
		exit(EXIT_FAILURE);
	}

	while ((ch = getopt(argc, argv, getopt_str)) != -1) {
		switch (ch) {
		case 'c':
			opts->config_file = optarg;
			break;
		case 'd':
			opts->enable_coredump = false;
			break;
		case 'e':
			opts->tpoint_group_mask = optarg;
			break;
		case 'h':
			usage(argv[0], &default_opts, app_usage);
			exit(EXIT_SUCCESS);
		case 'i':
			opts->shm_id = atoi(optarg);
			break;
		case 'm':
			opts->reactor_mask = optarg;
			break;
		case 'n':
			opts->mem_channel = atoi(optarg);
			break;
		case 'p':
			opts->master_core = atoi(optarg);
			break;
		case 'q':
			opts->print_level = SPDK_LOG_WARN;
			break;
		case 's':
			opts->mem_size = atoi(optarg);
			break;
		case 't':
			rc = spdk_log_set_trace_flag(optarg);
			if (rc < 0) {
				fprintf(stderr, "unknown flag\n");
				usage(argv[0], &default_opts, app_usage);
				exit(EXIT_FAILURE);
			}
			opts->print_level = SPDK_LOG_DEBUG;
#ifndef DEBUG
			fprintf(stderr, "%s must be built with CONFIG_DEBUG=y for -t flag\n",
				argv[0]);
			usage(argv[0], &default_opts, app_usage);
			exit(EXIT_FAILURE);
#endif
			break;
		case '?':
			usage(argv[0], &default_opts, app_usage);
			exit(EXIT_FAILURE);
		default:
			app_parse(ch, optarg);
		}
	}

	free(getopt_str);

	return 0;
}