Blame SOURCES/bz1477461-2-main-Add-support-for-libcgroup.patch

df4b1e
From c56086c701d08fc17cf6d8ef603caf505a4021b7 Mon Sep 17 00:00:00 2001
df4b1e
From: Jan Friesse <jfriesse@redhat.com>
df4b1e
Date: Fri, 28 Jul 2017 16:32:58 +0200
df4b1e
Subject: [PATCH] main: Add support for libcgroup
df4b1e
df4b1e
When corosync is started in environment where it ends in cgroup without
df4b1e
properly set rt_runtime_us it's impossible to get RT priority.
df4b1e
df4b1e
Already implemented workaround is to use higher non-RT priority.
df4b1e
df4b1e
This patch implements another solution. It moves corosync into root cpu
df4b1e
cgroup. Root cpu cgroup hopefully has enough RT budget.
df4b1e
df4b1e
Another solution was mentioned on ML
df4b1e
https://lists.freedesktop.org/archives/systemd-devel/2017-July/039353.html
df4b1e
but this means to generate some "random" values.
df4b1e
df4b1e
Signed-off-by: Jan Friesse <jfriesse@redhat.com>
df4b1e
Reviewed-by: Fabio M. Di Nitto <fdinitto@redhat.com>
df4b1e
Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
df4b1e
---
df4b1e
 configure.ac     |   11 ++++++
df4b1e
 corosync.spec.in |    7 ++++
df4b1e
 exec/Makefile.am |    5 +++
df4b1e
 exec/main.c      |  105 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
df4b1e
 man/corosync.8   |    6 +++-
df4b1e
 5 files changed, 131 insertions(+), 3 deletions(-)
df4b1e
df4b1e
diff --git a/configure.ac b/configure.ac
df4b1e
index 81fc91b..e60bf1b 100644
df4b1e
--- a/configure.ac
df4b1e
+++ b/configure.ac
df4b1e
@@ -416,6 +416,10 @@ AC_ARG_ENABLE([qnetd],
df4b1e
 	[  --enable-qnetd                  : Quorum Net Daemon support ],,
df4b1e
 	[ enable_qnetd="no" ])
df4b1e
 AM_CONDITIONAL(BUILD_QNETD, test x$enable_qnetd = xyes)
df4b1e
+AC_ARG_ENABLE([libcgroup],
df4b1e
+	[  --enable-libcgroup                  : Enable libcgroup support ],,
df4b1e
+	[ enable_libcgroup="no" ])
df4b1e
+AM_CONDITIONAL(ENABLE_LIBCGROUP, test x$enable_libcgroup = xyes)
df4b1e
 
df4b1e
 # *FLAGS handling goes here
df4b1e
 
df4b1e
@@ -548,6 +552,13 @@ if test "x${enable_snmp}" = xyes; then
df4b1e
 fi
df4b1e
 AM_CONDITIONAL(BUILD_SNMP, test "${do_snmp}" = "1")
df4b1e
 
df4b1e
+if test "x${enable_libcgroup}" = xyes; then
df4b1e
+    PKG_CHECK_MODULES([libcgroup], [libcgroup])
df4b1e
+    AC_DEFINE_UNQUOTED([HAVE_LIBCGROUP], 1, [have libcgroup])
df4b1e
+    PACKAGE_FEATURES="$PACKAGE_FEATURES libcgroup"
df4b1e
+    WITH_LIST="$WITH_LIST --with libcgroup"
df4b1e
+fi
df4b1e
+
df4b1e
 # extra warnings
df4b1e
 EXTRA_WARNINGS=""
df4b1e
 
df4b1e
diff --git a/corosync.spec.in b/corosync.spec.in
df4b1e
index 97c8e03..49d7b7e 100644
df4b1e
--- a/corosync.spec.in
df4b1e
+++ b/corosync.spec.in
df4b1e
@@ -17,6 +17,7 @@
df4b1e
 %bcond_with runautogen
df4b1e
 %bcond_with qdevices
df4b1e
 %bcond_with qnetd
df4b1e
+%bcond_with libcgroup
df4b1e
 
df4b1e
 %global gitver %{?numcomm:.%{numcomm}}%{?alphatag:.%{alphatag}}%{?dirty:.%{dirty}}
df4b1e
 %global gittarver %{?numcomm:.%{numcomm}}%{?alphatag:-%{alphatag}}%{?dirty:-%{dirty}}
df4b1e
@@ -74,6 +75,9 @@ Requires: nss-tools
df4b1e
 %if %{with qnetd}
df4b1e
 BuildRequires: sed
df4b1e
 %endif
df4b1e
+%if %{with libcgroup}
df4b1e
+BuildRequires: libcgroup-devel
df4b1e
+%endif
df4b1e
 
df4b1e
 BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
df4b1e
 
df4b1e
@@ -125,6 +129,9 @@ export rdmacm_LIBS=-lrdmacm \
df4b1e
 %if %{with qnetd}
df4b1e
 	--enable-qnetd \
df4b1e
 %endif
df4b1e
+%if %{with libcgroup}
df4b1e
+	--enable-libcgroup \
df4b1e
+%endif
df4b1e
 	--with-initddir=%{_initrddir} \
df4b1e
 	--with-systemddir=%{_unitdir} \
df4b1e
 	--with-upstartdir=%{_sysconfdir}/init \
df4b1e
diff --git a/exec/Makefile.am b/exec/Makefile.am
df4b1e
index 9ca7720..670daf6 100644
df4b1e
--- a/exec/Makefile.am
df4b1e
+++ b/exec/Makefile.am
df4b1e
@@ -78,5 +78,10 @@ corosync_LDADD		= libtotem_pg.la ../common_lib/libcorosync_common.la \
df4b1e
 
df4b1e
 corosync_DEPENDENCIES	= libtotem_pg.la ../common_lib/libcorosync_common.la
df4b1e
 
df4b1e
+if ENABLE_LIBCGROUP
df4b1e
+corosync_CFLAGS		+= $(libcgroup_CFLAGS)
df4b1e
+corosync_LDADD		+= $(libcgroup_LIBS)
df4b1e
+endif
df4b1e
+
df4b1e
 lint:
df4b1e
 	-splint $(LINT_FLAGS) $(CPPFLAGS) $(CFLAGS) *.c
df4b1e
diff --git a/exec/main.c b/exec/main.c
df4b1e
index 60c01a4..b3e7478 100644
df4b1e
--- a/exec/main.c
df4b1e
+++ b/exec/main.c
df4b1e
@@ -110,6 +110,10 @@
df4b1e
 #include <corosync/logsys.h>
df4b1e
 #include <corosync/icmap.h>
df4b1e
 
df4b1e
+#ifdef HAVE_LIBCGROUP
df4b1e
+#include <libcgroup.h>
df4b1e
+#endif
df4b1e
+
df4b1e
 #include "quorum.h"
df4b1e
 #include "totemsrp.h"
df4b1e
 #include "logconfig.h"
df4b1e
@@ -1134,12 +1138,95 @@ error_close:
df4b1e
 	return (err);
df4b1e
 }
df4b1e
 
df4b1e
+static int corosync_move_to_root_cgroup(void) {
df4b1e
+	int res = -1;
df4b1e
+#ifdef HAVE_LIBCGROUP
df4b1e
+	int cg_ret;
df4b1e
+	struct cgroup *root_cgroup = NULL;
df4b1e
+	struct cgroup_controller *root_cpu_cgroup_controller = NULL;
df4b1e
+	char *current_cgroup_path = NULL;
df4b1e
+
df4b1e
+	cg_ret = cgroup_init();
df4b1e
+	if (cg_ret) {
df4b1e
+		log_printf(LOGSYS_LEVEL_WARNING, "Unable to initialize libcgroup: %s ",
df4b1e
+		    cgroup_strerror(cg_ret));
df4b1e
+
df4b1e
+		goto exit_res;
df4b1e
+	}
df4b1e
+
df4b1e
+	cg_ret = cgroup_get_current_controller_path(getpid(), "cpu", &current_cgroup_path);
df4b1e
+	if (cg_ret) {
df4b1e
+		log_printf(LOGSYS_LEVEL_WARNING, "Unable to get current cpu cgroup path: %s ",
df4b1e
+		    cgroup_strerror(cg_ret));
df4b1e
+
df4b1e
+		goto exit_res;
df4b1e
+	}
df4b1e
+
df4b1e
+	if (strcmp(current_cgroup_path, "/") == 0) {
df4b1e
+		log_printf(LOGSYS_LEVEL_DEBUG, "Corosync is already in root cgroup path");
df4b1e
+
df4b1e
+		res = 0;
df4b1e
+		goto exit_res;
df4b1e
+	}
df4b1e
+
df4b1e
+	root_cgroup = cgroup_new_cgroup("/");
df4b1e
+	if (root_cgroup == NULL) {
df4b1e
+		log_printf(LOGSYS_LEVEL_WARNING, "Can't create root cgroup");
df4b1e
+
df4b1e
+		goto exit_res;
df4b1e
+	}
df4b1e
+
df4b1e
+	root_cpu_cgroup_controller = cgroup_add_controller(root_cgroup, "cpu");
df4b1e
+	if (root_cpu_cgroup_controller == NULL) {
df4b1e
+		log_printf(LOGSYS_LEVEL_WARNING, "Can't create root cgroup cpu controller");
df4b1e
+
df4b1e
+		goto exit_res;
df4b1e
+	}
df4b1e
+
df4b1e
+	cg_ret = cgroup_attach_task(root_cgroup);
df4b1e
+	if (cg_ret) {
df4b1e
+		log_printf(LOGSYS_LEVEL_WARNING, "Can't attach task to root cgroup: %s ",
df4b1e
+		    cgroup_strerror(cg_ret));
df4b1e
+
df4b1e
+		goto exit_res;
df4b1e
+	}
df4b1e
+
df4b1e
+	cg_ret = cgroup_get_current_controller_path(getpid(), "cpu", &current_cgroup_path);
df4b1e
+	if (cg_ret) {
df4b1e
+		log_printf(LOGSYS_LEVEL_WARNING, "Unable to get current cpu cgroup path: %s ",
df4b1e
+		    cgroup_strerror(cg_ret));
df4b1e
+
df4b1e
+		goto exit_res;
df4b1e
+	}
df4b1e
+
df4b1e
+	if (strcmp(current_cgroup_path, "/") == 0) {
df4b1e
+		log_printf(LOGSYS_LEVEL_NOTICE, "Corosync sucesfully moved to root cgroup");
df4b1e
+		res = 0;
df4b1e
+	} else {
df4b1e
+		log_printf(LOGSYS_LEVEL_WARNING, "Can't move Corosync to root cgroup");
df4b1e
+	}
df4b1e
+
df4b1e
+exit_res:
df4b1e
+	if (root_cgroup != NULL) {
df4b1e
+		cgroup_free(&root_cgroup);
df4b1e
+	}
df4b1e
+
df4b1e
+	/*
df4b1e
+	 * libcgroup doesn't define something like cgroup_fini so there is no way how to clean
df4b1e
+	 * it's cache. It has to be called when libcgroup authors decide to implement it.
df4b1e
+	 */
df4b1e
+
df4b1e
+#endif
df4b1e
+	 return (res);
df4b1e
+}
df4b1e
+
df4b1e
+
df4b1e
 int main (int argc, char **argv, char **envp)
df4b1e
 {
df4b1e
 	const char *error_string;
df4b1e
 	struct totem_config totem_config;
df4b1e
 	int res, ch;
df4b1e
-	int background, sched_rr, prio, testonly;
df4b1e
+	int background, sched_rr, prio, testonly, move_to_root_cgroup;
df4b1e
 	struct stat stat_out;
df4b1e
 	enum e_corosync_done flock_err;
df4b1e
 	uint64_t totem_config_warnings;
df4b1e
@@ -1153,8 +1240,9 @@ int main (int argc, char **argv, char **envp)
df4b1e
 	sched_rr = 1;
df4b1e
 	prio = 0;
df4b1e
 	testonly = 0;
df4b1e
+	move_to_root_cgroup = 1;
df4b1e
 
df4b1e
-	while ((ch = getopt (argc, argv, "fP:prtv")) != EOF) {
df4b1e
+	while ((ch = getopt (argc, argv, "fP:pRrtv")) != EOF) {
df4b1e
 
df4b1e
 		switch (ch) {
df4b1e
 			case 'f':
df4b1e
@@ -1179,6 +1267,9 @@ int main (int argc, char **argv, char **envp)
df4b1e
 					prio = tmpli;
df4b1e
 				}
df4b1e
 				break;
df4b1e
+			case 'R':
df4b1e
+				move_to_root_cgroup = 0;
df4b1e
+				break;
df4b1e
 			case 'r':
df4b1e
 				sched_rr = 1;
df4b1e
 				break;
df4b1e
@@ -1198,6 +1289,7 @@ int main (int argc, char **argv, char **envp)
df4b1e
 					"        -f     : Start application in foreground.\n"\
df4b1e
 					"        -p     : Do not set realtime scheduling.\n"\
df4b1e
 					"        -r     : Set round robin realtime scheduling (default).\n"\
df4b1e
+					"        -R     : Do not try move corosync to root cpu cgroup (valid when built with libcgroup)\n" \
df4b1e
 					"        -P num : Set priority of process (no effect when -r is used)\n"\
df4b1e
 					"        -t     : Test configuration and exit.\n"\
df4b1e
 					"        -v     : Display version and SVN revision of Corosync and exit.\n");
df4b1e
@@ -1312,6 +1404,15 @@ int main (int argc, char **argv, char **envp)
df4b1e
 		corosync_exit_error (COROSYNC_DONE_EXIT);
df4b1e
 	}
df4b1e
 
df4b1e
+
df4b1e
+	/*
df4b1e
+	 * Try to move corosync into root cpu cgroup. Failure is not fatal and
df4b1e
+	 * error is deliberately ignored.
df4b1e
+	 */
df4b1e
+	if (move_to_root_cgroup) {
df4b1e
+		(void)corosync_move_to_root_cgroup();
df4b1e
+	}
df4b1e
+
df4b1e
 	/*
df4b1e
 	 * Set round robin realtime scheduling with priority 99
df4b1e
 	 */
df4b1e
diff --git a/man/corosync.8 b/man/corosync.8
df4b1e
index dc596d1..7bce65e 100644
df4b1e
--- a/man/corosync.8
df4b1e
+++ b/man/corosync.8
df4b1e
@@ -35,7 +35,7 @@
df4b1e
 .SH NAME
df4b1e
 corosync \- The Corosync Cluster Engine.
df4b1e
 .SH SYNOPSIS
df4b1e
-.B "corosync [\-f] [\-P num] [\-p] [\-r] [\-t] [\-v]"
df4b1e
+.B "corosync [\-f] [\-P num] [\-p] [\-r] [-R] [\-t] [\-v]"
df4b1e
 .SH DESCRIPTION
df4b1e
 .B corosync
df4b1e
 Corosync provides clustering infrastructure such as membership, messaging and quorum.
df4b1e
@@ -62,6 +62,10 @@ meaning maximal / minimal priority (so minimal / maximal nice value).
df4b1e
 Set round robin realtime scheduling with maximal priority (default). When setting
df4b1e
 of scheduler fails, fallback to set maximal priority.
df4b1e
 .TP
df4b1e
+.B -R
df4b1e
+Do not try to move Corosync to root cpu cgroup. This feature is available only
df4b1e
+for corosync with libcgroup enabled during the build.
df4b1e
+.TP
df4b1e
 .B -t
df4b1e
 Test configuration and then exit.
df4b1e
 .TP
df4b1e
-- 
df4b1e
1.7.1
df4b1e