summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDhaval Giani <dhaval@linux.vnet.ibm.com>2008-08-06 17:47:41 +0000
committerDhaval Giani <dhaval@linux.vnet.ibm.com>2008-08-06 17:47:41 +0000
commit1d408fb14ebad88d254f58f733ad6b0ffe4adaf6 (patch)
tree372b1d2c30d3af9a1bc0199cdd21737cbe702221
parentbe7f8e221816cbfd0b69f7593f962133dab2fecf (diff)
downloadlibcg-1d408fb14ebad88d254f58f733ad6b0ffe4adaf6.tar.gz
libcg-1d408fb14ebad88d254f58f733ad6b0ffe4adaf6.tar.xz
libcg-1d408fb14ebad88d254f58f733ad6b0ffe4adaf6.zip
libcgroup: Add new API to get cgroup data structure from filesystem
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
-rw-r--r--api.c153
-rw-r--r--libcgroup.h1
2 files changed, 154 insertions, 0 deletions
diff --git a/api.c b/api.c
index 150f186..17e9d67 100644
--- 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;
+}
diff --git a/libcgroup.h b/libcgroup.h
index 8c12443..89f923a 100644
--- a/libcgroup.h
+++ b/libcgroup.h
@@ -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 */