summaryrefslogtreecommitdiffstats
path: root/src/config.c
diff options
context:
space:
mode:
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;
+}