[lxc-devel] [PATCH RFC] detect which cgroups we cannot use

Serge Hallyn serge.hallyn at ubuntu.com
Thu Dec 24 02:14:39 UTC 2015


and continue without them if possible

This patch only handles cgmanger - we need to handle this in cgfs too.

Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
---
 src/lxc/cgmanager.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 113 insertions(+), 3 deletions(-)

diff --git a/src/lxc/cgmanager.c b/src/lxc/cgmanager.c
index d69eb3d..95af043 100644
--- a/src/lxc/cgmanager.c
+++ b/src/lxc/cgmanager.c
@@ -1202,6 +1202,116 @@ static bool verify_and_prune(const char *cgroup_use)
 	return true;
 }
 
+static void drop_subsystem(int which)
+{
+	int i;
+
+	if (which <= 0 || which > nr_subsystems) {
+		ERROR("code error: dropping invalid subsystem index\n");
+		exit(1);
+	}
+
+	free(subsystems[which]);
+	/* note - we have nr_subsystems+1 entries, last one a NULL */
+	for (i = which; i < nr_subsystems; i++)
+		subsystems[i] = subsystems[i+1];
+	nr_subsystems -= 1;
+}
+
+/*
+ * Check whether we can create the cgroups we would want
+ */
+static bool subsys_is_writeable(const char *controller, const char *probe)
+{
+	int32_t existed;
+	bool ret = true;
+
+	if ( cgmanager_create_sync(NULL, cgroup_manager, controller,
+				       probe, &existed) != 0) {
+		NihError *nerr;
+		nerr = nih_error_get();
+		ERROR("call to cgmanager_create_sync failed: %s", nerr->message);
+		nih_free(nerr);
+		ERROR("Failed to create %s:%s", controller, probe);
+		ret = false;
+	}
+
+	return ret;
+}
+
+/*
+ * Return true if this is a subsystem which we cannot do
+ * without
+ */
+static bool is_crucial_subsys(const char *s)
+{
+	if (strcmp(s, "systemd") == 0)
+		return true;
+	if (strcmp(s, "name=systemd") == 0)
+		return true;
+	if (strcmp(s, "freezer") == 0)
+		return true;
+	return false;
+}
+
+/*
+ * Make sure that all the controllers are writeable.
+ * If any are not, then
+ *   - if they are listed in lxc.cgroup.use, refuse to start
+ *   - else if they are crucial subsystems, refuse to start
+ *   - else warn and do not use them
+ */
+static bool verify_final_subsystems(const char *cgroup_use)
+{
+	int i = 0;
+	bool dropped_any = false;
+	bool ret = false;
+	const char *cgroup_pattern;
+	char tmpnam[50], *probe;
+
+	if (!cgm_dbus_connect()) {
+		ERROR("Error connecting to cgroup manager");
+		return false;
+	}
+
+	cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern");
+	snprintf(tmpnam, 50, "lxcprobe-%d", getpid());
+	probe = lxc_string_replace("%n", tmpnam, cgroup_pattern);
+	if (!probe)
+		goto out;
+
+	while (i < nr_subsystems) {
+		if (!subsys_is_writeable(subsystems[i], probe)) {
+			if (is_crucial_subsys(subsystems[i])) {
+				ERROR("Cannot write to crucial subsystem %s\n",
+					subsystems[i]);
+				goto out;
+			}
+			if (cgroup_use && in_comma_list(subsystems[i], cgroup_use)) {
+				ERROR("Cannot write to subsystem %s which is requested in lxc.cgroup.use\n",
+					subsystems[i]);
+				goto out;
+			}
+			WARN("Cannot write to subsystem %s, continuing with out it\n",
+				subsystems[i]);
+			dropped_any = true;
+			drop_subsystem(i);
+		} else {
+			cgm_remove_cgroup(subsystems[i], probe);
+			i++;
+		}
+	}
+
+	if (dropped_any)
+		cgm_all_controllers_same = false;
+	ret = true;
+
+out:
+	free(probe);
+	cgm_dbus_disconnect();
+	return ret;
+}
+
 static bool collect_subsytems(void)
 {
 	char *line = NULL;
@@ -1285,7 +1395,7 @@ collected:
 	/* make sure that cgroup.use can be and is honored */
 	const char *cgroup_use = lxc_global_config_value("lxc.cgroup.use");
 	if (!cgroup_use && errno != 0)
-		goto out_good;
+		goto final_verify;
 	if (cgroup_use) {
 		if (!verify_and_prune(cgroup_use)) {
 			free_subsystems();
@@ -1295,8 +1405,8 @@ collected:
 		cgm_all_controllers_same = false;
 	}
 
-out_good:
-	return true;
+final_verify:
+	return verify_final_subsystems(cgroup_use);
 
 out_free:
 	free(line);
-- 
2.5.0



More information about the lxc-devel mailing list