[PATCH v2 10/16] monitor: discover from conf file on startup

mwilck at suse.com mwilck at suse.com
Sat Mar 6 00:36:53 GMT 2021


From: Martin Wilck <mwilck at suse.com>

Implement discovery from /etc/nvme/discovery.conf on startup of
the monitor.

The monitor needs to call discover_from_conf_file() in order to
be able to do discovery at startup. discover_from_conf_file() takes
the argconfig_commandline_options argument from fabrics_discover().
By moving these options into a static variable, we can avoid passing
them as function argument. This makes it possible to use
discover_from_conf_file() from the monitor without making the
options for fabric_discover() globally visible.
---
 fabrics.c | 67 +++++++++++++++++++++++++++----------------------------
 fabrics.h |  5 +++++
 monitor.c | 58 +++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 94 insertions(+), 36 deletions(-)

diff --git a/fabrics.c b/fabrics.c
index 5012519..b195d0e 100644
--- a/fabrics.c
+++ b/fabrics.c
@@ -85,7 +85,6 @@ struct connect_args {
 struct connect_args *tracked_ctrls;
 
 #define PATH_NVME_FABRICS	"/dev/nvme-fabrics"
-#define PATH_NVMF_DISC		"/etc/nvme/discovery.conf"
 #define PATH_NVMF_HOSTNQN	"/etc/nvme/hostnqn"
 #define PATH_NVMF_HOSTID	"/etc/nvme/hostid"
 #define MAX_DISC_ARGS		10
@@ -1439,8 +1438,9 @@ int do_discover(char *argstr, bool connect, enum nvme_print_flags flags)
 	return ret;
 }
 
-static int discover_from_conf_file(const char *desc, char *argstr,
-		const struct argconfig_commandline_options *opts, bool connect)
+static OPT_ARGS(discover_opts);
+
+int discover_from_conf_file(const char *desc, char *argstr, bool connect)
 {
 	FILE *f;
 	char line[256], *ptr, *all_args, *args, **argv;
@@ -1480,7 +1480,7 @@ static int discover_from_conf_file(const char *desc, char *argstr,
 		while ((ptr = strsep(&args, " =\n")) != NULL)
 			argv[argc++] = ptr;
 
-		err = argconfig_parse(argc, argv, desc, opts);
+		err = argconfig_parse(argc, argv, desc, discover_opts);
 		if (err)
 			goto free_and_continue;
 
@@ -1523,41 +1523,40 @@ out:
 	return ret;
 }
 
+static OPT_ARGS(discover_opts) = {
+	OPT_LIST("transport",      't', &fabrics_cfg.transport,       "transport type"),
+	OPT_LIST("traddr",         'a', &fabrics_cfg.traddr,          "transport address"),
+	OPT_LIST("trsvcid",        's', &fabrics_cfg.trsvcid,         "transport service id (e.g. IP port)"),
+	OPT_LIST("host-traddr",    'w', &fabrics_cfg.host_traddr,     "host traddr (e.g. FC WWN's)"),
+	OPT_LIST("hostnqn",        'q', &fabrics_cfg.hostnqn,         "user-defined hostnqn (if default not used)"),
+	OPT_LIST("hostid",         'I', &fabrics_cfg.hostid,          "user-defined hostid (if default not used)"),
+	OPT_LIST("raw",            'r', &fabrics_cfg.raw,             "raw output file"),
+	OPT_LIST("device",         'd', &fabrics_cfg.device,          "use existing discovery controller device"),
+	OPT_INT("keep-alive-tmo",  'k', &fabrics_cfg.keep_alive_tmo,  "keep alive timeout period in seconds"),
+	OPT_INT("reconnect-delay", 'c', &fabrics_cfg.reconnect_delay, "reconnect timeout period in seconds"),
+	OPT_INT("ctrl-loss-tmo",   'l', &fabrics_cfg.ctrl_loss_tmo,   "controller loss timeout period in seconds"),
+	OPT_INT("tos",             'T', &fabrics_cfg.tos,             "type of service"),
+	OPT_FLAG("hdr_digest",     'g', &fabrics_cfg.hdr_digest,      "enable transport protocol header digest (TCP transport)"),
+	OPT_FLAG("data_digest",    'G', &fabrics_cfg.data_digest,     "enable transport protocol data digest (TCP transport)"),
+	OPT_INT("nr-io-queues",    'i', &fabrics_cfg.nr_io_queues,    "number of io queues to use (default is core count)"),
+	OPT_INT("nr-write-queues", 'W', &fabrics_cfg.nr_write_queues, "number of write queues to use (default 0)"),
+	OPT_INT("nr-poll-queues",  'P', &fabrics_cfg.nr_poll_queues,  "number of poll queues to use (default 0)"),
+	OPT_INT("queue-size",      'Q', &fabrics_cfg.queue_size,      "number of io queue elements to use (default 128)"),
+	OPT_FLAG("persistent",     'p', &fabrics_cfg.persistent,      "persistent discovery connection"),
+	OPT_FLAG("quiet",          'S', &fabrics_cfg.quiet,           "suppress already connected errors"),
+	OPT_FLAG("matching",       'm', &fabrics_cfg.matching_only,   "connect only records matching the traddr"),
+	OPT_FMT("output-format",   'o', &fabrics_cfg.output_format,   "Output format: normal|json|binary"),
+	OPT_END()
+};
+
 int fabrics_discover(const char *desc, int argc, char **argv, bool connect)
 {
 	char argstr[BUF_SIZE];
 	int ret;
 	enum nvme_print_flags flags;
-	bool quiet = false;
-
-	OPT_ARGS(opts) = {
-		OPT_LIST("transport",      't', &fabrics_cfg.transport,       "transport type"),
-		OPT_LIST("traddr",         'a', &fabrics_cfg.traddr,          "transport address"),
-		OPT_LIST("trsvcid",        's', &fabrics_cfg.trsvcid,         "transport service id (e.g. IP port)"),
-		OPT_LIST("host-traddr",    'w', &fabrics_cfg.host_traddr,     "host traddr (e.g. FC WWN's)"),
-		OPT_LIST("hostnqn",        'q', &fabrics_cfg.hostnqn,         "user-defined hostnqn (if default not used)"),
-		OPT_LIST("hostid",         'I', &fabrics_cfg.hostid,          "user-defined hostid (if default not used)"),
-		OPT_LIST("raw",            'r', &fabrics_cfg.raw,             "raw output file"),
-		OPT_LIST("device",         'd', &fabrics_cfg.device,          "existing discovery controller device"),
-		OPT_INT("keep-alive-tmo",  'k', &fabrics_cfg.keep_alive_tmo,  "keep alive timeout period in seconds"),
-		OPT_INT("reconnect-delay", 'c', &fabrics_cfg.reconnect_delay, "reconnect timeout period in seconds"),
-		OPT_INT("ctrl-loss-tmo",   'l', &fabrics_cfg.ctrl_loss_tmo,   "controller loss timeout period in seconds"),
-		OPT_INT("tos",             'T', &fabrics_cfg.tos,             "type of service"),
-		OPT_FLAG("hdr_digest",     'g', &fabrics_cfg.hdr_digest,      "enable transport protocol header digest (TCP transport)"),
-		OPT_FLAG("data_digest",    'G', &fabrics_cfg.data_digest,     "enable transport protocol data digest (TCP transport)"),
-		OPT_INT("nr-io-queues",    'i', &fabrics_cfg.nr_io_queues,    "number of io queues to use (default is core count)"),
-		OPT_INT("nr-write-queues", 'W', &fabrics_cfg.nr_write_queues, "number of write queues to use (default 0)"),
-		OPT_INT("nr-poll-queues",  'P', &fabrics_cfg.nr_poll_queues,  "number of poll queues to use (default 0)"),
-		OPT_INT("queue-size",      'Q', &fabrics_cfg.queue_size,      "number of io queue elements to use (default 128)"),
-		OPT_FLAG("persistent",     'p', &fabrics_cfg.persistent,      "persistent discovery connection"),
-		OPT_FLAG("quiet",          'S', &quiet,               "suppress already connected errors"),
-		OPT_FLAG("matching",       'm', &fabrics_cfg.matching_only,   "connect only records matching the traddr"),
-		OPT_FMT("output-format",   'o', &fabrics_cfg.output_format,   output_format),
-		OPT_END()
-	};
 
 	fabrics_cfg.tos = -1;
-	ret = argconfig_parse(argc, argv, desc, opts);
+	ret = argconfig_parse(argc, argv, desc, discover_opts);
 	if (ret)
 		goto out;
 
@@ -1572,7 +1571,7 @@ int fabrics_discover(const char *desc, int argc, char **argv, bool connect)
 		}
 	}
 
-	if (quiet)
+	if (fabrics_cfg.quiet)
 		log_level = LOG_WARNING;
 
 	if (fabrics_cfg.device && !strcmp(fabrics_cfg.device, "none"))
@@ -1581,7 +1580,7 @@ int fabrics_discover(const char *desc, int argc, char **argv, bool connect)
 	fabrics_cfg.nqn = NVME_DISC_SUBSYS_NAME;
 
 	if (!fabrics_cfg.transport && !fabrics_cfg.traddr) {
-		ret = discover_from_conf_file(desc, argstr, opts, connect);
+		ret = discover_from_conf_file(desc, argstr, connect);
 	} else {
 		set_discovery_kato(&fabrics_cfg);
 
diff --git a/fabrics.h b/fabrics.h
index 41e6a2d..128f251 100644
--- a/fabrics.h
+++ b/fabrics.h
@@ -38,6 +38,7 @@ struct fabrics_config {
 	int  data_digest;
 	bool persistent;
 	bool matching_only;
+	bool quiet;
 	const char *output_format;
 };
 extern struct fabrics_config fabrics_cfg;
@@ -45,11 +46,15 @@ extern struct fabrics_config fabrics_cfg;
 extern const char *const trtypes[];
 
 #define BUF_SIZE 4096
+#define PATH_NVMF_CFG_DIR	"/etc/nvme"
+#define FILE_NVMF_DISC		"discovery.conf"
+#define PATH_NVMF_DISC		PATH_NVMF_CFG_DIR "/" FILE_NVMF_DISC
 
 int build_options(char *argstr, int max_len, bool discover);
 int do_discover(char *argstr, bool connect, enum nvme_print_flags flags);
 int ctrl_instance(const char *device);
 char *parse_conn_arg(const char *conargs, const char delim, const char *field);
 int remove_ctrl(int instance);
+int discover_from_conf_file(const char *desc, char *argstr, bool connect);
 
 #endif
diff --git a/monitor.c b/monitor.c
index 43d3084..95dea19 100644
--- a/monitor.c
+++ b/monitor.c
@@ -477,12 +477,20 @@ static int handle_epoll_err(int errcode)
 		default:
 			break;
 		}
+
 		co = conndb_find_by_pid(pid);
 		if (!co) {
-			msg(LOG_ERR, "no connection found for discovery task %ld\n",
-			    (long)pid);
+			if (!WIFEXITED(wstatus))
+				msg(LOG_WARNING, "child %ld didn't exit normally\n",
+				    (long)pid);
+			else if (WEXITSTATUS(wstatus) != 0)
+				msg(LOG_NOTICE, "child %ld exited with status \"%s\"\n",
+				    (long)pid, strerror(WEXITSTATUS(wstatus)));
+			else
+				msg(LOG_DEBUG, "child %ld exited normally\n", (long)pid);
 			continue;
 		}
+
 		if (!WIFEXITED(wstatus)) {
 			msg(LOG_WARNING, "child %ld didn't exit normally\n",
 			    (long)pid);
@@ -572,6 +580,45 @@ static int monitor_remove_discovery_ctrl(struct nvme_connection *co,
 	return CD_CB_OK;
 }
 
+static int monitor_discover_from_conf_file(void)
+{
+	char argstr[BUF_SIZE];
+	pid_t pid;
+	int rc;
+
+	pid = fork();
+	if (pid == -1) {
+		msg(LOG_ERR, "failed to fork discovery task: %m");
+		return -errno;
+	} else if (pid > 0) {
+		msg(LOG_DEBUG, "started discovery task %ld from conf file\n",
+		    (long)pid);
+		return 0;
+	}
+
+	child_reset_signals();
+
+	msg(LOG_NOTICE, "starting discovery from conf file\n");
+
+	fabrics_cfg.nqn = NVME_DISC_SUBSYS_NAME;
+	fabrics_cfg.tos = -1;
+	fabrics_cfg.persistent = true;
+
+	rc = discover_from_conf_file("Discover NVMeoF subsystems from " PATH_NVMF_DISC,
+				     argstr, mon_cfg.autoconnect);
+
+	exit(-rc);
+	/* not reached */
+	return rc;
+}
+
+static int discovery_from_conf_file_cb(struct event *ev __attribute__((unused)),
+					unsigned int __attribute__((unused)) ep_events)
+{
+	monitor_discover_from_conf_file();
+	return EVENTCB_CLEANUP;
+}
+
 static int monitor_parse_opts(const char *desc, int argc, char **argv)
 {
 	bool quiet = false;
@@ -638,6 +685,7 @@ int aen_monitor(const char *desc, int argc, char **argv)
 	struct udev *udev __cleanup__(cleanup_udevp) = NULL;
 	struct udev_monitor *monitor __cleanup__(cleanup_monitorp) = NULL;
 	struct udev_monitor_event udev_event = { .e.fd = -1, };
+	struct event startup_discovery_event = { .fd = -1, };
 	sigset_t wait_mask;
 
 	ret = monitor_parse_opts(desc, argc, argv);
@@ -663,6 +711,12 @@ int aen_monitor(const char *desc, int argc, char **argv)
 		goto out;
 	}
 
+	startup_discovery_event =
+		TIMER_EVENT_ON_STACK(discovery_from_conf_file_cb, 0);
+	if ((ret = event_add(mon_dsp, &startup_discovery_event)) != 0)
+		msg(LOG_ERR, "failed to register initial discovery timer: %s\n",
+		    strerror(-ret));
+
 	ret = create_udev_monitor(udev, &monitor);
 	if (ret != 0)
 		goto out;
-- 
2.29.2




More information about the Linux-nvme mailing list