public inbox for lvm2-cvs@sourceware.org help / color / mirror / Atom feed
From: prajnoha@sourceware.org To: lvm-devel@redhat.com, lvm2-cvs@sourceware.org Subject: LVM2/daemons/common daemon-server.c Date: Tue, 28 Feb 2012 13:05:00 -0000 [thread overview] Message-ID: <20120228130521.28603.qmail@sourceware.org> (raw) CVSROOT: /cvs/lvm2 Module name: LVM2 Changes by: prajnoha@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;
next 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 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 \ --cc=lvm2-cvs@sourceware.org \ /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: linkBe 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 read-only IMAP folder(s) and NNTP newsgroup(s).