+#endif // 0
+
+static thread_local int unified_cache = -1;
+
+int cg_unified(void) {
+ struct statfs fs;
+
+ /* Checks if we support the unified hierarchy. Returns an
+ * error when the cgroup hierarchies aren't mounted yet or we
+ * have any other trouble determining if the unified hierarchy
+ * is supported. */
+
+ if (unified_cache >= 0)
+ return unified_cache;
+
+ if (statfs("/sys/fs/cgroup/", &fs) < 0)
+ return -errno;
+
+/// elogind can not support the unified hierarchy as a controller,
+/// so always assume a classical hierarchy.
+/// If, ond only *if*, someone really wants to substitute systemd-login
+/// in an environment managed by systemd with elogin, we might have to
+/// add such a support.
+#if 0
+ if (F_TYPE_EQUAL(fs.f_type, CGROUP_SUPER_MAGIC))
+ unified_cache = true;
+ else if (F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC))
+#else
+ if (F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC))
+#endif // 0
+ unified_cache = false;
+ else
+ return -ENOEXEC;
+
+ return unified_cache;
+}
+
+/// UNNEEDED by elogind
+#if 0
+void cg_unified_flush(void) {
+ unified_cache = -1;
+}
+
+int cg_enable_everywhere(CGroupMask supported, CGroupMask mask, const char *p) {
+ _cleanup_free_ char *fs = NULL;
+ CGroupController c;
+ int r, unified;
+
+ assert(p);
+
+ if (supported == 0)
+ return 0;
+
+ unified = cg_unified();
+ if (unified < 0)
+ return unified;
+ if (!unified) /* on the legacy hiearchy there's no joining of controllers defined */
+ return 0;
+
+ r = cg_get_path(ELOGIND_CGROUP_CONTROLLER, p, "cgroup.subtree_control", &fs);
+ if (r < 0)
+ return r;
+
+ for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
+ CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c);
+ const char *n;
+
+ if (!(supported & bit))
+ continue;
+
+ n = cgroup_controller_to_string(c);
+ {
+ char s[1 + strlen(n) + 1];
+
+ s[0] = mask & bit ? '+' : '-';
+ strcpy(s + 1, n);
+
+ r = write_string_file(fs, s, 0);
+ if (r < 0)
+ log_debug_errno(r, "Failed to enable controller %s for %s (%s): %m", n, p, fs);
+ }
+ }
+
+ return 0;
+}
+
+bool cg_is_unified_wanted(void) {
+ static thread_local int wanted = -1;
+ int r, unified;
+
+ /* If the hierarchy is already mounted, then follow whatever
+ * was chosen for it. */
+ unified = cg_unified();
+ if (unified >= 0)
+ return unified;
+
+ /* Otherwise, let's see what the kernel command line has to
+ * say. Since checking that is expensive, let's cache the
+ * result. */
+ if (wanted >= 0)
+ return wanted;
+
+ r = get_proc_cmdline_key("systemd.unified_cgroup_hierarchy", NULL);
+ if (r > 0)
+ return (wanted = true);
+ else {
+ _cleanup_free_ char *value = NULL;
+
+ r = get_proc_cmdline_key("systemd.unified_cgroup_hierarchy=", &value);
+ if (r < 0)
+ return false;
+ if (r == 0)
+ return (wanted = false);
+
+ return (wanted = parse_boolean(value) > 0);
+ }
+}
+
+bool cg_is_legacy_wanted(void) {
+ return !cg_is_unified_wanted();
+}
+#else
+bool cg_is_legacy_wanted(void) {
+ return true;
+}
+#endif // 0
+
+static const char *cgroup_controller_table[_CGROUP_CONTROLLER_MAX] = {
+ [CGROUP_CONTROLLER_CPU] = "cpu",
+ [CGROUP_CONTROLLER_CPUACCT] = "cpuacct",
+ [CGROUP_CONTROLLER_BLKIO] = "blkio",
+ [CGROUP_CONTROLLER_MEMORY] = "memory",
+ [CGROUP_CONTROLLER_DEVICE] = "devices",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(cgroup_controller, CGroupController);