From 36ed9afee2dfbd6b5e16df6d5f37cd05bb44eecb Mon Sep 17 00:00:00 2001 From: Kamalesh Babulal Date: Wed, 8 Feb 2023 16:23:00 +0530 Subject: [PATCH] tools/cgxget: add support for default systemd delegation slice/scope Enhance the cgxget tool to support default systemd delegation slice/scope, if set in the cgconfig.conf's systemd setting. Parse the configuration file and read the systemd::delegate setting, if any, and set it as the default systemd slice/scope in systemd_default_cgroup. Setting it appends the slice/scope name to the constructed default cgroup mount path. When the user passes the relative cgroup name, its appends to the sub-tree (delegated slice/scope) by default and if the user wishes to get details about the cgroups in another subtree or cgroup root hierarchy, they need to use the absolute path. For example: cgroup_root / \ / \ systemd.slice* cgrp1 | systemd.scope | cgrp-d1 * default system delegation slice/scope - read from cgconfig.conf $ sudo cgxget -1 -r cpu.shares cgrp-d1 will display the cpu controller information under the cgroup_root:systemd_default_cgroup:cgrp-d1 and for viewing the cpu controller information of cgrp1, the user can use: $ sudo cgxget -1 -r cpu.shares /cgrp1 or use the newly introduced -b switch to ignore the systemd slice/scope: $ sudo cgxget -b -1 -r cpu.shares /cgrp1 Signed-off-by: Kamalesh Babulal Signed-off-by: Tom Hromatka TJH: Fix minor typo in a comment where delegate was written instead of setdefault --- src/tools/cgxget.c | 54 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/src/tools/cgxget.c b/src/tools/cgxget.c index fb7a0ccf..225e3a63 100644 --- a/src/tools/cgxget.c +++ b/src/tools/cgxget.c @@ -17,11 +17,13 @@ #include #include #include +#include #include #define MODE_SHOW_HEADERS 1 #define MODE_SHOW_NAMES 2 +#define MODE_SYSTEMD_DELEGATE 4 #define LL_MAX 100 @@ -58,6 +60,9 @@ static void usage(int status, const char *program_name) info(" -n Do not print headers\n"); info(" -r, --variable Define parameter to display\n"); info(" -v, --values-only Print only values, not parameter names\n"); +#ifdef WITH_SYSTEMD + info(" -b Ignore default systemd delegate hierarchy\n"); +#endif } static int get_controller_from_name(const char * const name, char **controller) @@ -412,8 +417,16 @@ static int parse_opts(int argc, char *argv[], struct cgroup **cg_list[], int * c int c; /* Parse arguments. */ +#ifdef WITH_SYSTEMD + while ((c = getopt_long(argc, argv, "r:hnvg:a12ib", long_options, NULL)) > 0) { + switch (c) { + case 'b': + *mode = (*mode) & (INT_MAX ^ MODE_SYSTEMD_DELEGATE); + break; +#else while ((c = getopt_long(argc, argv, "r:hnvg:a12i", long_options, NULL)) > 0) { switch (c) { +#endif case 'h': usage(0, argv[0]); exit(0); @@ -577,7 +590,10 @@ static int indent_multiline_value(struct control_value * const cv) static int fill_empty_controller(struct cgroup * const cg, struct cgroup_controller * const cgc) { struct dirent *ctrl_dir = NULL; - char path[FILENAME_MAX]; + char path[FILENAME_MAX] = { '\0' }; +#ifdef WITH_SYSTEMD + char tmp[FILENAME_MAX] = { '\0' }; +#endif bool found_mount = false; int i, path_len, ret = 0; DIR *dir = NULL; @@ -601,6 +617,36 @@ static int fill_empty_controller(struct cgroup * const cg, struct cgroup_control goto out; path_len = strlen(path); +#ifdef WITH_SYSTEMD + /* + * If the user has set a slice/scope as setdefault in the + * cgconfig.conf file, every path constructed will have the + * systemd_default_cgroup slice/scope suffixed to it. + * + * We need to trim the slice/scope from the path, incase of + * user providing / as the cgroup name in the command + * line: + * cgxget -1 -r cpu.shares /a + */ + + if (cg->name[0] == '/' && cg->name[1] != '\0' && + strncmp(path + (path_len - 7), ".scope/", 7) == 0) { + snprintf(tmp, FILENAME_MAX, "%s", dirname(path)); + strncpy(path, tmp, FILENAME_MAX - 1); + path[FILENAME_MAX - 1] = '\0'; + + path_len = strlen(path); + if (strncmp(path + (path_len - 6), ".slice", 6) == 0) { + snprintf(tmp, FILENAME_MAX, "%s", dirname(path)); + strncpy(path, tmp, FILENAME_MAX - 1); + path[FILENAME_MAX - 1] = '\0'; + } else { + cgroup_dbg("Malformed path %s (expected slice name)\n", path); + ret = ECGOTHER; + goto out; + } + } +#endif strncat(path, cg->name, FILENAME_MAX - path_len - 1); path[sizeof(path) - 1] = '\0'; @@ -787,7 +833,7 @@ out: int main(int argc, char *argv[]) { - int mode = MODE_SHOW_NAMES | MODE_SHOW_HEADERS; + int mode = MODE_SHOW_NAMES | MODE_SHOW_HEADERS | MODE_SYSTEMD_DELEGATE; enum cg_version_t version = CGROUP_UNK; struct cgroup **cg_list = NULL; bool ignore_unmappable = false; @@ -810,6 +856,10 @@ int main(int argc, char *argv[]) if (ret) goto err; + /* this is false always for disable-systemd */ + if (mode & MODE_SYSTEMD_DELEGATE) + cgroup_set_default_systemd_cgroup(); + ret = convert_cgroups(&cg_list, cg_list_len, version, CGROUP_DISK); if (ret == ECGNOVERSIONCONVERT && ignore_unmappable) /* -- 2.47.2