diff --git a/src/shared/cgroup-setup.c b/src/shared/cgroup-setup.c index c1019f571d5..b94d0b00a66 100644 --- a/src/shared/cgroup-setup.c +++ b/src/shared/cgroup-setup.c @@ -1,6 +1,5 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include #include #include "cgroup-setup.h" @@ -12,168 +11,11 @@ #include "mkdir.h" #include "parse-util.h" #include "path-util.h" -#include "proc-cmdline.h" #include "process-util.h" #include "recurse-dir.h" #include "stdio-util.h" #include "string-util.h" #include "user-util.h" -#include "virt.h" - -static int cg_any_controller_used_for_v1(void) { - _cleanup_free_ char *buf = NULL; - _cleanup_strv_free_ char **lines = NULL; - int r; - - r = read_full_virtual_file("/proc/cgroups", &buf, NULL); - if (r < 0) - return log_debug_errno(r, "Could not read /proc/cgroups, ignoring: %m"); - - r = strv_split_newlines_full(&lines, buf, 0); - if (r < 0) - return r; - - /* The intention of this is to check if the fully unified cgroup tree setup is possible, meaning all - * enabled kernel cgroup controllers are currently not in use by cgroup1. For reference: - * https://systemd.io/CGROUP_DELEGATION/#three-different-tree-setups- - * - * Note that this is typically only useful to check inside a container where we don't know what - * cgroup tree setup is in use by the host; if the host is using legacy or hybrid, we can't use - * unified since some or all controllers would be missing. This is not the best way to detect this, - * as whatever container manager created our container should have mounted /sys/fs/cgroup - * appropriately, but in case that wasn't done, we try to detect if it's possible for us to use - * unified cgroups. */ - STRV_FOREACH(line, lines) { - _cleanup_free_ char *name = NULL, *hierarchy_id = NULL, *num = NULL, *enabled = NULL; - - /* Skip header line */ - if (startswith(*line, "#")) - continue; - - const char *p = *line; - r = extract_many_words(&p, NULL, 0, &name, &hierarchy_id, &num, &enabled); - if (r < 0) - return log_debug_errno(r, "Error parsing /proc/cgroups line, ignoring: %m"); - else if (r < 4) { - log_debug("Invalid /proc/cgroups line, ignoring."); - continue; - } - - /* Ignore disabled controllers. */ - if (streq(enabled, "0")) - continue; - - /* Ignore controllers we don't care about. */ - if (cgroup_controller_from_string(name) < 0) - continue; - - /* Since the unified cgroup doesn't use multiple hierarchies, if any controller has a - * non-zero hierarchy_id that means it's in use already in a legacy (or hybrid) cgroup v1 - * hierarchy, and can't be used in a unified cgroup. */ - if (!streq(hierarchy_id, "0")) { - log_debug("Cgroup controller %s in use by legacy v1 hierarchy.", name); - return 1; - } - } - - return 0; -} - -bool cg_is_unified_wanted(void) { - static thread_local int wanted = -1; - int r; - - /* If we have a cached value, return that. */ - if (wanted >= 0) - return wanted; - - /* If the hierarchy is already mounted, then follow whatever was chosen for it. */ - r = cg_unified_cached(true); - if (r >= 0) - return (wanted = r >= CGROUP_UNIFIED_ALL); - - /* If we have explicit configuration for v1 or v2, respect that. */ - if (cg_is_legacy_force_enabled()) - return (wanted = false); - - bool b; - r = proc_cmdline_get_bool("systemd.unified_cgroup_hierarchy", /* flags = */ 0, &b); - if (r > 0 && b) - return (wanted = true); - - /* If we passed cgroup_no_v1=all with no other instructions, it seems highly unlikely that we want to - * use hybrid or legacy hierarchy. */ - _cleanup_free_ char *c = NULL; - r = proc_cmdline_get_key("cgroup_no_v1", 0, &c); - if (r > 0 && streq_ptr(c, "all")) - return (wanted = true); - - /* If any controller is in use as v1, don't use unified. */ - if (cg_any_controller_used_for_v1() > 0) - return (wanted = false); - - return (wanted = true); -} - -bool cg_is_legacy_wanted(void) { - /* Check if we have cgroup v2 already mounted. */ - if (cg_unified_cached(true) == CGROUP_UNIFIED_ALL) - return false; - - /* Otherwise, assume that at least partial legacy is wanted, - * since cgroup v2 should already be mounted at this point. */ - return true; -} - -bool cg_is_hybrid_wanted(void) { - static thread_local int wanted = -1; - int r; - - /* If we have a cached value, return that. */ - if (wanted >= 0) - return wanted; - - /* If the hierarchy is already mounted, then follow whatever was chosen for it. */ - if (cg_unified_cached(true) == CGROUP_UNIFIED_ALL) - return (wanted = false); - - /* Otherwise, let's see what the kernel command line has to say. Since checking is expensive, cache - * a non-error result. - * The meaning of the kernel option is reversed wrt. to the return value of this function, hence the - * negation. */ - bool b; - r = proc_cmdline_get_bool("systemd.legacy_systemd_cgroup_controller", /* flags = */ 0, &b); - if (r > 0) - return (wanted = !b); - - /* The default hierarchy is "unified". But if this is reached, it means that unified hierarchy was - * not mounted, so return true too. */ - return (wanted = true); -} - -bool cg_is_legacy_enabled(void) { - int r; - bool b; - - r = proc_cmdline_get_bool("systemd.unified_cgroup_hierarchy", /* flags = */ 0, &b); - return r > 0 && !b; -} - -bool cg_is_legacy_force_enabled(void) { - int r; - bool b; - - /* Require both systemd.unified_cgroup_hierarchy=0 and SYSTEMD_CGROUP_ENABLE_LEGACY_FORCE=1. */ - - if (!cg_is_legacy_enabled()) - return false; - - r = proc_cmdline_get_bool("SYSTEMD_CGROUP_ENABLE_LEGACY_FORCE", /* flags = */ 0, &b); - if (r <= 0 || !b) - return false; - - return true; -} int cg_weight_parse(const char *s, uint64_t *ret) { uint64_t u; diff --git a/src/shared/cgroup-setup.h b/src/shared/cgroup-setup.h index 31c4ea1aced..6eecb9be101 100644 --- a/src/shared/cgroup-setup.h +++ b/src/shared/cgroup-setup.h @@ -7,12 +7,6 @@ #include "cgroup-util.h" -bool cg_is_unified_wanted(void); -bool cg_is_legacy_wanted(void); -bool cg_is_hybrid_wanted(void); -bool cg_is_legacy_enabled(void); -bool cg_is_legacy_force_enabled(void); - int cg_weight_parse(const char *s, uint64_t *ret); int cg_cpu_weight_parse(const char *s, uint64_t *ret); int cg_cpu_shares_parse(const char *s, uint64_t *ret); diff --git a/src/shared/mount-setup.c b/src/shared/mount-setup.c index 611d233167f..db963df39e6 100644 --- a/src/shared/mount-setup.c +++ b/src/shared/mount-setup.c @@ -55,9 +55,6 @@ typedef struct MountPoint { bool cgroupfs_recursiveprot_supported(void) { int r; - if (!cg_is_unified_wanted()) - return false; - /* Added in kernel 5.7 */ r = mount_option_supported("cgroup2", "memory_recursiveprot", /* value = */ NULL); @@ -95,11 +92,9 @@ static const MountPoint mount_table[] = { { "tmpfs", "/run", "tmpfs", "mode=0755" TMPFS_LIMITS_RUN, MS_NOSUID|MS_NODEV|MS_STRICTATIME, NULL, MNT_FATAL|MNT_IN_CONTAINER }, { "cgroup2", "/sys/fs/cgroup", "cgroup2", "nsdelegate,memory_recursiveprot", MS_NOSUID|MS_NOEXEC|MS_NODEV, - cgroupfs_recursiveprot_supported, MNT_IN_CONTAINER|MNT_CHECK_WRITABLE }, + cgroupfs_recursiveprot_supported, MNT_FATAL|MNT_IN_CONTAINER|MNT_CHECK_WRITABLE }, { "cgroup2", "/sys/fs/cgroup", "cgroup2", "nsdelegate", MS_NOSUID|MS_NOEXEC|MS_NODEV, - cg_is_unified_wanted, MNT_IN_CONTAINER|MNT_CHECK_WRITABLE }, - { "cgroup2", "/sys/fs/cgroup", "cgroup2", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, - cg_is_unified_wanted, MNT_IN_CONTAINER|MNT_CHECK_WRITABLE }, + NULL, MNT_FATAL|MNT_IN_CONTAINER|MNT_CHECK_WRITABLE }, #if ENABLE_PSTORE { "pstore", "/sys/fs/pstore", "pstore", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL, MNT_NONE }, diff --git a/src/test/meson.build b/src/test/meson.build index ec03ad2b7d2..e86a28f8761 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -55,7 +55,6 @@ simple_tests += files( 'test-build-path.c', 'test-bus-util.c', 'test-calendarspec.c', - 'test-cgroup-setup.c', 'test-cgroup-util.c', 'test-cgroup.c', 'test-chase.c', diff --git a/src/test/test-cgroup-setup.c b/src/test/test-cgroup-setup.c deleted file mode 100644 index af5712060bf..00000000000 --- a/src/test/test-cgroup-setup.c +++ /dev/null @@ -1,71 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include - -#include "alloc-util.h" -#include "cgroup-setup.h" -#include "errno-util.h" -#include "log.h" -#include "proc-cmdline.h" -#include "string-util.h" -#include "tests.h" - -static void test_is_wanted_print_one(bool header) { - _cleanup_free_ char *cmdline = NULL; - - log_info("-- %s --", __func__); - ASSERT_OK(proc_cmdline(&cmdline)); - log_info("cmdline: %s", cmdline); - if (header) - (void) system("findmnt -n /sys/fs/cgroup"); - - log_info("is_unified_wanted() → %s", yes_no(cg_is_unified_wanted())); - log_info("is_hybrid_wanted() → %s", yes_no(cg_is_hybrid_wanted())); - log_info("is_legacy_wanted() → %s", yes_no(cg_is_legacy_wanted())); - log_info(" "); -} - -TEST(is_wanted_print) { - test_is_wanted_print_one(true); - test_is_wanted_print_one(false); /* run twice to test caching */ -} - -TEST(is_wanted) { - ASSERT_OK_ERRNO(setenv("SYSTEMD_PROC_CMDLINE", - "systemd.unified_cgroup_hierarchy", 1)); - test_is_wanted_print_one(false); - - ASSERT_OK_ERRNO(setenv("SYSTEMD_PROC_CMDLINE", - "systemd.unified_cgroup_hierarchy=0", 1)); - test_is_wanted_print_one(false); - - ASSERT_OK_ERRNO(setenv("SYSTEMD_PROC_CMDLINE", - "systemd.unified_cgroup_hierarchy=0 " - "systemd.legacy_systemd_cgroup_controller", 1)); - test_is_wanted_print_one(false); - - ASSERT_OK_ERRNO(setenv("SYSTEMD_PROC_CMDLINE", - "systemd.unified_cgroup_hierarchy=0 " - "systemd.legacy_systemd_cgroup_controller=0", 1)); - test_is_wanted_print_one(false); - - /* cgroup_no_v1=all implies unified cgroup hierarchy, unless otherwise - * explicitly specified. */ - ASSERT_OK_ERRNO(setenv("SYSTEMD_PROC_CMDLINE", - "cgroup_no_v1=all", 1)); - test_is_wanted_print_one(false); - - ASSERT_OK_ERRNO(setenv("SYSTEMD_PROC_CMDLINE", - "cgroup_no_v1=all " - "systemd.unified_cgroup_hierarchy=0", 1)); - test_is_wanted_print_one(false); -} - -static int intro(void) { - if (access("/proc/cmdline", R_OK) < 0 && ERRNO_IS_PRIVILEGE(errno)) - return log_tests_skipped("can't read /proc/cmdline"); - - return EXIT_SUCCESS; -} - -DEFINE_TEST_MAIN_WITH_INTRO(LOG_DEBUG, intro);