Peter Rajnoha 056a28
 WHATS_NEW_DM                |    1 +
Peter Rajnoha 056a28
 daemons/dmeventd/dmeventd.c |   95 +++++++++++++++++++++++++++++++++++++++++--
Peter Rajnoha 056a28
 2 files changed, 92 insertions(+), 4 deletions(-)
Peter Rajnoha 056a28
Peter Rajnoha 056a28
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
Peter Rajnoha 056a28
index 868a469..d09a50c 100644
Peter Rajnoha 056a28
--- a/WHATS_NEW_DM
Peter Rajnoha 056a28
+++ b/WHATS_NEW_DM
Peter Rajnoha 056a28
@@ -1,5 +1,6 @@
Peter Rajnoha 056a28
 Version 1.02.66 -
Peter Rajnoha 056a28
 ===============================
Peter Rajnoha 056a28
+  Add support for systemd file descriptor handover to dmeventd.
Peter Rajnoha 056a28
   Add support for new oom killer adjustment interface (oom_score_adj).
Peter Rajnoha 056a28
   Add systemd unit files for dmeventd.
Peter Rajnoha 056a28
 
Peter Rajnoha 056a28
diff --git a/daemons/dmeventd/dmeventd.c b/daemons/dmeventd/dmeventd.c
Peter Rajnoha 056a28
index a6956cb..ec514ee 100644
Peter Rajnoha 056a28
--- a/daemons/dmeventd/dmeventd.c
Peter Rajnoha 056a28
+++ b/daemons/dmeventd/dmeventd.c
Peter Rajnoha 056a28
@@ -55,6 +55,13 @@
Peter Rajnoha 056a28
 /* New interface */
Peter Rajnoha 056a28
 #  define OOM_SCORE_ADJ_MIN (-1000)
Peter Rajnoha 056a28
 
Peter Rajnoha 056a28
+/* Systemd on-demand activation support */
Peter Rajnoha 056a28
+#  define SD_LISTEN_PID_ENV_VAR_NAME "LISTEN_PID"
Peter Rajnoha 056a28
+#  define SD_LISTEN_FDS_ENV_VAR_NAME "LISTEN_FDS"
Peter Rajnoha 056a28
+#  define SD_LISTEN_FDS_START 3
Peter Rajnoha 056a28
+#  define SD_FD_FIFO_SERVER SD_LISTEN_FDS_START
Peter Rajnoha 056a28
+#  define SD_FD_FIFO_CLIENT (SD_LISTEN_FDS_START + 1)
Peter Rajnoha 056a28
+
Peter Rajnoha 056a28
 #endif
Peter Rajnoha 056a28
 
Peter Rajnoha 056a28
 /* FIXME We use syslog for now, because multilog is not yet implemented */
Peter Rajnoha 056a28
@@ -104,6 +111,7 @@ static pthread_mutex_t _global_mutex;
Peter Rajnoha 056a28
 #define THREAD_STACK_SIZE (300*1024)
Peter Rajnoha 056a28
 
Peter Rajnoha 056a28
 int dmeventd_debug = 0;
Peter Rajnoha 056a28
+static int _systemd_activation = 0;
Peter Rajnoha 056a28
 static int _foreground = 0;
Peter Rajnoha 056a28
 static int _restart = 0;
Peter Rajnoha 056a28
 static char **_initial_registrations = 0;
Peter Rajnoha 056a28
@@ -1710,8 +1718,13 @@ static void _daemonize(void)
Peter Rajnoha 056a28
 	else
Peter Rajnoha 056a28
 		fd = rlim.rlim_cur;
Peter Rajnoha 056a28
 
Peter Rajnoha 056a28
-	for (--fd; fd >= 0; fd--)
Peter Rajnoha 056a28
+	for (--fd; fd >= 0; fd--) {
Peter Rajnoha 056a28
+		/* Do not close fds preloaded by systemd! */
Peter Rajnoha 056a28
+		if (_systemd_activation &&
Peter Rajnoha 056a28
+		    (fd == SD_FD_FIFO_SERVER || fd == SD_FD_FIFO_CLIENT))
Peter Rajnoha 056a28
+			continue;
Peter Rajnoha 056a28
 		close(fd);
Peter Rajnoha 056a28
+	}
Peter Rajnoha 056a28
 
Peter Rajnoha 056a28
 	if ((open("/dev/null", O_RDONLY) < 0) ||
Peter Rajnoha 056a28
 	    (open("/dev/null", O_WRONLY) < 0) ||
Peter Rajnoha 056a28
@@ -1780,6 +1793,76 @@ static void restart(void)
Peter Rajnoha 056a28
 	fini_fifos(&fifos);
Peter Rajnoha 056a28
 }
Peter Rajnoha 056a28
 
Peter Rajnoha 056a28
+static int _handle_preloaded_fifo(int fd, const char *path)
Peter Rajnoha 056a28
+{
Peter Rajnoha 056a28
+	struct stat st_fd, st_path;
Peter Rajnoha 056a28
+	int flags;
Peter Rajnoha 056a28
+
Peter Rajnoha 056a28
+	if ((flags = fcntl(fd, F_GETFD)) < 0)
Peter Rajnoha 056a28
+		return 0;
Peter Rajnoha 056a28
+
Peter Rajnoha 056a28
+	if (flags & FD_CLOEXEC)
Peter Rajnoha 056a28
+		return 0;
Peter Rajnoha 056a28
+
Peter Rajnoha 056a28
+	if (fstat(fd, &st_fd) < 0 || !S_ISFIFO(st_fd.st_mode))
Peter Rajnoha 056a28
+		return 0;
Peter Rajnoha 056a28
+
Peter Rajnoha 056a28
+	if (stat(path, &st_path) < 0 ||
Peter Rajnoha 056a28
+	    st_path.st_dev != st_fd.st_dev ||
Peter Rajnoha 056a28
+	    st_path.st_ino != st_fd.st_ino)
Peter Rajnoha 056a28
+		return 0;
Peter Rajnoha 056a28
+
Peter Rajnoha 056a28
+	if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
Peter Rajnoha 056a28
+		return 0;
Peter Rajnoha 056a28
+
Peter Rajnoha 056a28
+	return 1;
Peter Rajnoha 056a28
+}
Peter Rajnoha 056a28
+
Peter Rajnoha 056a28
+static int _systemd_handover(struct dm_event_fifos *fifos)
Peter Rajnoha 056a28
+{
Peter Rajnoha 056a28
+	const char *e;
Peter Rajnoha 056a28
+	char *p;
Peter Rajnoha 056a28
+	unsigned long env_pid, env_listen_fds;
Peter Rajnoha 056a28
+	int r = 0;
Peter Rajnoha 056a28
+
Peter Rajnoha 056a28
+	memset(fifos, 0, sizeof(*fifos));
Peter Rajnoha 056a28
+
Peter Rajnoha 056a28
+	/* LISTEN_PID must be equal to our PID! */
Peter Rajnoha 056a28
+	if (!(e = getenv(SD_LISTEN_PID_ENV_VAR_NAME)))
Peter Rajnoha 056a28
+		goto out;
Peter Rajnoha 056a28
+
Peter Rajnoha 056a28
+	errno = 0;
Peter Rajnoha 056a28
+	env_pid = strtoul(e, &p, 10);
Peter Rajnoha 056a28
+	if (errno || !p || *p || env_pid <= 0 ||
Peter Rajnoha 056a28
+	    getpid() != (pid_t) env_pid)
Peter Rajnoha 056a28
+		goto out;
Peter Rajnoha 056a28
+
Peter Rajnoha 056a28
+	/* LISTEN_FDS must be 2 and the fds must be FIFOSs! */
Peter Rajnoha 056a28
+	if (!(e = getenv(SD_LISTEN_FDS_ENV_VAR_NAME)))
Peter Rajnoha 056a28
+		goto out;
Peter Rajnoha 056a28
+
Peter Rajnoha 056a28
+	errno = 0;
Peter Rajnoha 056a28
+	env_listen_fds = strtoul(e, &p, 10);
Peter Rajnoha 056a28
+	if (errno || !p || *p || env_listen_fds != 2)
Peter Rajnoha 056a28
+		goto out;
Peter Rajnoha 056a28
+
Peter Rajnoha 056a28
+	/* Check and handle the FIFOs passed in */
Peter Rajnoha 056a28
+	r = (_handle_preloaded_fifo(SD_FD_FIFO_SERVER, DM_EVENT_FIFO_SERVER) &&
Peter Rajnoha 056a28
+	     _handle_preloaded_fifo(SD_FD_FIFO_CLIENT, DM_EVENT_FIFO_CLIENT));
Peter Rajnoha 056a28
+
Peter Rajnoha 056a28
+	if (r) {
Peter Rajnoha 056a28
+		fifos->server = SD_FD_FIFO_SERVER;
Peter Rajnoha 056a28
+		fifos->server_path = DM_EVENT_FIFO_SERVER;
Peter Rajnoha 056a28
+		fifos->client = SD_FD_FIFO_CLIENT;
Peter Rajnoha 056a28
+		fifos->client_path = DM_EVENT_FIFO_CLIENT;
Peter Rajnoha 056a28
+	}
Peter Rajnoha 056a28
+
Peter Rajnoha 056a28
+out:
Peter Rajnoha 056a28
+	unsetenv(SD_LISTEN_PID_ENV_VAR_NAME);
Peter Rajnoha 056a28
+	unsetenv(SD_LISTEN_FDS_ENV_VAR_NAME);
Peter Rajnoha 056a28
+	return r;
Peter Rajnoha 056a28
+}
Peter Rajnoha 056a28
+
Peter Rajnoha 056a28
 static void usage(char *prog, FILE *file)
Peter Rajnoha 056a28
 {
Peter Rajnoha 056a28
 	fprintf(file, "Usage:\n"
Peter Rajnoha 056a28
@@ -1834,6 +1917,8 @@ int main(int argc, char *argv[])
Peter Rajnoha 056a28
 	if (_restart)
Peter Rajnoha 056a28
 		restart();
Peter Rajnoha 056a28
 
Peter Rajnoha 056a28
+	_systemd_activation = _systemd_handover(&fifos);
Peter Rajnoha 056a28
+
Peter Rajnoha 056a28
 	if (!_foreground)
Peter Rajnoha 056a28
 		_daemonize();
Peter Rajnoha 056a28
 
Peter Rajnoha 056a28
@@ -1852,7 +1937,8 @@ int main(int argc, char *argv[])
Peter Rajnoha 056a28
 	signal(SIGQUIT, &_exit_handler);
Peter Rajnoha 056a28
 
Peter Rajnoha 056a28
 #ifdef linux
Peter Rajnoha 056a28
-	if (!_protect_against_oom_killer())
Peter Rajnoha 056a28
+	/* Systemd has adjusted oom killer for us already */
Peter Rajnoha 056a28
+	if (!_systemd_activation && !_protect_against_oom_killer())
Peter Rajnoha 056a28
 		syslog(LOG_ERR, "Failed to protect against OOM killer");
Peter Rajnoha 056a28
 #endif
Peter Rajnoha 056a28
 
Peter Rajnoha 056a28
@@ -1863,11 +1949,12 @@ int main(int argc, char *argv[])
Peter Rajnoha 056a28
 	//multilog_init_verbose(std_syslog, _LOG_DEBUG);
Peter Rajnoha 056a28
 	//multilog_async(1);
Peter Rajnoha 056a28
 
Peter Rajnoha 056a28
-	_init_fifos(&fifos);
Peter Rajnoha 056a28
+	if (!_systemd_activation)
Peter Rajnoha 056a28
+		_init_fifos(&fifos);
Peter Rajnoha 056a28
 
Peter Rajnoha 056a28
 	pthread_mutex_init(&_global_mutex, NULL);
Peter Rajnoha 056a28
 
Peter Rajnoha 056a28
-	if (_open_fifos(&fifos))
Peter Rajnoha 056a28
+	if (!_systemd_activation && _open_fifos(&fifos))
Peter Rajnoha 056a28
 		exit(EXIT_FIFO_FAILURE);
Peter Rajnoha 056a28
 
Peter Rajnoha 056a28
 	/* Signal parent, letting them know we are ready to go. */