Signed-off-by: Tom Hromatka <tom.hroma...@oracle.com>
---
src/api.c | 142 ++++++++++++++++++++++++++++++++++-----
src/libcgroup-internal.h | 6 ++
2 files changed, 132 insertions(+), 16 deletions(-)
diff --git a/src/api.c b/src/api.c
index 3845352f07cf..0c05f851391a 100644
--- a/src/api.c
+++ b/src/api.c
@@ -63,6 +63,12 @@ static __thread char errtext[MAXLEN];
/* Task command name length */
#define TASK_COMM_LEN 16
+/* cgroup v2 controllers file */
+#define CGV2_CONTROLLERS_FILE "cgroup.controllers"
+
+/* maximum line length when reading the cgroup.controllers file */
+#define LL_MAX 100
+
/* Check if cgroup_init has been called or not. */
static int cgroup_initialized;
@@ -1086,6 +1092,7 @@ static int cgroup_process_v1_mnt(char
*controllers[], struct mntent *ent,
cg_mount_table[*mnt_tbl_idx].mount.path[FILENAME_MAX-1] =
'\0';
cg_mount_table[*mnt_tbl_idx].mount.next = NULL;
+ cg_mount_table[*mnt_tbl_idx].version = CGROUP_V1;
cgroup_dbg("Found cgroup option %s, count %d\n",
ent->mnt_opts, *mnt_tbl_idx);
(*mnt_tbl_idx)++;
@@ -1147,6 +1154,96 @@ out:
return ret;
}
+/**
+ * Process a cgroup v2 mount and add it to cg_mount_table if it's not a
+ * duplicate.
+ *
+ * @param ent File system description of cgroup mount being processed
+ * @param mnt_tbl_idx cg_mount_table index
+ */
+static int cgroup_process_v2_mnt(struct mntent *ent, int *mnt_tbl_idx)
+{
+ char cgroup_controllers_path[FILENAME_MAX];
+ char *ret_c = NULL, line[LL_MAX], *stok_buff = NULL;
+ int ret = 0, i, duplicate;
+ FILE *fp = NULL;
+
+ /* determine what v2 controllers are available on this mount */
+ snprintf(cgroup_controllers_path, FILENAME_MAX, "%s/%s",
ent->mnt_dir,
+ CGV2_CONTROLLERS_FILE);
+
+ fp = fopen(cgroup_controllers_path, "re");
+ if (!fp) {
+ ret = ECGOTHER;
+ goto out;
+ }
+
+ ret_c = fgets(line, LL_MAX, fp);
+ if (ret_c == NULL) {
+ ret = ECGEOF;
+ goto out;
+ }
+
+ /* remove the trailing newline */
+ ret_c[strlen(ret_c) - 1] = '\0';
+
+ /*
+ * cgroup.controllers returns a list of available controllers in
+ * the following format:
+ * cpuset cpu io memory pids rdma
+ */
+ stok_buff = strtok(ret_c, " ");
+ while (stok_buff) {
+ /* do not have duplicates in mount table */
+ duplicate = 0;
+
+ for (i = 0; i < *mnt_tbl_idx; i++) {
+ if (strncmp(cg_mount_table[i].name, stok_buff,
+ FILENAME_MAX) == 0) {
+ duplicate = 1;
+ break;
+ }
+ }
+
+ if (duplicate) {
+ cgroup_dbg("controller %s is already mounted on
%s\n",
+ stok_buff, cg_mount_table[i].mount.path);
+
+ ret = cg_add_duplicate_mount(&cg_mount_table[i],
+ ent->mnt_dir);
+ if (ret)
+ goto out;
+
+ /* advance to the next controller */
+ stok_buff = strtok(NULL, " ");
+ continue;
+ }
+
+ /* this controller is not in the mount table. add it */
+ strncpy(cg_mount_table[*mnt_tbl_idx].name,
+ stok_buff, FILENAME_MAX);
+ cg_mount_table[*mnt_tbl_idx].name[FILENAME_MAX-1] = '\0';
+ strncpy(cg_mount_table[*mnt_tbl_idx].mount.path,
+ ent->mnt_dir, FILENAME_MAX);
+ cg_mount_table[*mnt_tbl_idx].mount.path[FILENAME_MAX-1] =
+ '\0';
+ cg_mount_table[*mnt_tbl_idx].mount.next = NULL;
+ cg_mount_table[*mnt_tbl_idx].version = CGROUP_V2;
+ cgroup_dbg("Found cgroup option %s, count %d\n",
+ stok_buff, *mnt_tbl_idx);
+ (*mnt_tbl_idx)++;
+
+ /* advance to the next controller */
+ stok_buff = strtok(NULL, " ");
+ }
+
+out:
+ if (fp)
+ fclose(fp);
+
+ return ret;
+}
+
/**
* cgroup_init(), initializes the MOUNT_POINT.
*
@@ -1255,6 +1352,16 @@ int cgroup_init(void)
if (ret)
goto unlock_exit;
}
+ else if (strcmp(ent->mnt_type, "cgroup2") == 0) {
+ ret = cgroup_process_v2_mnt(ent, &found_mnt);
+ if (ret == ECGEOF)
+ /* The controllers file was empty. Ignore
and
+ * move on.
+ */
+ continue;
+ else if (ret)
+ goto unlock_exit;
+ }
}
free(temp_ent);
@@ -1314,7 +1421,8 @@ static int cg_test_mounted_fs(void)
goto done;
}
- while (strcmp(ent->mnt_type, "cgroup") != 0) {
+ while (strcmp(ent->mnt_type, "cgroup") != 0 &&
+ strcmp(ent->mnt_type, "cgroup2") != 0) {
ent = getmntent_r(proc_mount, temp_ent, mntent_buff,
sizeof(mntent_buff));
if (ent == NULL) {
@@ -2687,25 +2795,27 @@ int cgroup_get_cgroup(struct cgroup *cgroup)
* Get the uid and gid information
*/
- ret = asprintf(&control_path, "%s/tasks", path);
+ if (cg_mount_table[i].version == CGROUP_V1) {
+ ret = asprintf(&control_path, "%s/tasks", path);
- if (ret < 0) {
- last_errno = errno;
- error = ECGOTHER;
- goto unlock_error;
- }
+ if (ret < 0) {
+ last_errno = errno;
+ error = ECGOTHER;
+ goto unlock_error;
+ }
- if (stat(control_path, &stat_buffer)) {
- last_errno = errno;
- free(control_path);
- error = ECGOTHER;
- goto unlock_error;
- }
+ if (stat(control_path, &stat_buffer)) {
+ last_errno = errno;
+ free(control_path);
+ error = ECGOTHER;
+ goto unlock_error;
+ }
- cgroup->tasks_uid = stat_buffer.st_uid;
- cgroup->tasks_gid = stat_buffer.st_gid;
+ cgroup->tasks_uid = stat_buffer.st_uid;
+ cgroup->tasks_gid = stat_buffer.st_gid;
- free(control_path);
+ free(control_path);
+ }
cgc = cgroup_add_controller(cgroup,
cg_mount_table[i].name);
diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h
index e31df512fcbe..dc292c661842 100644
--- a/src/libcgroup-internal.h
+++ b/src/libcgroup-internal.h
@@ -112,6 +112,11 @@ struct cg_mount_point {
struct cg_mount_point *next;
};
+enum cg_version_t {
+ CGROUP_V1,
+ CGROUP_V2,
+};
+
struct cg_mount_table_s {
/** Controller name. */
char name[FILENAME_MAX];
@@ -120,6 +125,7 @@ struct cg_mount_table_s {
*/
struct cg_mount_point mount;
int index;
+ enum cg_version_t version;
};
struct cgroup_rules_data {
--
2.25.3
_______________________________________________
Libcg-devel mailing list
Libcg-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libcg-devel