From 34d880fc4c7b10e39a83c949f4b9348745431c71 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Mon, 21 Jan 2013 14:36:26 +0100 Subject: [PATCH] Launch mdmon via systemctl to avoid it ending up in the wrong cgroup Resolves bz879327 Signed-off-by: Jes Sorensen --- ...launching-mdmon-via-systemctl-instea.patch | 160 ++++++++++++++++++ mdadm-3.2.6-cgroup.patch | 38 ----- mdadm.spec | 47 ++--- 3 files changed, 188 insertions(+), 57 deletions(-) create mode 100644 mdadm-3.2.6-Add-support-for-launching-mdmon-via-systemctl-instea.patch delete mode 100644 mdadm-3.2.6-cgroup.patch diff --git a/mdadm-3.2.6-Add-support-for-launching-mdmon-via-systemctl-instea.patch b/mdadm-3.2.6-Add-support-for-launching-mdmon-via-systemctl-instea.patch new file mode 100644 index 0000000..d9301d4 --- /dev/null +++ b/mdadm-3.2.6-Add-support-for-launching-mdmon-via-systemctl-instea.patch @@ -0,0 +1,160 @@ +From df9a354667f1a8b2994cf73a4d396766bc565a91 Mon Sep 17 00:00:00 2001 +From: Jes Sorensen +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 +--- + 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 + + 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 + diff --git a/mdadm-3.2.6-cgroup.patch b/mdadm-3.2.6-cgroup.patch deleted file mode 100644 index 69638bd..0000000 --- a/mdadm-3.2.6-cgroup.patch +++ /dev/null @@ -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; diff --git a/mdadm.spec b/mdadm.spec index fd10d8c..6a22265 100644 --- a/mdadm.spec +++ b/mdadm.spec @@ -1,7 +1,7 @@ Summary: The mdadm program controls Linux md devices (software RAID arrays) Name: mdadm Version: 3.2.6 -Release: 11%{?dist} +Release: 12%{?dist} Source: http://www.kernel.org/pub/linux/utils/raid/mdadm/mdadm-%{version}.tar.xz Source1: mdmonitor.init Source2: raid-check @@ -9,15 +9,17 @@ Source3: mdadm.rules Source4: mdadm-raid-check-sysconfig Source5: mdadm-cron Source6: mdmonitor.service -Source8: mdadm.conf -Source9: mdadm_event.conf -Patch0: mdadm-3.2.6-cgroup.patch +Source7: mdmon-offroot@.service +Source8: mdmon@.service +Source9: mdadm.conf +Source10: mdadm_event.conf 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 +Patch96: mdadm-3.2.6-Add-support-for-launching-mdmon-via-systemctl-instea.patch # Fedora customization patches Patch97: mdadm-3.2.6-udev.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 URL: http://www.kernel.org/pub/linux/utils/raid/mdadm/ License: GPLv2+ @@ -26,18 +28,15 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) Obsoletes: mdctl,raidtools %if "%{fedora}" >= "18" Obsoletes: mdadm-sysvinit -%endif -BuildRequires: systemd-units binutils-devel -%if "%{fedora}" <= "17" -Requires(post): systemd-units systemd-sysv chkconfig coreutils -%else +Conflicts: dracut < 024-23 Requires(post): systemd-units chkconfig coreutils -%endif -Requires(preun): systemd-units -Requires(postun): systemd-units coreutils -%if "%{fedora}" <= "17" +%else +Requires(post): systemd-units systemd-sysv chkconfig coreutils Requires: udev initscripts %endif +BuildRequires: systemd-units binutils-devel +Requires(preun): systemd-units +Requires(postun): systemd-units coreutils %if "%{fedora}" >= "17" Requires: libreport-filesystem Conflicts: dracut < 009-14 @@ -66,9 +65,9 @@ is not used as the system init process. %prep %setup -q -# Only apply cgroups workaround on F18 and higher +# Use systemctl to launch mdmon on F18 and higher %if "%{fedora}" >= "18" -%patch0 -p1 -b .cgroup +%patch96 -p1 -b .sysctl %endif %patch1 -p1 -b .raidsize @@ -77,7 +76,7 @@ is not used as the system init process. # Fedora customization patches %patch97 -p1 -b .udev %patch98 -p1 -b .static -# Fedora 15, 16, 17 - only +# Fedora 16, 17 - only %if "%{fedora}" <= "17" %patch99 -p1 -b .map-dir %endif @@ -100,17 +99,19 @@ mkdir -p -m 700 %{buildroot}/var/run/mdadm # systemd mkdir -p %{buildroot}%{_unitdir} install -m644 %{SOURCE6} %{buildroot}%{_unitdir} +install -m644 %{SOURCE7} %{buildroot}%{_unitdir} +install -m644 %{SOURCE8} %{buildroot}%{_unitdir} # tmpfile 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/ install -d -m 0710 %{buildroot}%{_localstatedir}/run/%{name}/ # abrt %if "%{fedora}" >= "17" mkdir -p %{buildroot}/etc/libreport/events.d -install -m644 %{SOURCE9} %{buildroot}/etc/libreport/events.d +install -m644 %{SOURCE10} %{buildroot}/etc/libreport/events.d %endif %clean @@ -144,6 +145,8 @@ rm -rf %{buildroot} /sbin/* %{_sbindir}/raid-check %{_unitdir}/mdmonitor.service +%{_unitdir}/mdmon-offroot@.service +%{_unitdir}/mdmon@.service %{_mandir}/man*/md* %config(noreplace) %{_sysconfdir}/cron.d/* %config(noreplace) %{_sysconfdir}/sysconfig/* @@ -159,6 +162,12 @@ rm -rf %{buildroot} %endif %changelog +* Mon Jan 21 2013 Jes Sorensen - 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 - 3.2.6-11 - Move code to leave udev cgroup into mdmon and excute it after we work, to make sure it actually does the right thing.