From 056a28e80778f0b1be02906a986d94642be1bfe7 Mon Sep 17 00:00:00 2001 From: Peter Rajnoha Date: Thu, 28 Jul 2011 19:49:05 +0200 Subject: [PATCH] More systemd support. --- lvm2-add-systemd-units.patch | 44 ++++++-- lvm2-new-oom-adj-interface.patch | 116 +++++++++++++++++++++ lvm2-systemd-fds-handover.patch | 167 +++++++++++++++++++++++++++++++ lvm2.spec | 22 +++- 4 files changed, 337 insertions(+), 12 deletions(-) create mode 100644 lvm2-new-oom-adj-interface.patch create mode 100644 lvm2-systemd-fds-handover.patch diff --git a/lvm2-add-systemd-units.patch b/lvm2-add-systemd-units.patch index e2755c7..49bba6b 100644 --- a/lvm2-add-systemd-units.patch +++ b/lvm2-add-systemd-units.patch @@ -1,14 +1,40 @@ - scripts/dm_event_systemd_red_hat.service.in | 13 +++++++++++++ - scripts/dm_event_systemd_red_hat.socket | 10 ++++++++++ + WHATS_NEW | 4 ++++ + WHATS_NEW_DM | 4 ++++ + scripts/dm_event_systemd_red_hat.service.in | 14 ++++++++++++++ + scripts/dm_event_systemd_red_hat.socket | 11 +++++++++++ scripts/lvm2_monitoring_systemd_red_hat.service.in | 17 +++++++++++++++++ - 3 files changed, 40 insertions(+), 0 deletions(-) + 5 files changed, 50 insertions(+), 0 deletions(-) +diff --git a/WHATS_NEW b/WHATS_NEW +index ddb04ad..f8bb79e 100644 +--- a/WHATS_NEW ++++ b/WHATS_NEW +@@ -1,3 +1,7 @@ ++Version 2.02.87 - ++=============================== ++ Add systemd unit file to provide lvm2 monitoring. ++ + Version 2.02.86 - 8th July 2011 + =============================== + Remove unnecessary warning in pvcreate for MD linear devices. +diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM +index 5e4aeaf..b6a5360 100644 +--- a/WHATS_NEW_DM ++++ b/WHATS_NEW_DM +@@ -1,3 +1,7 @@ ++Version 1.02.66 - ++=============================== ++ Add systemd unit files for dmeventd. ++ + Version 1.02.65 - 8th July 2011 + =============================== + Remove dev name prefix from dmsetup line output if exactly one dev requested. diff --git a/scripts/dm_event_systemd_red_hat.service.in b/scripts/dm_event_systemd_red_hat.service.in new file mode 100644 -index 0000000..3e18c69 +index 0000000..32295d3 --- /dev/null +++ b/scripts/dm_event_systemd_red_hat.service.in -@@ -0,0 +1,13 @@ +@@ -0,0 +1,14 @@ +[Unit] +Description=Device-mapper event daemon +After=fedora-storage-init.service fedora-storage-init-late.service @@ -19,15 +45,16 @@ index 0000000..3e18c69 +Type=forking +ExecStart=@sbindir@/dmeventd +PIDFile=@DMEVENTD_PIDFILE@ ++OOMScoreAdjust=-1000 + +[Install] +WantedBy=sysinit.target diff --git a/scripts/dm_event_systemd_red_hat.socket b/scripts/dm_event_systemd_red_hat.socket new file mode 100644 -index 0000000..45c02dd +index 0000000..c580555 --- /dev/null +++ b/scripts/dm_event_systemd_red_hat.socket -@@ -0,0 +1,10 @@ +@@ -0,0 +1,11 @@ +[Unit] +Description=Device-mapper event daemon FIFOs +DefaultDependencies=no @@ -35,12 +62,13 @@ index 0000000..45c02dd +[Socket] +ListenFIFO=/var/run/dmeventd-server +ListenFIFO=/var/run/dmeventd-client ++SocketMode=0600 + +[Install] +WantedBy=sockets.target diff --git a/scripts/lvm2_monitoring_systemd_red_hat.service.in b/scripts/lvm2_monitoring_systemd_red_hat.service.in new file mode 100644 -index 0000000..c284bbb +index 0000000..4715416 --- /dev/null +++ b/scripts/lvm2_monitoring_systemd_red_hat.service.in @@ -0,0 +1,17 @@ diff --git a/lvm2-new-oom-adj-interface.patch b/lvm2-new-oom-adj-interface.patch new file mode 100644 index 0000000..50b2014 --- /dev/null +++ b/lvm2-new-oom-adj-interface.patch @@ -0,0 +1,116 @@ + WHATS_NEW_DM | 1 + + daemons/dmeventd/dmeventd.c | 61 +++++++++++++++++++++++++++++------------- + 2 files changed, 43 insertions(+), 19 deletions(-) + +diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM +index b6a5360..868a469 100644 +--- a/WHATS_NEW_DM ++++ b/WHATS_NEW_DM +@@ -1,5 +1,6 @@ + Version 1.02.66 - + =============================== ++ Add support for new oom killer adjustment interface (oom_score_adj). + Add systemd unit files for dmeventd. + + Version 1.02.65 - 8th July 2011 +diff --git a/daemons/dmeventd/dmeventd.c b/daemons/dmeventd/dmeventd.c +index 1a91cb8..a6956cb 100644 +--- a/daemons/dmeventd/dmeventd.c ++++ b/daemons/dmeventd/dmeventd.c +@@ -41,11 +41,19 @@ + #ifdef linux + # include + +-# define OOM_ADJ_FILE "/proc/self/oom_adj" ++/* ++ * 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) + + #endif + +@@ -1594,33 +1602,48 @@ static void _exit_handler(int sig __attribute__((unused))) + } + + #ifdef linux ++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() + { +- 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; +- } + +- if (!(fp = fopen(OOM_ADJ_FILE, "w"))) { +- perror(OOM_ADJ_FILE ": fopen failed"); +- return 0; +- } ++ /* 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; ++ } + +- fprintf(fp, "%i", val); +- if (dm_fclose(fp)) +- perror(OOM_ADJ_FILE ": fclose failed"); ++ return _set_oom_adj(OOM_ADJ_FILE_OLD, OOM_DISABLE) || ++ _set_oom_adj(OOM_ADJ_FILE_OLD, OOM_ADJUST_MIN); ++ } + +- return 1; ++ return _set_oom_adj(OOM_ADJ_FILE, OOM_SCORE_ADJ_MIN); + } + #endif + +@@ -1829,8 +1852,8 @@ int main(int argc, char *argv[]) + signal(SIGQUIT, &_exit_handler); + + #ifdef linux +- if (!_set_oom_adj(OOM_DISABLE) && !_set_oom_adj(OOM_ADJUST_MIN)) +- syslog(LOG_ERR, "Failed to set oom_adj to protect against OOM killer"); ++ if (!_protect_against_oom_killer()) ++ syslog(LOG_ERR, "Failed to protect against OOM killer"); + #endif + + _init_thread_signals(); diff --git a/lvm2-systemd-fds-handover.patch b/lvm2-systemd-fds-handover.patch new file mode 100644 index 0000000..5487fa6 --- /dev/null +++ b/lvm2-systemd-fds-handover.patch @@ -0,0 +1,167 @@ + WHATS_NEW_DM | 1 + + daemons/dmeventd/dmeventd.c | 95 +++++++++++++++++++++++++++++++++++++++++-- + 2 files changed, 92 insertions(+), 4 deletions(-) + +diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM +index 868a469..d09a50c 100644 +--- a/WHATS_NEW_DM ++++ b/WHATS_NEW_DM +@@ -1,5 +1,6 @@ + Version 1.02.66 - + =============================== ++ Add support for systemd file descriptor handover to dmeventd. + Add support for new oom killer adjustment interface (oom_score_adj). + Add systemd unit files for dmeventd. + +diff --git a/daemons/dmeventd/dmeventd.c b/daemons/dmeventd/dmeventd.c +index a6956cb..ec514ee 100644 +--- a/daemons/dmeventd/dmeventd.c ++++ b/daemons/dmeventd/dmeventd.c +@@ -55,6 +55,13 @@ + /* 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_FIFO_SERVER SD_LISTEN_FDS_START ++# define SD_FD_FIFO_CLIENT (SD_LISTEN_FDS_START + 1) ++ + #endif + + /* FIXME We use syslog for now, because multilog is not yet implemented */ +@@ -104,6 +111,7 @@ static pthread_mutex_t _global_mutex; + #define THREAD_STACK_SIZE (300*1024) + + int dmeventd_debug = 0; ++static int _systemd_activation = 0; + static int _foreground = 0; + static int _restart = 0; + static char **_initial_registrations = 0; +@@ -1710,8 +1718,13 @@ static void _daemonize(void) + else + fd = rlim.rlim_cur; + +- for (--fd; fd >= 0; fd--) ++ for (--fd; fd >= 0; fd--) { ++ /* Do not close fds preloaded by systemd! */ ++ if (_systemd_activation && ++ (fd == SD_FD_FIFO_SERVER || fd == SD_FD_FIFO_CLIENT)) ++ continue; + close(fd); ++ } + + if ((open("/dev/null", O_RDONLY) < 0) || + (open("/dev/null", O_WRONLY) < 0) || +@@ -1780,6 +1793,76 @@ static void restart(void) + fini_fifos(&fifos); + } + ++static int _handle_preloaded_fifo(int fd, const char *path) ++{ ++ struct stat st_fd, st_path; ++ int flags; ++ ++ if ((flags = fcntl(fd, F_GETFD)) < 0) ++ return 0; ++ ++ if (flags & FD_CLOEXEC) ++ return 0; ++ ++ if (fstat(fd, &st_fd) < 0 || !S_ISFIFO(st_fd.st_mode)) ++ return 0; ++ ++ if (stat(path, &st_path) < 0 || ++ st_path.st_dev != st_fd.st_dev || ++ st_path.st_ino != st_fd.st_ino) ++ return 0; ++ ++ if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) ++ return 0; ++ ++ return 1; ++} ++ ++static int _systemd_handover(struct dm_event_fifos *fifos) ++{ ++ const char *e; ++ char *p; ++ unsigned long env_pid, env_listen_fds; ++ int r = 0; ++ ++ memset(fifos, 0, sizeof(*fifos)); ++ ++ /* 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) ++ goto out; ++ ++ /* LISTEN_FDS must be 2 and the fds must be FIFOSs! */ ++ 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 != 2) ++ goto out; ++ ++ /* Check and handle the FIFOs passed in */ ++ r = (_handle_preloaded_fifo(SD_FD_FIFO_SERVER, DM_EVENT_FIFO_SERVER) && ++ _handle_preloaded_fifo(SD_FD_FIFO_CLIENT, DM_EVENT_FIFO_CLIENT)); ++ ++ if (r) { ++ fifos->server = SD_FD_FIFO_SERVER; ++ fifos->server_path = DM_EVENT_FIFO_SERVER; ++ fifos->client = SD_FD_FIFO_CLIENT; ++ fifos->client_path = DM_EVENT_FIFO_CLIENT; ++ } ++ ++out: ++ unsetenv(SD_LISTEN_PID_ENV_VAR_NAME); ++ unsetenv(SD_LISTEN_FDS_ENV_VAR_NAME); ++ return r; ++} ++ + static void usage(char *prog, FILE *file) + { + fprintf(file, "Usage:\n" +@@ -1834,6 +1917,8 @@ int main(int argc, char *argv[]) + if (_restart) + restart(); + ++ _systemd_activation = _systemd_handover(&fifos); ++ + if (!_foreground) + _daemonize(); + +@@ -1852,7 +1937,8 @@ int main(int argc, char *argv[]) + signal(SIGQUIT, &_exit_handler); + + #ifdef linux +- if (!_protect_against_oom_killer()) ++ /* Systemd has adjusted oom killer for us already */ ++ if (!_systemd_activation && !_protect_against_oom_killer()) + syslog(LOG_ERR, "Failed to protect against OOM killer"); + #endif + +@@ -1863,11 +1949,12 @@ int main(int argc, char *argv[]) + //multilog_init_verbose(std_syslog, _LOG_DEBUG); + //multilog_async(1); + +- _init_fifos(&fifos); ++ if (!_systemd_activation) ++ _init_fifos(&fifos); + + pthread_mutex_init(&_global_mutex, NULL); + +- if (_open_fifos(&fifos)) ++ if (!_systemd_activation && _open_fifos(&fifos)) + exit(EXIT_FIFO_FAILURE); + + /* Signal parent, letting them know we are ready to go. */ diff --git a/lvm2.spec b/lvm2.spec index 128d4ea..3636b35 100644 --- a/lvm2.spec +++ b/lvm2.spec @@ -39,7 +39,7 @@ Summary: Userland logical volume management tools Name: lvm2 Version: 2.02.86 -Release: 3%{?dist} +Release: 4%{?dist} License: GPLv2 Group: System Environment/Base URL: http://sources.redhat.com/lvm2 @@ -51,6 +51,8 @@ Patch0: lvm2-set-default-preferred_names.patch Patch1: lvm2-add-systemd-units.patch Patch2: lvm2-systemd-conf-make-support.patch Patch3: lvm2-autoreconf.patch +Patch4: lvm2-new-oom-adj-interface.patch +Patch5: lvm2-systemd-fds-handover.patch BuildRequires: libselinux-devel >= 1.30.19-4, libsepol-devel BuildRequires: ncurses-devel @@ -93,6 +95,8 @@ or more physical volumes and creating one or more logical volumes %patch1 -p1 -b .systemd_units %patch2 -p1 -b .systemd_conf_make %patch3 -p1 -b .autoreconf +%patch4 -p1 -b .oom_adj +%patch5 -p1 -b .systemd_fds %build %define _exec_prefix "" @@ -528,9 +532,15 @@ fi %postun -n device-mapper-event %if %{enable_systemd} /bin/systemctl daemon-reload > /dev/null 2>&1 || : -if [ $1 -ge 1 ]; then - /bin/systemctl try-restart dm-event.service > /dev/null 2>&1 || : -fi +# +# We'd need systemd to call specific restart command (dmeventd -R) instead +# of simple 'stop and start' - we need to keep any existing dmeventd +# registrations. Also, we can't kill dmeventd with existing registrations +# with SIGTERM, we would need to use SIGKILL instead (but losing registrations). +# +# if [ $1 -ge 1 ]; then +# /bin/systemctl try-restart dm-event.service > /dev/null 2>&1 || : +# fi %endif %files -n device-mapper-event @@ -583,6 +593,10 @@ the device-mapper event library. /usr%{_libdir}/pkgconfig/devmapper-event.pc %changelog +* Thu Jul 28 2011 Peter Rajnoha - 2.02.86-4 +- Add support for systemd file descriptor handover to dmeventd. +- Add support for new oom killer adjustment interface (oom_score_adj). + * Wed Jul 20 2011 Peter Rajnoha - 2.02.86-3 - Fix broken lvm2-sysinit Requires: lvm2 dependency.