]> git.ipfire.org Git - thirdparty/libcgroup.git/commitdiff
api: Add support for "cgroup" controller in cgroup v2
authorTom Hromatka <tom.hromatka@oracle.com>
Tue, 14 Feb 2023 19:58:59 +0000 (12:58 -0700)
committerTom Hromatka <tom.hromatka@oracle.com>
Wed, 22 Feb 2023 16:35:44 +0000 (09:35 -0700)
The "cgroup" controller has settings that the user may want to
read/write, e.g. cgroup.controllers, cgroup.subtree_control,
cgroup.procs, etc.

Add support for this controller when the cgroup v2 mount table is
parsed by creating a custom controller for the "cgroup" settings.
Note that this feature has not been added to cgroup v1 and cgroup v1
will continue to have limited access to the cgroup.* files.

Reported-by: Justin Israel <justinisrael@gmail.com>
Reviewed-by: Kamalesh Babulal <kamalesh.babulal@oracle.com>
Signed-off-by: Tom Hromatka <tom.hromatka@oracle.com>
(cherry picked from commit b09f6e750ecdf605f5b9cae97e6b831b6ecf187d)

src/api.c
tests/gunit/008-cgroup_process_v2_mount.cpp

index 210ef16500ef4a82eee3162c4f6d71313d20fb12..a944b73afd84d3f88057811b0e3828d46f839fda 100644 (file)
--- a/src/api.c
+++ b/src/api.c
@@ -1218,8 +1218,8 @@ out:
  */
 STATIC int cgroup_process_v2_mnt(struct mntent *ent, int *mnt_tbl_idx)
 {
+       char *ret_c = NULL, line[LL_MAX], *stok_buff = NULL, *controller, *controllers = NULL;
        char cgroup_controllers_path[FILENAME_MAX];
-       char *ret_c = NULL, line[LL_MAX], *stok_buff = NULL, *controller;
        int ret = 0, i, duplicate, shared_mnt;
        FILE *fp = NULL;
 
@@ -1273,12 +1273,25 @@ STATIC int cgroup_process_v2_mnt(struct mntent *ent, int *mnt_tbl_idx)
        /* Remove the trailing newline */
        ret_c[strlen(ret_c) - 1] = '\0';
 
+       /*
+        * The "cgroup" controller is a pseudo-controller that has settings that a user may
+        * wish to read/modify.  Add it to our cg_mount_table so that it can be manipulated
+        * like other "normal" controllers
+        */
+       controllers = malloc(strlen(ret_c) + strlen(CGROUP_FILE_PREFIX) + 1);
+       if (!controllers) {
+               ret = ECGOTHER;
+               goto out;
+       }
+
+       sprintf(controllers, "%s %s", ret_c, CGROUP_FILE_PREFIX);
+
        /*
         * cgroup.controllers returns a list of available controllers in
         * the following format:
         *      cpuset cpu io memory pids rdma
         */
-       controller = strtok_r(ret_c, " ", &stok_buff);
+       controller = strtok_r(controllers, " ", &stok_buff);
        do {
                /* Check if controllers share mount points */
                shared_mnt = cgroup_set_cg_mnt_tbl_shared_mnt(ent->mnt_dir, mnt_tbl_idx);
@@ -1315,6 +1328,9 @@ out:
        if (fp)
                fclose(fp);
 
+       if (controllers)
+               free(controllers);
+
        return ret;
 }
 
@@ -5267,6 +5283,18 @@ int cgroup_get_controller_next(void **handle, struct cgroup_mount_point *info)
                goto out_unlock;
        }
 
+       if (strncmp(cg_mount_table[*pos].name, CGROUP_FILE_PREFIX, CONTROL_NAMELEN_MAX) == 0)
+               /*
+                * For now, hide the "cgroup" pseudo-controller from the user.  This may be
+                * worth revisiting in the future.
+                */
+               (*pos)++;
+
+       if (cg_mount_table[*pos].name[0] == '\0') {
+               ret = ECGEOF;
+               goto out_unlock;
+       }
+
        strncpy(info->name, cg_mount_table[*pos].name, FILENAME_MAX - 1);
        info->name[FILENAME_MAX - 1] = '\0';
 
index 845978939450fcdfb272acef014b01a7047b109e..a68c8ed72d190ae879a36cfc45f844a1c819fd6a 100644 (file)
@@ -106,13 +106,14 @@ TEST_F(CgroupProcessV2MntTest, AddV2Mount)
        ret = cgroup_process_v2_mnt(&ent, &mnt_tbl_idx);
 
        ASSERT_EQ(ret, 0);
-       ASSERT_EQ(mnt_tbl_idx, 6);
+       ASSERT_EQ(mnt_tbl_idx, 7);
        ASSERT_STREQ(cg_mount_table[0].name, "cpuset");
        ASSERT_STREQ(cg_mount_table[1].name, "cpu");
        ASSERT_STREQ(cg_mount_table[2].name, "io");
        ASSERT_STREQ(cg_mount_table[3].name, "memory");
        ASSERT_STREQ(cg_mount_table[4].name, "pids");
        ASSERT_STREQ(cg_mount_table[5].name, "rdma");
+       ASSERT_STREQ(cg_mount_table[6].name, "cgroup");
 
        ASSERT_STREQ(cg_mount_table[0].mount.path, ent.mnt_dir);
        ASSERT_STREQ(cg_mount_table[1].mount.path, ent.mnt_dir);
@@ -120,6 +121,7 @@ TEST_F(CgroupProcessV2MntTest, AddV2Mount)
        ASSERT_STREQ(cg_mount_table[3].mount.path, ent.mnt_dir);
        ASSERT_STREQ(cg_mount_table[4].mount.path, ent.mnt_dir);
        ASSERT_STREQ(cg_mount_table[5].mount.path, ent.mnt_dir);
+       ASSERT_STREQ(cg_mount_table[6].mount.path, ent.mnt_dir);
 }
 
 TEST_F(CgroupProcessV2MntTest, AddV2Mount_Duplicate)
@@ -136,13 +138,14 @@ TEST_F(CgroupProcessV2MntTest, AddV2Mount_Duplicate)
        ret = cgroup_process_v2_mnt(&ent, &mnt_tbl_idx);
 
        ASSERT_EQ(ret, 0);
-       ASSERT_EQ(mnt_tbl_idx, 6);
+       ASSERT_EQ(mnt_tbl_idx, 7);
        ASSERT_STREQ(cg_mount_table[0].name, "cpuset");
        ASSERT_STREQ(cg_mount_table[1].name, "cpu");
        ASSERT_STREQ(cg_mount_table[2].name, "io");
        ASSERT_STREQ(cg_mount_table[3].name, "memory");
        ASSERT_STREQ(cg_mount_table[4].name, "pids");
        ASSERT_STREQ(cg_mount_table[5].name, "rdma");
+       ASSERT_STREQ(cg_mount_table[6].name, "cgroup");
 
        ASSERT_STREQ(cg_mount_table[0].mount.next->path, ent.mnt_dir);
        ASSERT_STREQ(cg_mount_table[1].mount.next->path, ent.mnt_dir);
@@ -150,6 +153,7 @@ TEST_F(CgroupProcessV2MntTest, AddV2Mount_Duplicate)
        ASSERT_STREQ(cg_mount_table[3].mount.next->path, ent.mnt_dir);
        ASSERT_STREQ(cg_mount_table[4].mount.next->path, ent.mnt_dir);
        ASSERT_STREQ(cg_mount_table[5].mount.next->path, ent.mnt_dir);
+       ASSERT_STREQ(cg_mount_table[6].mount.next->path, ent.mnt_dir);
 }
 
 /*