On Fri, May 8, 2020 at 7:46 AM Tom Hromatka <tom.hroma...@oracle.com> wrote:
> This commit adds cgroup v2 support to cgroup_init(), > cg_test_mounted_fs(), and cgroup_get_cgroup(). With these > changes, cgget and cgset now work on a cgroup v1 mount, a > cgroup v2 mount, or a cgroup v2 unified mount hierarchy. > > There is a lot of stuff happening in this patch. Could you please split the patch slightly? - prepwork introducing needed fields (Version field comes to mind straight up) - pre reqs needed for v2 support - v2 support I *think* the patch looks fine, but my 8am brain is slow :), the patch split will make it easier to parse the review :) > 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 > _______________________________________________ Libcg-devel mailing list Libcg-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libcg-devel