All of lore.kernel.org
 help / color / mirror / Atom feed
From: prajnoha@sourceware.org <prajnoha@sourceware.org>
To: lvm-devel@redhat.com
Subject: LVM2/daemons/common daemon-server.c
Date: 28 Feb 2012 13:05:21 -0000	[thread overview]
Message-ID: <20120228130521.28603.qmail@sourceware.org> (raw)

CVSROOT:	/cvs/lvm2
Module name:	LVM2
Changes by:	prajnoha at sourceware.org	2012-02-28 13:05:21

Modified files:
	daemons/common : daemon-server.c 

Log message:
	Add support for systemd socket handover for common daemon-server code and also add support for new OOM killer adjustment interface.
	
	This code is already a part of dmeventd, but it's modified slightly to check
	sockets instead of FIFOs.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/daemons/common/daemon-server.c.diff?cvsroot=lvm2&r1=1.17&r2=1.18

--- LVM2/daemons/common/daemon-server.c	2012/02/23 23:52:11	1.17
+++ LVM2/daemons/common/daemon-server.c	2012/02/28 13:05:21	1.18
@@ -43,6 +43,7 @@
 #endif
 
 static volatile sig_atomic_t _shutdown_requested = 0;
+static int _systemd_activation = 0;
 
 static void _exit_handler(int sig __attribute__((unused)))
 {
@@ -50,41 +51,148 @@
 }
 
 #ifdef linux
-#  define OOM_ADJ_FILE "/proc/self/oom_adj"
-#  include <stdio.h>
+
+#include <stddef.h>
+
+/*
+ * Kernel version 2.6.36 and higher has
+ * new OOM killer adjustment interface.
+ */
+#  define OOM_ADJ_FILE_OLD "/proc/self/oom_adj"
+#  define OOM_ADJ_FILE "/proc/self/oom_score_adj"
 
 /* From linux/oom.h */
+/* Old interface */
 #  define OOM_DISABLE (-17)
 #  define OOM_ADJUST_MIN (-16)
+/* New interface */
+#  define OOM_SCORE_ADJ_MIN (-1000)
+
+/* Systemd on-demand activation support */
+#  define SD_LISTEN_PID_ENV_VAR_NAME "LISTEN_PID"
+#  define SD_LISTEN_FDS_ENV_VAR_NAME "LISTEN_FDS"
+#  define SD_LISTEN_FDS_START 3
+#  define SD_FD_SOCKET_SERVER SD_LISTEN_FDS_START
+
+#  include <stdio.h>
+
+static int _set_oom_adj(const char *oom_adj_path, int val)
+{
+	FILE *fp;
+
+	if (!(fp = fopen(oom_adj_path, "w"))) {
+		perror("oom_adj: fopen failed");
+		return 0;
+	}
+
+	fprintf(fp, "%i", val);
+
+	if (dm_fclose(fp))
+		perror("oom_adj: fclose failed");
+
+	return 1;
+}
 
 /*
  * Protection against OOM killer if kernel supports it
  */
-static int _set_oom_adj(int val)
+static int _protect_against_oom_killer(void)
 {
-	FILE *fp;
-
 	struct stat st;
 
 	if (stat(OOM_ADJ_FILE, &st) == -1) {
-		if (errno == ENOENT)
-			perror(OOM_ADJ_FILE " not found");
-		else
+		if (errno != ENOENT)
 			perror(OOM_ADJ_FILE ": stat failed");
-		return 1;
+
+		/* Try old oom_adj interface as a fallback */
+		if (stat(OOM_ADJ_FILE_OLD, &st) == -1) {
+			if (errno == ENOENT)
+				perror(OOM_ADJ_FILE_OLD " not found");
+			else
+				perror(OOM_ADJ_FILE_OLD ": stat failed");
+			return 1;
+		}
+
+		return _set_oom_adj(OOM_ADJ_FILE_OLD, OOM_DISABLE) ||
+		       _set_oom_adj(OOM_ADJ_FILE_OLD, OOM_ADJUST_MIN);
 	}
 
-	if (!(fp = fopen(OOM_ADJ_FILE, "w"))) {
-		perror(OOM_ADJ_FILE ": fopen failed");
+	return _set_oom_adj(OOM_ADJ_FILE, OOM_SCORE_ADJ_MIN);
+}
+
+union sockaddr_union {
+	struct sockaddr sa;
+	struct sockaddr_un un;
+};
+
+static int _handle_preloaded_socket(int fd, const char *path)
+{
+	struct stat st_fd;
+	union sockaddr_union sockaddr;
+	int type = 0;
+	socklen_t len = sizeof(type);
+	size_t path_len = strlen(path);
+
+	if (fd < 0)
 		return 0;
-	}
 
-	fprintf(fp, "%i", val);
-	if (fclose(fp))
-		perror(OOM_ADJ_FILE ": fclose failed");
+	if (fstat(fd, &st_fd) < 0 || !S_ISSOCK(st_fd.st_mode))
+		return 0;
+
+	if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len) < 0 ||
+	    len != sizeof(type) || type != SOCK_STREAM)
+		return 0;
+
+	memset(&sockaddr, 0, sizeof(sockaddr));
+	len = sizeof(sockaddr);
+	if (getsockname(fd, &sockaddr.sa, &len) < 0 ||
+	    len < sizeof(sa_family_t) ||
+	    sockaddr.sa.sa_family != PF_UNIX)
+		return 0;
+
+	if (!(len >= offsetof(struct sockaddr_un, sun_path) + path_len + 1 &&
+	      memcmp(path, sockaddr.un.sun_path, path_len) == 0))
+		return 0;
 
 	return 1;
 }
+
+static int _systemd_handover(struct daemon_state *ds)
+{
+	const char *e;
+	char *p;
+	unsigned long env_pid, env_listen_fds;
+	int r = 0;
+
+	/* LISTEN_PID must be equal to our PID! */
+	if (!(e = getenv(SD_LISTEN_PID_ENV_VAR_NAME)))
+		goto out;
+
+	errno = 0;
+	env_pid = strtoul(e, &p, 10);
+	if (errno || !p || *p || env_pid <= 0 ||
+	    getpid() != (pid_t) env_pid)
+		;
+
+	/* LISTEN_FDS must be 1 and the fd must be a socket! */
+	if (!(e = getenv(SD_LISTEN_FDS_ENV_VAR_NAME)))
+		goto out;
+
+	errno = 0;
+	env_listen_fds = strtoul(e, &p, 10);
+	if (errno || !p || *p || env_listen_fds != 1)
+		goto out;
+
+	/* Check and handle the socket passed in */
+	if ((r = _handle_preloaded_socket(SD_FD_SOCKET_SERVER, ds->socket_path)))
+		ds->socket_fd = SD_FD_SOCKET_SERVER;
+
+out:
+	unsetenv(SD_LISTEN_PID_ENV_VAR_NAME);
+	unsetenv(SD_LISTEN_FDS_ENV_VAR_NAME);
+	return r;
+}
+
 #endif
 
 static int _open_socket(daemon_state s)
@@ -192,8 +300,14 @@
 	else
 		fd = rlim.rlim_cur;
 
-	for (--fd; fd >= 0; fd--)
+	for (--fd; fd >= 0; fd--) {
+#ifdef linux
+		/* Do not close fds preloaded by systemd! */
+		if (_systemd_activation && fd == SD_FD_SOCKET_SERVER)
+			continue;
+#endif
 		close(fd);
+	}
 
 	if ((open("/dev/null", O_RDONLY) < 0) ||
 	    (open("/dev/null", O_WRONLY) < 0) ||
@@ -328,6 +442,10 @@
 	if (setenv("LANG", "C", 1))
 		perror("Cannot set LANG to C");
 
+#ifdef linux
+	_systemd_activation = _systemd_handover(&s);
+#endif
+
 	if (!s.foreground)
 		_daemonise();
 
@@ -354,11 +472,12 @@
 	signal(SIGPIPE, SIG_IGN);
 
 #ifdef linux
-	if (s.avoid_oom && !_set_oom_adj(OOM_DISABLE) && !_set_oom_adj(OOM_ADJUST_MIN))
-		syslog(LOG_ERR, "Failed to set oom_adj to protect against OOM killer");
+	/* Systemd has adjusted oom killer for us already */
+	if (s.avoid_oom && !_systemd_activation && !_protect_against_oom_killer())
+		syslog(LOG_ERR, "Failed to protect against OOM killer");
 #endif
 
-	if (s.socket_path) {
+	if (!_systemd_activation && s.socket_path) {
 		s.socket_fd = _open_socket(s);
 		if (s.socket_fd < 0)
 			failed = 1;



             reply	other threads:[~2012-02-28 13:05 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-28 13:05 prajnoha [this message]
  -- strict thread matches above, loose matches on Subject: below --
2012-02-28 14:25 LVM2/daemons/common daemon-server.c zkabelac
2012-01-25 21:30 zkabelac
2012-01-15 10:33 mornfall
2011-07-20 18:23 mornfall

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=20120228130521.28603.qmail@sourceware.org \
    --to=prajnoha@sourceware.org \
    --cc=lvm-devel@redhat.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.