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 <[email protected]>
---
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/libcg-devel