*/
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;
/* 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);
if (fp)
fclose(fp);
+ if (controllers)
+ free(controllers);
+
return ret;
}
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';
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);
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)
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);
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);
}
/*