[PATCH v2 11/16] monitor: watch discovery.conf with inotify
mwilck at suse.com
mwilck at suse.com
Sat Mar 6 00:36:54 GMT 2021
From: Martin Wilck <mwilck at 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
More information about the Linux-nvme
mailing list