summaryrefslogtreecommitdiffstats
path: root/src/config.c
diff options
context:
space:
mode:
authorDhaval Giani <dhaval@linux.vnet.ibm.com>2009-06-22 17:20:09 +0530
committerDhaval Giani <dhaval@linux.vnet.ibm.com>2009-06-22 17:20:09 +0530
commitb761e6e872d2ef159f0d2e6d80c3fe2b6218bf19 (patch)
tree48da511eeb7d22e44a89a2ce3127b1e97f338449 /src/config.c
parent3ee2b056852a65bc7a3128ef924f1ae83573016e (diff)
downloadlibcg-b761e6e872d2ef159f0d2e6d80c3fe2b6218bf19.tar.gz
libcg-b761e6e872d2ef159f0d2e6d80c3fe2b6218bf19.tar.xz
libcg-b761e6e872d2ef159f0d2e6d80c3fe2b6218bf19.zip
libcgroup: Introduce a unload cgroups API
This API will unload the cgroups created in the cgroupfs and unmount and delete the filesystem mount point. The action is equivalent to what is done currently in service cgconfig stop. The reason for this API is to make sure we don't end up with a asymmetric library API subset. Today an application program can programatically through cgroup_config_load_config() load a configuration file, but has no means to cleanup (including all temporarily created groups). changes from v3 1. Address Jan's comments from http://article.gmane.org/gmane.comp.lib.libcg.devel/1105 changes from v2 1. Fix a leak as noted by Bharata 2. Address Balbir's review comments at http://article.gmane.org/gmane.comp.lib.libcg.devel/1080 changes from v1 1. Change the name of the function to cgroup_unload_cgroups 2. Change the name of the executatble to cgclear 3. Split out the funtions Signed-off-by: Dhaval Giani <dhaval@linux.vnet.ibm.com> Acked-by: Balbir Singh <balbir@linux.vnet.ibm.com>
Diffstat (limited to 'src/config.c')
-rw-r--r--src/config.c174
1 files changed, 174 insertions, 0 deletions
diff --git a/src/config.c b/src/config.c
index 5706e1d..5d5155f 100644
--- a/src/config.c
+++ b/src/config.c
@@ -492,3 +492,177 @@ err_mnt:
fclose(yyin);
return error;
}
+
+static int cgroup_cleanup_cgroup_controller_files(struct cgroup_file_info info,
+ char *root_path, char *ctrl)
+{
+ void *task_handle;
+ pid_t pid;
+ char *rel_path = NULL;
+ int error;
+ int ret;
+
+
+ rel_path = info.full_path + strlen(root_path) - 1;
+
+ if (!strncmp(rel_path, "/", strlen(rel_path)))
+ return 0;
+
+ error = cgroup_get_task_begin(rel_path, ctrl,
+ &task_handle, &pid);
+
+ if (error && error != ECGEOF)
+ return error;
+
+ while (error != ECGEOF) {
+ ret = cgroup_attach_task_pid(NULL, pid);
+
+ if (ret) {
+ cgroup_get_task_end(&task_handle);
+ return ret;
+ }
+ error = cgroup_get_task_next(&task_handle, &pid);
+
+ if (error && error != ECGEOF) {
+ cgroup_get_task_end(&task_handle);
+ return error;
+ }
+ }
+
+ cgroup_get_task_end(&task_handle);
+
+ error = rmdir(info.full_path);
+ if (error) {
+ last_errno = errno;
+ return ECGOTHER;
+ }
+
+ return 0;
+}
+
+static int cgroup_config_unload_controller(struct cgroup_mount_point mount_info)
+{
+ struct cgroup_file_info info;
+ void *tree_handle;
+ int lvl;
+ int ret = 0, error;
+ char *root_path = NULL;
+
+ error = cgroup_walk_tree_begin(mount_info.name, "/", 0, &tree_handle,
+ &info, &lvl);
+
+ if (error && error != ECGEOF)
+ return error;
+
+ root_path = strdup(info.full_path);
+
+ if (!root_path) {
+ cgroup_walk_tree_end(&tree_handle);
+ last_errno = errno;
+ return ECGOTHER;
+ }
+
+ ret = cgroup_walk_tree_set_flags(&tree_handle,
+ CGROUP_WALK_TYPE_POST_DIR);
+
+ if (ret) {
+ cgroup_walk_tree_end(&tree_handle);
+ goto out_error;
+ }
+
+ while (error != ECGEOF) {
+ if (info.type == CGROUP_FILE_TYPE_DIR) {
+ ret = cgroup_cleanup_cgroup_controller_files(info,
+ root_path, mount_info.name);
+
+ if (ret) {
+ cgroup_walk_tree_end(&tree_handle);
+ goto out_error;
+ }
+ }
+
+ error = cgroup_walk_tree_next(0, &tree_handle, &info, lvl);
+
+ if (error && error != ECGEOF) {
+ ret = error;
+ cgroup_walk_tree_end(&tree_handle);
+ }
+ }
+ cgroup_walk_tree_end(&tree_handle);
+ error = umount(mount_info.path);
+
+ if (error) {
+ last_errno = errno;
+ ret = ECGOTHER;
+ goto out_error;
+ }
+
+ error = rmdir(mount_info.path);
+
+ if (error) {
+ last_errno = errno;
+ ret = ECGOTHER;
+ }
+
+out_error:
+ free(root_path);
+ return ret;
+}
+
+int cgroup_unload_cgroups(void)
+{
+ int error = 0;
+ void *ctrl_handle;
+ int ret = 0;
+ char *curr_path = NULL;
+ struct cgroup_mount_point info;
+
+ error = cgroup_init();
+
+ if (error) {
+ ret = error;
+ goto out_error;
+ }
+
+ error = cgroup_get_controller_begin(&ctrl_handle, &info);
+
+
+ if (error && error != ECGEOF) {
+ ret = error;
+ goto out_error;
+ }
+
+ while (error != ECGEOF) {
+ if (!curr_path || strcmp(info.path, curr_path) != 0) {
+ if (curr_path)
+ free(curr_path);
+
+ curr_path = strdup(info.path);
+ if (!curr_path)
+ goto out_errno;
+
+ ret = cgroup_config_unload_controller(info);
+
+ if (ret)
+ goto out_error;
+ }
+
+ error = cgroup_get_controller_next(&ctrl_handle, &info);
+
+ if (error && error != ECGEOF) {
+ ret = error;
+ goto out_error;
+ }
+ }
+
+out_error:
+ if (curr_path)
+ free(curr_path);
+ cgroup_get_controller_end(&ctrl_handle);
+ return ret;
+
+out_errno:
+ last_errno = errno;
+ cgroup_get_controller_end(&ctrl_handle);
+ return ECGOTHER;
+}