]> git.ipfire.org Git - thirdparty/libcgroup.git/commitdiff
api: cg_build_path_locked() - support default systemd delegate scope
authorKamalesh Babulal <kamalesh.babulal@oracle.com>
Wed, 8 Feb 2023 09:40:23 +0000 (15:10 +0530)
committerTom Hromatka <tom.hromatka@oracle.com>
Fri, 10 Feb 2023 21:44:25 +0000 (14:44 -0700)
Add support to build cgroup path to the default systemd slice/scope
cgroup, if setdefault is set in the systemd configuration of the
cgconfig.conf.

$ cat /etc/cgconfig.conf
...
systemd {
    slice = database.slice;
    scope = db.scope;
    setdefault = yes; <--  set cgroup root path to '/sys/fs/cgroup/database.slice/db.scope/'
}

systemd {
    slice = database.slice;
    scope = house_keeping.scope;
    pid = 3241;
}

systemd {
    slice = others.slice;
    scope = server.scope;
}

cg_build_path() constructs the cgroup path to the mount point of the
given cgroup controller. With the support for the default systemd scope,
the default cgroup path for the controller, appends the slice/scope
name, making it the default cgroup root.

Allowing the users to set their default cgroup path from
'/sys/fs/cgroup/' to
'/sys/fs/cgroup/<systemd slice name>/<systemd scope name>/', while
using the libcgroup tools, allowing them to work on the delegated
cgroup hierarchy.

Signed-off-by: Kamalesh Babulal <kamalesh.babulal@oracle.com>
Signed-off-by: Tom Hromatka <tom.hromatka@oracle.com>
src/api.c

index 3123c12a66e96531c04edd3c136ffdc474b69dbb..ff79b344ce782af77b933c979d7e22c388499d31 100644 (file)
--- a/src/api.c
+++ b/src/api.c
@@ -1690,8 +1690,34 @@ char *cg_build_path_locked(const char *name, char *path, const char *type)
         * cg_mount_table[i].mount.path + '/' + cg_namespace_table[i] + '/'
         */
        int i, ret, len = (FILENAME_MAX * 2) + 2;
-       char *_path;
+       char *tmp_systemd_default_cgroup, *_path = NULL;
 
+       /*
+        * systemd_default_cgroup can't be clobbered.   The user may pass
+        * multiple cgroups, hence use temporary variable for manipulations
+        * for example:
+        * cgget -g cpu:/ -g cpu:cgrp1 -g cpu:/cgrp2
+        */
+       tmp_systemd_default_cgroup = calloc(1, (sizeof(char) * len));
+       if (!tmp_systemd_default_cgroup) {
+               cgroup_err("Failed to allocate memory for tmp_systemd_default_cgroup\n");
+               goto out;
+       }
+
+#ifdef WITH_SYSTEMD
+       /*
+        * If the user specifies the name as /<cgroup-name>, they are
+        * effectively overriding the systemd_default_cgroup but if the name
+        * is "/", the cgroup root path is systemd_default_cgroup
+        */
+       if (strlen(systemd_default_cgroup) && name && name[0] == '/' && name[1] != '\0')
+               tmp_systemd_default_cgroup[0] = '\0';
+       else
+               snprintf(tmp_systemd_default_cgroup, len, "%s/", systemd_default_cgroup);
+
+       /* allocate more space for systemd_default_cgroup + '/' */
+       len += (FILENAME_MAX + 1);
+#endif
        /*
         * Recent gcc are unhappy when sizeof(dest) <= sizeof(src) with
         * snprintf()'s.  Alternative is to use multiple strncpy()/strcat(),
@@ -1701,7 +1727,7 @@ char *cg_build_path_locked(const char *name, char *path, const char *type)
        _path = malloc(len);
        if (!_path) {
                cgroup_err("Failed to allocate memory for _path\n");
-               return NULL;
+               goto out;
        }
 
        /*
@@ -1711,7 +1737,8 @@ char *cg_build_path_locked(const char *name, char *path, const char *type)
         * any controller.
         */
        if (!type && strlen(cg_cgroup_v2_mount_path) > 0) {
-               ret = snprintf(_path, len, "%s/", cg_cgroup_v2_mount_path);
+               ret = snprintf(_path, len, "%s/%s", cg_cgroup_v2_mount_path,
+                              tmp_systemd_default_cgroup);
                if (ret >= FILENAME_MAX)
                        cgroup_dbg("filename too long: %s", _path);
 
@@ -1745,10 +1772,11 @@ char *cg_build_path_locked(const char *name, char *path, const char *type)
                     cg_mount_table[i].version == CGROUP_V2)) {
 
                        if (cg_namespace_table[i])
-                               ret = snprintf(_path, len, "%s/%s/", cg_mount_table[i].mount.path,
-                                              cg_namespace_table[i]);
+                               ret = snprintf(_path, len, "%s/%s%s/", cg_mount_table[i].mount.path,
+                                              tmp_systemd_default_cgroup, cg_namespace_table[i]);
                        else
-                               ret = snprintf(_path, len, "%s/", cg_mount_table[i].mount.path);
+                               ret = snprintf(_path, len, "%s/%s", cg_mount_table[i].mount.path,
+                                              tmp_systemd_default_cgroup);
 
                        if (ret >= FILENAME_MAX)
                                cgroup_dbg("filename too long: %s", _path);
@@ -1775,6 +1803,9 @@ out:
        if (_path)
                free(_path);
 
+       if (tmp_systemd_default_cgroup)
+               free(tmp_systemd_default_cgroup);
+
        return path;
 }