From 6d5e5737e5ab874d451c083e6edb5ad899527bf1 Mon Sep 17 00:00:00 2001 From: Kamalesh Babulal Date: Tue, 25 Oct 2022 15:18:40 -0600 Subject: [PATCH] api: Introduce a new API to find the cgroup setup mode MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This patch introduces a new API to detect the current cgroup setup mode (Legacy/Unified/Hybrid). The setup will depend on the Linux Kernel's grub command line, the system/VM is booted with. Uses cases: Depending upon the cgroup setup, the users can enable or disable features in their applications. Like some controllers are only available on cgroup v2, so they might need to set/get settings for those available controllers only. Suggested-by: Tom Hromatka Suggested-by: Michal Koutný Signed-off-by: Kamalesh Babulal Signed-off-by: Tom Hromatka (cherry picked from commit 4aefa6d04f5e8a4b3914bdcdf2825943c4aef3fc) --- include/libcgroup/groups.h | 14 +++++++++++ src/api.c | 51 ++++++++++++++++++++++++++++++++++++++ src/libcgroup.map | 3 +++ 3 files changed, 68 insertions(+) diff --git a/include/libcgroup/groups.h b/include/libcgroup/groups.h index 41edbda2..dc8479a6 100644 --- a/include/libcgroup/groups.h +++ b/include/libcgroup/groups.h @@ -23,6 +23,13 @@ enum cg_version_t { CGROUP_DISK = 0xFF, }; +enum cg_setup_mode_t { + CGROUP_MODE_UNK = 0, + CGROUP_MODE_LEGACY, + CGROUP_MODE_HYBRID, + CGROUP_MODE_UNIFIED, +}; + /** * Flags for cgroup_delete_cgroup_ext(). */ @@ -636,6 +643,13 @@ int cgroup_list_mount_points(const enum cg_version_t cgrp_version, int cgroup_get_controller_version(const char * const controller, enum cg_version_t * const version); +/** + * Get the current group setup mode (legacy/unified/hybrid) + * + * @return CGROUP_MODE_UNK on failure and setup mode on success + */ +enum cg_setup_mode_t cgroup_setup_mode(void); + /** * @} * @} diff --git a/src/api.c b/src/api.c index 51190ad4..92e211dd 100644 --- a/src/api.c +++ b/src/api.c @@ -43,6 +43,7 @@ #include #include #include +#include #include @@ -6118,3 +6119,53 @@ const struct cgroup_library_version *cgroup_version(void) { return &library_version; } + +/** + * Finds the current cgroup setup mode (legacy/unified/hybrid). + * Returns unknown of failure and setup mode on success. + */ +enum cg_setup_mode_t cgroup_setup_mode(void) +{ +#define CGROUP2_SUPER_MAGIC 0x63677270 +#define CGROUP_SUPER_MAGIC 0x27E0EB + + unsigned int cg_setup_mode_bitmask = 0U; + enum cg_setup_mode_t setup_mode; + struct statfs cgrp_buf; + int i, ret = 0; + + if (!cgroup_initialized) { + return ECGROUPNOTINITIALIZED; + } + + setup_mode = CGROUP_MODE_UNK; + + pthread_rwlock_wrlock(&cg_mount_table_lock); + for (i = 0; cg_mount_table[i].name[0] != '\0'; i++) { + ret = statfs(cg_mount_table[i].mount.path, &cgrp_buf); + if (ret) { + setup_mode = CGROUP_MODE_UNK; + cgroup_err("Failed to get stats of '%s'\n", cg_mount_table[i].mount.path); + goto out; + } + + if (cgrp_buf.f_type == CGROUP2_SUPER_MAGIC) + cg_setup_mode_bitmask |= (1U << 0); + else if (cgrp_buf.f_type == CGROUP_SUPER_MAGIC) + cg_setup_mode_bitmask |= (1U << 1); + } + + if (cg_cgroup_v2_empty_mount_paths) + cg_setup_mode_bitmask |= (1U << 0); + + if (cg_setup_mode_bitmask & (1U << 0) && cg_setup_mode_bitmask & (1U << 1)) + setup_mode = CGROUP_MODE_HYBRID; + else if (cg_setup_mode_bitmask & (1U << 0)) + setup_mode = CGROUP_MODE_UNIFIED; + else if (cg_setup_mode_bitmask & (1U << 1)) + setup_mode = CGROUP_MODE_LEGACY; + +out: + pthread_rwlock_unlock(&cg_mount_table_lock); + return setup_mode; +} diff --git a/src/libcgroup.map b/src/libcgroup.map index fbf4d5d5..0cecba2f 100644 --- a/src/libcgroup.map +++ b/src/libcgroup.map @@ -146,4 +146,7 @@ CGROUP_3.0 { cgroup_cgxset; cgroup_version; cgroup_list_mount_points; + + /* libcgroup 3.0.1 */ + cgroup_setup_mode; } CGROUP_2.0; -- 2.47.2