This commit adds a function that, given a pid, can read in the controllers and cgroups listed in /proc/{pid}/cgroup. The caller is expected to allocate the controller_list[] and cgroup_list[] arrays as well as null each entry in the arrays. cg_get_cgroups_from_proc_cgroups() will allocate the necessary memory for each string within the arrays.
Note that it's common to have many controllers on newer kernels, so MAX_MNT_ELEMENTS was increased to 16 to handle these additional controllers. Signed-off-by: Tom Hromatka <tom.hroma...@oracle.com> --- src/api.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++ src/libcgroup-internal.h | 2 +- 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/src/api.c b/src/api.c index 907475f8d6cf..105816a3ff51 100644 --- a/src/api.c +++ b/src/api.c @@ -4189,6 +4189,109 @@ int cgroup_get_uid_gid_from_procfs(pid_t pid, uid_t *euid, gid_t *egid) } /** + * Given a pid, this function will return the controllers and cgroups that + * the pid is a member of. The caller is expected to allocate the + * controller_list[] and cgroup_list[] arrays as well as null each entry in + * the arrays. This function will allocate the necessary memory for each + * string within the arrays. + * + * @param pid The process id + * @param cgroup_list[] An array of char pointers to hold the cgroups + * @param controller_list[] An array of char pointers to hold the list + * of controllers + * @param list_len The size of the arrays + */ +static int cg_get_cgroups_from_proc_cgroups(pid_t pid, char *cgroup_list[], + char *controller_list[], + int list_len) +{ + char path[FILENAME_MAX]; + char buf[4092]; + char *stok_buff = NULL; + int ret = 0; + size_t buff_len; + int idx = 0; + FILE *f; + + sprintf(path, "/proc/%d/cgroup", pid); + f = fopen(path, "re"); + if (!f) + return ECGROUPNOTEXIST; + + while (fgets(buf, sizeof(buf), f)) { + /* + * Each line in /proc/{pid}/cgroup is like the following: + * + * {cg#}:{controller}:{cgname} + * + * e.g. + * 7:devices:/user.slice + */ + + /* read in the cgroup number. we don't care about it */ + stok_buff = strtok(buf, ":"); + /* read in the controller name */ + stok_buff = strtok(NULL, ":"); + + /* + * after this point, we have allocated memory. if we return + * an error code after this, it's up to us to free the + * memory we allocated + */ + controller_list[idx] = strndup(stok_buff, + strlen(stok_buff) + 1); + + /* read in the cgroup name */ + stok_buff = strtok(NULL, ":"); + + if (stok_buff == NULL) { + /* + * An empty controller is reported on some kernels. + * It may look like this: + * 0::/user.slice/user-1000.slice/session-1.scope + * + * Ignore this controller and move on. Note that we + * need to free the controller list entry we made. + */ + free(controller_list[idx]); + controller_list[idx] = NULL; + continue; + } + + buff_len = strlen(stok_buff); + if (stok_buff[buff_len - 1] == '\n') + /* Don't copy the trailing newline char */ + buff_len--; + + /* read in the cgroup name */ + if (buff_len > 1) { + /* + * Strip off the leading '/' for every cgroup but + * the root cgroup + */ + cgroup_list[idx] = malloc(buff_len); + snprintf(cgroup_list[idx], buff_len, "%s", + &stok_buff[1]); + } else { + /* + * Retain the leading '/' since we're in the root + * cgroup + */ + cgroup_list[idx] = strndup(stok_buff, buff_len); + } + + idx++; + if (idx >= list_len) { + cgroup_warn("Maximum mount elements reached. " + "Consider increasing MAX_MNT_ELEMENTS\n"); + break; + } + } + fclose(f); + return ret; +} + +/** * Get process name from /proc/<pid>/status file. * @param pid: The process id * @param pname_status : The process name diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h index e438916dafaf..b52c82c3f042 100644 --- a/src/libcgroup-internal.h +++ b/src/libcgroup-internal.h @@ -28,7 +28,7 @@ __BEGIN_DECLS #include <setjmp.h> /* Maximum number of mount points/controllers */ -#define MAX_MNT_ELEMENTS 8 +#define MAX_MNT_ELEMENTS 16 /* Estimated number of groups created */ #define MAX_GROUP_ELEMENTS 128 -- 1.8.3.1 _______________________________________________ Libcg-devel mailing list Libcg-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libcg-devel