linux-nvme.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: mwilck@suse.com
To: Sagi Grimberg <sagi@grimberg.me>, Hannes Reinecke <hare@suse.de>,
	Keith Busch <kbusch@kernel.org>
Cc: Chaitanya Kulkarni <Chaitanya.Kulkarni@wdc.com>,
	linux-nvme@lists.infradead.org,
	Enzo Matsumiya <ematsumiya@suse.de>,
	Martin Wilck <mwilck@suse.com>
Subject: [PATCH v2 11/16] monitor: watch discovery.conf with inotify
Date: Sat,  6 Mar 2021 01:36:54 +0100	[thread overview]
Message-ID: <20210306003659.21207-12-mwilck@suse.com> (raw)
In-Reply-To: <20210306003659.21207-1-mwilck@suse.com>

From: Martin Wilck <mwilck@suse.com>

Watch discovery.conf, and re-start discovery from conf file
whenever it's created or changed.
---
 monitor.c      | 114 +++++++++++++++++++++++++++++++++++++++++++++++++
 util/cleanup.c |   2 +
 util/cleanup.h |   1 +
 3 files changed, 117 insertions(+)

diff --git a/monitor.c b/monitor.c
index 95dea19..a1229a7 100644
--- a/monitor.c
+++ b/monitor.c
@@ -20,6 +20,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
+#include <inttypes.h>
 #include <libudev.h>
 #include <signal.h>
 #include <time.h>
@@ -28,6 +29,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/epoll.h>
+#include <sys/inotify.h>
 
 #include "nvme-status.h"
 #include "nvme.h"
@@ -448,6 +450,14 @@ static int monitor_handle_uevents(struct event *ev,
 	return EVENTCB_CONTINUE;
 }
 
+static struct {
+	bool running;
+	bool pending;
+	pid_t pid;
+} discovery_conf_task;
+
+static int monitor_discover_from_conf_file(void);
+
 static int handle_epoll_err(int errcode)
 {
 	if (errcode != -EINTR)
@@ -488,6 +498,15 @@ static int handle_epoll_err(int errcode)
 				    (long)pid, strerror(WEXITSTATUS(wstatus)));
 			else
 				msg(LOG_DEBUG, "child %ld exited normally\n", (long)pid);
+			if (discovery_conf_task.running &&
+			    discovery_conf_task.pid == pid) {
+				discovery_conf_task.running = false;
+				if (discovery_conf_task.pending) {
+					msg(LOG_NOTICE,
+					    "discovery from conf file pending - restarting\n");
+					monitor_discover_from_conf_file();
+				}
+			}
 			continue;
 		}
 
@@ -586,6 +605,13 @@ static int monitor_discover_from_conf_file(void)
 	pid_t pid;
 	int rc;
 
+	if (discovery_conf_task.running) {
+		msg(LOG_NOTICE, "discovery from conf file already running (%ld)\n",
+		    (long)discovery_conf_task.pid);
+		discovery_conf_task.pending = true;
+		return 0;
+	}
+
 	pid = fork();
 	if (pid == -1) {
 		msg(LOG_ERR, "failed to fork discovery task: %m");
@@ -593,6 +619,9 @@ static int monitor_discover_from_conf_file(void)
 	} else if (pid > 0) {
 		msg(LOG_DEBUG, "started discovery task %ld from conf file\n",
 		    (long)pid);
+		discovery_conf_task.pending = false;
+		discovery_conf_task.running = true;
+		discovery_conf_task.pid = pid;
 		return 0;
 	}
 
@@ -619,6 +648,89 @@ static int discovery_from_conf_file_cb(struct event *ev __attribute__((unused)),
 	return EVENTCB_CLEANUP;
 }
 
+static void handle_inotify_event(struct inotify_event *iev)
+{
+	if ((iev->mask & (IN_CLOSE_WRITE|IN_MOVED_TO)) == 0) {
+		msg(LOG_DEBUG, "ignoring event mask 0x%"PRIx32"\n", iev->mask);
+		return;
+	}
+
+	if (!iev->name || strcmp(iev->name, FILE_NVMF_DISC)) {
+		msg(LOG_DEBUG, "ignoring event mask 0x%"PRIx32" for %s\n",
+		    iev->mask, iev->name ? iev->name : "(null)");
+		return;
+	}
+
+	msg(LOG_INFO, "discovery.conf changed, re-reading\n");
+	monitor_discover_from_conf_file();
+}
+
+static int inotify_cb(struct event *ev, unsigned int ep_events)
+{
+	char buf[sizeof(struct inotify_event) + NAME_MAX + 1];
+	int rc;
+
+	if (ev->reason != REASON_EVENT_OCCURED || (ep_events & EPOLLIN) == 0)
+		return EVENTCB_CONTINUE;
+
+	while (true) {
+		struct inotify_event *iev;
+
+		rc = read(ev->fd, buf, sizeof(buf));
+		if (rc == -1) {
+			if (errno != EAGAIN)
+				msg(LOG_ERR, "error reading from inotify fd: %m\n");
+			return EVENTCB_CONTINUE;
+		}
+
+		iev = (struct inotify_event *)buf;
+		if (iev->mask & (IN_DELETE_SELF|IN_MOVE_SELF)) {
+			if (inotify_rm_watch(ev->fd, iev->wd) == -1)
+				msg(LOG_ERR, "failed to remove watch %d: %m\n",
+				    iev->wd);
+			msg(LOG_WARNING, "inotify watch %d removed\n", iev->wd);
+			return EVENTCB_CLEANUP;
+		}
+		handle_inotify_event(iev);
+	}
+	return EVENTCB_CONTINUE;
+}
+
+static DEFINE_CLEANUP_FUNC(cleanup_event, struct event *, free);
+
+static void add_inotify_event(struct dispatcher *dsp)
+{
+	struct event *inotify_event __cleanup__(cleanup_event) = NULL;
+	int fd __cleanup__(cleanup_fd) = -1;
+	int rc;
+
+	inotify_event = calloc(1, sizeof *inotify_event);
+	if (!inotify_event)
+		return;
+
+	fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
+	if (fd == -1) {
+		msg(LOG_ERR, "failed to init inotify: %m\n");
+		return;
+	}
+
+	*inotify_event = EVENT_ON_HEAP(inotify_cb, fd, EPOLLIN);
+	rc = inotify_add_watch(inotify_event->fd, PATH_NVMF_CFG_DIR,
+			       IN_CLOSE_WRITE|IN_MOVED_TO|
+			       IN_DELETE_SELF|IN_MOVE_SELF);
+	if (rc == -1)
+		msg(LOG_ERR, "failed to add inotify watch for %s: %m\n",
+		    PATH_NVMF_CFG_DIR);
+
+	if ((rc = event_add(dsp, inotify_event)) < 0) {
+		msg(LOG_ERR, "failed to add inotify event: %s\n",
+		    strerror(-rc));
+		return;
+	}
+	fd = -1;
+	inotify_event = NULL;
+}
+
 static int monitor_parse_opts(const char *desc, int argc, char **argv)
 {
 	bool quiet = false;
@@ -735,7 +847,9 @@ int aen_monitor(const char *desc, int argc, char **argv)
 		goto out;
 	}
 
+	add_inotify_event(mon_dsp);
 	conndb_init_from_sysfs();
+
 	ret = event_loop(mon_dsp, &wait_mask, handle_epoll_err);
 
 	conndb_for_each(monitor_kill_discovery_task, NULL);
diff --git a/util/cleanup.c b/util/cleanup.c
index 0d5d910..3101e1a 100644
--- a/util/cleanup.c
+++ b/util/cleanup.c
@@ -1,4 +1,6 @@
 #include <stdlib.h>
+#include <unistd.h>
 #include "cleanup.h"
 
 DEFINE_CLEANUP_FUNC(cleanup_charp, char *, free);
+DEFINE_CLEANUP_FUNC(cleanup_fd, int, close);
diff --git a/util/cleanup.h b/util/cleanup.h
index 89a4984..b039488 100644
--- a/util/cleanup.h
+++ b/util/cleanup.h
@@ -14,5 +14,6 @@ DECLARE_CLEANUP_FUNC(name, type)		\
 }
 
 DECLARE_CLEANUP_FUNC(cleanup_charp, char *);
+DECLARE_CLEANUP_FUNC(cleanup_fd, int);
 
 #endif
-- 
2.29.2


_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme

  parent reply	other threads:[~2021-03-06  0:46 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-06  0:36 [PATCH v2 00/16] nvme-cli: add "nvme monitor" subcommand mwilck
2021-03-06  0:36 ` [PATCH v2 01/16] fabrics: export symbols required for monitor functionality mwilck
2021-03-06  0:36 ` [PATCH v2 02/16] nvme-cli: add code for event and timeout handling mwilck
2021-03-17  0:32   ` Martin Wilck
2021-03-19 16:42     ` Martin Wilck
2021-03-30 22:06       ` Martin Wilck
2021-03-06  0:36 ` [PATCH v2 03/16] monitor: add basic "nvme monitor" functionality mwilck
2021-03-06  0:36 ` [PATCH v2 04/16] monitor: implement uevent handling mwilck
2021-03-06  0:36 ` [PATCH v2 05/16] conn-db: add simple connection registry mwilck
2021-03-06  0:36 ` [PATCH v2 06/16] monitor: monitor_discovery(): try to reuse existing controllers mwilck
2021-03-06  0:36 ` [PATCH v2 07/16] monitor: kill running discovery tasks on exit mwilck
2021-03-06  0:36 ` [PATCH v2 08/16] monitor: add option --cleanup / -C mwilck
2021-03-06  0:36 ` [PATCH v2 09/16] monitor: handling of add/remove uevents for nvme controllers mwilck
2021-03-06  0:36 ` [PATCH v2 10/16] monitor: discover from conf file on startup mwilck
2021-03-06  0:36 ` mwilck [this message]
2021-03-06  0:36 ` [PATCH v2 12/16] monitor: add parent/child messaging and "notify" message exchange mwilck
2021-03-06  0:36 ` [PATCH v2 13/16] monitor: add "query device" " mwilck
2021-03-06  0:36 ` [PATCH v2 14/16] completions: add completions for nvme monitor mwilck
2021-03-06  0:36 ` [PATCH v2 15/16] nvmf-autoconnect: add unit file for nvme-monitor.service mwilck
2021-03-06  0:36 ` [PATCH v2 16/16] nvme-monitor(1): add man page for nvme-monitor mwilck

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210306003659.21207-12-mwilck@suse.com \
    --to=mwilck@suse.com \
    --cc=Chaitanya.Kulkarni@wdc.com \
    --cc=ematsumiya@suse.de \
    --cc=hare@suse.de \
    --cc=kbusch@kernel.org \
    --cc=linux-nvme@lists.infradead.org \
    --cc=sagi@grimberg.me \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).