]> git.ipfire.org Git - thirdparty/libcgroup.git/commitdiff
libcgroup: Add new API to get cgroup data structure from filesystem
authorDhaval Giani <dhaval@linux.vnet.ibm.com>
Wed, 6 Aug 2008 17:47:41 +0000 (17:47 +0000)
committerDhaval Giani <dhaval@linux.vnet.ibm.com>
Wed, 6 Aug 2008 17:47:41 +0000 (17:47 +0000)
New API to get the cgroup datastructure from the mounted filesystem.
It accepts the cgroup datastructure with the name of the cgroup
which has to populated across various mountpoints.

TODO:
More testing.

Signed-off-by: Dhaval Giani <dhaval@linux.vnet.ibm.com>
Cc: Dan Smith <danms@us.ibm.com>
Cc: Paul Menage <menage@google.com>
git-svn-id: https://libcg.svn.sourceforge.net/svnroot/libcg/trunk@117 4f4bb910-9a46-0410-90c8-c897d4f1cd53

api.c
libcgroup.h

diff --git a/api.c b/api.c
index 150f186ea4a98c2ba44cd297eeb3e4f50ea4ac93..17e9d675da29693a21672a4bbaffcf88bb425504 100644 (file)
--- a/api.c
+++ b/api.c
@@ -22,6 +22,7 @@
  * his mistake.
  */
 
+#include <dirent.h>
 #include <errno.h>
 #include <libcgroup.h>
 #include <libcgroup-internal.h>
@@ -661,3 +662,155 @@ base_open_err:
        }
        return error;
 }
+
+/*
+ * This function should really have more checks, but this version
+ * will assume that the callers have taken care of everything.
+ * Including the locking.
+ */
+static char *cg_rd_ctrl_file(char *subsys, char *cgroup, char *file)
+{
+       char *value;
+       char path[FILENAME_MAX];
+       FILE *ctrl_file;
+
+       if (!cg_build_path_locked(cgroup, path, subsys))
+               return NULL;
+
+       strcat(path, file);
+       ctrl_file = fopen(path, "r");
+       if (!ctrl_file)
+               return NULL;
+
+       fscanf(ctrl_file, "%as", &value);
+
+       fclose(ctrl_file);
+
+       return value;
+}
+
+/*
+ * Call this function with required locks taken.
+ */
+static int cgroup_fill_cgc(struct dirent *ctrl_dir, struct cgroup *cgroup,
+                       struct cgroup_controller *cgc, int index)
+{
+       char *ctrl_name;
+       char *ctrl_file;
+       char *ctrl_value;
+       char *d_name;
+       char *buffer;
+       int error = 0;
+
+       d_name = strdup(ctrl_dir->d_name);
+
+       ctrl_name = strtok_r(d_name, ".", &buffer);
+
+       if (!ctrl_name) {
+               error = ECGFAIL;
+               goto fill_error;
+       }
+
+       ctrl_file = strtok_r(NULL, ".", &buffer);
+
+       if (!ctrl_file) {
+               error = ECGFAIL;
+               goto fill_error;
+       }
+
+       if (strcmp(ctrl_name, cg_mount_table[index].name) == 0) {
+               ctrl_value = cg_rd_ctrl_file(cg_mount_table[index].name,
+                               cgroup->name, d_name);
+               if (!ctrl_value) {
+                       error = ECGFAIL;
+                       goto fill_error;
+               }
+
+               if (cgroup_add_value_string(cgc, ctrl_dir->d_name,
+                               ctrl_value)) {
+                       error = ECGFAIL;
+                       goto fill_error;
+               }
+       }
+fill_error:
+       free(ctrl_value);
+       free(d_name);
+       return error;
+}
+
+/*
+ * cgroup_get_cgroup returns the cgroup data from the filesystem.
+ * struct cgroup has the name of the group to be populated
+ *
+ * return succesfully filled cgroup data structure on success.
+ */
+struct cgroup *cgroup_get_cgroup(struct cgroup *cgroup)
+{
+       int i;
+       char path[FILENAME_MAX];
+       DIR *dir;
+       struct dirent *ctrl_dir;
+
+       if (!cgroup_initialized) {
+               /* ECGROUPNOTINITIALIZED */
+               return NULL;
+       }
+
+       if (!cgroup) {
+               /* ECGROUPNOTALLOWED */
+               return NULL;
+       }
+
+       pthread_rwlock_rdlock(&cg_mount_table_lock);
+       for (i = 0; i < CG_CONTROLLER_MAX &&
+                       cg_mount_table[i].name[0] != '\0'; i++) {
+               /*
+                * cgc will not leak, since it has to be freed using
+                * cgroup_free_cgroup
+                */
+               struct cgroup_controller *cgc;
+               if (!cg_build_path_locked(NULL, path,
+                                       cg_mount_table[i].name))
+                       continue;
+
+               strncat(path, cgroup->name, sizeof(path));
+
+               if (access(path, F_OK))
+                       continue;
+
+               if (!cg_build_path_locked(cgroup->name, path,
+                                       cg_mount_table[i].name)) {
+                       /*
+                        * This fails when the cgroup does not exist
+                        * for that controller.
+                        */
+                       continue;
+               }
+
+               cgc = cgroup_add_controller(cgroup,
+                               cg_mount_table[i].name);
+               if (!cgc)
+                       goto unlock_error;
+
+               dir = opendir(path);
+               if (!dir) {
+                       /* error = ECGROUPSTRUCTERROR; */
+                       goto unlock_error;
+               }
+               while ((ctrl_dir = readdir(dir)) != NULL) {
+                       if (cgroup_fill_cgc(ctrl_dir, cgroup, cgc, i)) {
+                               closedir(dir);
+                               goto unlock_error;
+                       }
+
+               }
+               closedir(dir);
+       }
+       pthread_rwlock_unlock(&cg_mount_table_lock);
+       return cgroup;
+
+unlock_error:
+       pthread_rwlock_unlock(&cg_mount_table_lock);
+       cgroup = NULL;
+       return NULL;
+}
index 8c124430cd777a914fd9c8f16de3a38db40b9054..89f923ae67091dc2013048927dbefd7b47b40db0 100644 (file)
@@ -164,6 +164,7 @@ int cgroup_modify_cgroup(struct cgroup *cgroup);
 int cgroup_create_cgroup(struct cgroup *cgroup, int ignore_ownership);
 int cgroup_delete_cgroup(struct cgroup *cgroup, int ignore_migration);
 int cgroup_attach_task_pid(struct cgroup *cgroup, pid_t tid);
+struct cgroup *cgroup_get_cgroup(struct cgroup *cgroup);
 
 /* The wrappers for filling libcg structures */