Launch mdmon via systemctl to avoid it ending up in the wrong cgroup

Resolves bz879327

Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
This commit is contained in:
Jes Sorensen 2013-01-21 14:36:26 +01:00
parent d047b34df2
commit 34d880fc4c
3 changed files with 188 additions and 57 deletions

View File

@ -0,0 +1,160 @@
From df9a354667f1a8b2994cf73a4d396766bc565a91 Mon Sep 17 00:00:00 2001
From: Jes Sorensen <Jes.Sorensen@redhat.com>
Date: Thu, 17 Jan 2013 18:06:43 +0100
Subject: [PATCH 1/1] Add support for launching mdmon via systemctl instead of
fork/exec
To launch mdmon via systemctl, a new command line argument is added to
mdadm '--systemctl'. Alternatively it is possible to set the
environment variable MDMON_SYSTEMCTL.
This allows for having mdmon launched via systemctl which avoids
problems with it getting killed by systemd due to it ending up in the
parent's cgroup (udev).
Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
---
ReadMe.c | 2 ++
mdadm.c | 4 ++++
mdadm.h | 2 ++
mdmon.c | 4 +++-
util.c | 41 ++++++++++++++++++++++++++++++-----------
6 files changed, 47 insertions(+), 12 deletions(-)
diff --git a/ReadMe.c b/ReadMe.c
index 0aa8cbd..69b8597 100644
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -95,6 +95,7 @@ struct option long_options[] = {
{"update-subarray", 1, 0, UpdateSubarray},
{"udev-rules", 2, 0, UdevRules},
{"offroot", 0, 0, OffRootOpt},
+ {"systemctl", 0, 0, SystemctlOpt},
/* synonyms */
{"monitor", 0, 0, 'F'},
@@ -261,6 +262,7 @@ char OptionHelp[] =
" application was launched from initrd/initramfs and\n"
" should not be shutdown by systemd as part of the\n"
" regular shutdown process.\n"
+" --systemctl : Use systemctl to launch mdmon rather than exec/fork\n"
;
/*
"\n"
diff --git a/mdadm.c b/mdadm.c
index 11016e7..4c8d382 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -176,6 +176,10 @@ int main(int argc, char *argv[])
prefer = NULL;
continue;
+ case SystemctlOpt:
+ __mdmon_systemctl = 1;
+ continue;
+
case ':':
case '?':
fputs(Usage, stderr);
diff --git a/mdadm.h b/mdadm.h
index f1352e3..54874cb 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -337,6 +337,7 @@ enum special_options {
Continue,
OffRootOpt,
Prefer,
+ SystemctlOpt,
};
/* structures read from config file */
@@ -1485,3 +1486,4 @@ char *xstrdup(const char *str);
#define MAX_DISKS 4096
extern int __offroot;
+extern int __mdmon_systemctl;
diff --git a/mdmon.c b/mdmon.c
index 5d5ae94..7459ae2 100644
--- a/mdmon.c
+++ b/mdmon.c
@@ -188,7 +188,9 @@ static void try_kill_monitor(pid_t pid, char *devname, int sock)
* might be "@dmon"
*/
if (n < 0 || !(strstr(buf, "mdmon") ||
- strstr(buf, "@dmon")))
+ strstr(buf, "@dmon") ||
+ strstr(buf, "/usr/sbin/mdmon") ||
+ strstr(buf, "@usr/sbin/mdmon")))
return;
kill(pid, SIGTERM);
diff --git a/util.c b/util.c
index 6c10365..8202748 100644
--- a/util.c
+++ b/util.c
@@ -33,6 +33,7 @@
#include <signal.h>
int __offroot;
+int __mdmon_systemctl = 1;
/*
* following taken from linux/blkpg.h because they aren't
@@ -1651,6 +1652,9 @@ int start_mdmon(int devnum)
if (check_env("MDADM_NO_MDMON"))
return 0;
+ if (check_env("MDMON_SYSTEMCTL"))
+ __mdmon_systemctl = 1;
+
len = readlink("/proc/self/exe", pathbuf, sizeof(pathbuf)-1);
if (len > 0) {
char *sl;
@@ -1651,18 +1655,33 @@ int start_mdmon(int devnum)
else
skipped = 0;
- for (i=0; paths[i]; i++)
- if (paths[i][0]) {
- if (__offroot) {
- execl(paths[i], "mdmon", "--offroot",
- devnum2devname(devnum),
- NULL);
- } else {
- execl(paths[i], "mdmon",
- devnum2devname(devnum),
- NULL);
- }
+ if (__mdmon_systemctl) {
+ if (__offroot) {
+ snprintf(pathbuf, 40, "mdmon-offroot@%s.service",
+ devnum2devname(devnum));
+ execl("/usr/bin/systemctl", "systemctl",
+ "start", pathbuf, NULL);
+ } else {
+ snprintf(pathbuf, 30, "mdmon@%s.service",
+ devnum2devname(devnum));
+ execl("/usr/bin/systemctl", "systemctl",
+ "start", pathbuf, NULL);
}
+ } else {
+ for (i = 0; paths[i]; i++)
+ if (paths[i][0]) {
+ if (__offroot) {
+ execl(paths[i], "mdmon",
+ "--offroot",
+ devnum2devname(devnum),
+ NULL);
+ } else {
+ execl(paths[i], "mdmon",
+ devnum2devname(devnum),
+ NULL);
+ }
+ }
+ }
exit(1);
case -1: fprintf(stderr, Name ": cannot run mdmon. "
"Array remains readonly\n");
--
1.7.11.7

View File

@ -1,38 +0,0 @@
diff -up mdadm-3.2.6/util.c.cgroup mdadm-3.2.6/util.c
--- mdadm-3.2.6/mdmon.c.cgroup 2012-11-15 16:48:03.327035349 -0500
+++ mdadm-3.2.6/mdmon.c 2012-11-15 17:07:16.628751041 -0500
@@ -386,6 +386,25 @@
return mdmon(devname, devnum, do_fork(), takeover);
}
+int set_cgroup(char *group)
+{
+ char pid[8];
+ char pathbuf[PATH_MAX];
+ int tasks_fd, n;
+
+ snprintf(pathbuf, PATH_MAX, "/sys/fs/cgroup/%s/tasks", group);
+ tasks_fd = open(pathbuf, O_WRONLY);
+ if (tasks_fd >= 0) {
+ snprintf(pid, sizeof(pid), "%d", getpid());
+ n = write(tasks_fd, pid, strlen(pid));
+ close(tasks_fd);
+ if (n != (int)strlen(pid)) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
static int mdmon(char *devname, int devnum, int must_fork, int takeover)
{
int mdfd;
@@ -438,6 +457,8 @@
} else
pfd[0] = pfd[1] = -1;
+ set_cgroup("systemd");
+
container = calloc(1, sizeof(*container));
container->devnum = devnum;
container->devname = devname;

View File

@ -1,7 +1,7 @@
Summary: The mdadm program controls Linux md devices (software RAID arrays) Summary: The mdadm program controls Linux md devices (software RAID arrays)
Name: mdadm Name: mdadm
Version: 3.2.6 Version: 3.2.6
Release: 11%{?dist} Release: 12%{?dist}
Source: http://www.kernel.org/pub/linux/utils/raid/mdadm/mdadm-%{version}.tar.xz Source: http://www.kernel.org/pub/linux/utils/raid/mdadm/mdadm-%{version}.tar.xz
Source1: mdmonitor.init Source1: mdmonitor.init
Source2: raid-check Source2: raid-check
@ -9,15 +9,17 @@ Source3: mdadm.rules
Source4: mdadm-raid-check-sysconfig Source4: mdadm-raid-check-sysconfig
Source5: mdadm-cron Source5: mdadm-cron
Source6: mdmonitor.service Source6: mdmonitor.service
Source8: mdadm.conf Source7: mdmon-offroot@.service
Source9: mdadm_event.conf Source8: mdmon@.service
Patch0: mdadm-3.2.6-cgroup.patch Source9: mdadm.conf
Source10: mdadm_event.conf
Patch1: mdadm-3.2.6-Create.c-check-if-freesize-is-equal-0.patch Patch1: mdadm-3.2.6-Create.c-check-if-freesize-is-equal-0.patch
Patch2: mdadm-3.2.6-imsm-Forbid-spanning-between-multiple-controllers.patch Patch2: mdadm-3.2.6-imsm-Forbid-spanning-between-multiple-controllers.patch
Patch96: mdadm-3.2.6-Add-support-for-launching-mdmon-via-systemctl-instea.patch
# Fedora customization patches # Fedora customization patches
Patch97: mdadm-3.2.6-udev.patch Patch97: mdadm-3.2.6-udev.patch
Patch98: mdadm-2.5.2-static.patch Patch98: mdadm-2.5.2-static.patch
# Fedora 15, 16, 17 - only # Fedora 16, 17 - only
Patch99: mdadm-3.2.4-map-dir.patch Patch99: mdadm-3.2.4-map-dir.patch
URL: http://www.kernel.org/pub/linux/utils/raid/mdadm/ URL: http://www.kernel.org/pub/linux/utils/raid/mdadm/
License: GPLv2+ License: GPLv2+
@ -26,18 +28,15 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
Obsoletes: mdctl,raidtools Obsoletes: mdctl,raidtools
%if "%{fedora}" >= "18" %if "%{fedora}" >= "18"
Obsoletes: mdadm-sysvinit Obsoletes: mdadm-sysvinit
%endif Conflicts: dracut < 024-23
BuildRequires: systemd-units binutils-devel
%if "%{fedora}" <= "17"
Requires(post): systemd-units systemd-sysv chkconfig coreutils
%else
Requires(post): systemd-units chkconfig coreutils Requires(post): systemd-units chkconfig coreutils
%endif %else
Requires(preun): systemd-units Requires(post): systemd-units systemd-sysv chkconfig coreutils
Requires(postun): systemd-units coreutils
%if "%{fedora}" <= "17"
Requires: udev initscripts Requires: udev initscripts
%endif %endif
BuildRequires: systemd-units binutils-devel
Requires(preun): systemd-units
Requires(postun): systemd-units coreutils
%if "%{fedora}" >= "17" %if "%{fedora}" >= "17"
Requires: libreport-filesystem Requires: libreport-filesystem
Conflicts: dracut < 009-14 Conflicts: dracut < 009-14
@ -66,9 +65,9 @@ is not used as the system init process.
%prep %prep
%setup -q %setup -q
# Only apply cgroups workaround on F18 and higher # Use systemctl to launch mdmon on F18 and higher
%if "%{fedora}" >= "18" %if "%{fedora}" >= "18"
%patch0 -p1 -b .cgroup %patch96 -p1 -b .sysctl
%endif %endif
%patch1 -p1 -b .raidsize %patch1 -p1 -b .raidsize
@ -77,7 +76,7 @@ is not used as the system init process.
# Fedora customization patches # Fedora customization patches
%patch97 -p1 -b .udev %patch97 -p1 -b .udev
%patch98 -p1 -b .static %patch98 -p1 -b .static
# Fedora 15, 16, 17 - only # Fedora 16, 17 - only
%if "%{fedora}" <= "17" %if "%{fedora}" <= "17"
%patch99 -p1 -b .map-dir %patch99 -p1 -b .map-dir
%endif %endif
@ -100,17 +99,19 @@ mkdir -p -m 700 %{buildroot}/var/run/mdadm
# systemd # systemd
mkdir -p %{buildroot}%{_unitdir} mkdir -p %{buildroot}%{_unitdir}
install -m644 %{SOURCE6} %{buildroot}%{_unitdir} install -m644 %{SOURCE6} %{buildroot}%{_unitdir}
install -m644 %{SOURCE7} %{buildroot}%{_unitdir}
install -m644 %{SOURCE8} %{buildroot}%{_unitdir}
# tmpfile # tmpfile
mkdir -p %{buildroot}%{_prefix}/lib/tmpfiles.d mkdir -p %{buildroot}%{_prefix}/lib/tmpfiles.d
install -m 0644 %{SOURCE8} %{buildroot}%{_prefix}/lib/tmpfiles.d/%{name}.conf install -m 0644 %{SOURCE9} %{buildroot}%{_prefix}/lib/tmpfiles.d/%{name}.conf
mkdir -p %{buildroot}%{_localstatedir}/run/ mkdir -p %{buildroot}%{_localstatedir}/run/
install -d -m 0710 %{buildroot}%{_localstatedir}/run/%{name}/ install -d -m 0710 %{buildroot}%{_localstatedir}/run/%{name}/
# abrt # abrt
%if "%{fedora}" >= "17" %if "%{fedora}" >= "17"
mkdir -p %{buildroot}/etc/libreport/events.d mkdir -p %{buildroot}/etc/libreport/events.d
install -m644 %{SOURCE9} %{buildroot}/etc/libreport/events.d install -m644 %{SOURCE10} %{buildroot}/etc/libreport/events.d
%endif %endif
%clean %clean
@ -144,6 +145,8 @@ rm -rf %{buildroot}
/sbin/* /sbin/*
%{_sbindir}/raid-check %{_sbindir}/raid-check
%{_unitdir}/mdmonitor.service %{_unitdir}/mdmonitor.service
%{_unitdir}/mdmon-offroot@.service
%{_unitdir}/mdmon@.service
%{_mandir}/man*/md* %{_mandir}/man*/md*
%config(noreplace) %{_sysconfdir}/cron.d/* %config(noreplace) %{_sysconfdir}/cron.d/*
%config(noreplace) %{_sysconfdir}/sysconfig/* %config(noreplace) %{_sysconfdir}/sysconfig/*
@ -159,6 +162,12 @@ rm -rf %{buildroot}
%endif %endif
%changelog %changelog
* Mon Jan 21 2013 Jes Sorensen <Jes.Sorensen@redhat.com> - 3.2.6-12
- Launch mdmon via systemctl to avoid it ending up in the wrong cgroup
and getting killed in the boot process when switching from the
initrd to the real root.
- Resolves bz879327
* Tue Jan 8 2013 Jes Sorensen <Jes.Sorensen@redhat.com> - 3.2.6-11 * Tue Jan 8 2013 Jes Sorensen <Jes.Sorensen@redhat.com> - 3.2.6-11
- Move code to leave udev cgroup into mdmon and excute it after we - Move code to leave udev cgroup into mdmon and excute it after we
work, to make sure it actually does the right thing. work, to make sure it actually does the right thing.