diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/config.c | 174 | ||||
-rw-r--r-- | src/libcgroup.map | 1 | ||||
-rw-r--r-- | src/tools/Makefile.am | 4 | ||||
-rw-r--r-- | src/tools/cgclear.c | 37 |
4 files changed, 215 insertions, 1 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; +} diff --git a/src/libcgroup.map b/src/libcgroup.map index adcf905..5b088d4 100644 --- a/src/libcgroup.map +++ b/src/libcgroup.map @@ -66,6 +66,7 @@ global: cgroup_get_controller_end; cgroup_get_controller_next; cgroup_get_controller_begin; + cgroup_unload_cgroups; cgroup_get_controller; cgroup_get_uid_gid_from_procfs; } CGROUP_0.33; diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am index 2b4c9e7..f82916c 100644 --- a/src/tools/Makefile.am +++ b/src/tools/Makefile.am @@ -5,7 +5,7 @@ if WITH_TOOLS bin_PROGRAMS = cgexec cgclassify cgcreate cgset -sbin_PROGRAMS = cgconfigparser +sbin_PROGRAMS = cgconfigparser cgclear cgexec_SOURCES = cgexec.c tools-common.c tools-common.h @@ -15,4 +15,6 @@ cgcreate_SOURCES = cgcreate.c tools-common.c tools-common.h cgconfigparser_SOURCES = cgconfig.c +cgclear_SOURCES = cgclear.c + endif diff --git a/src/tools/cgclear.c b/src/tools/cgclear.c new file mode 100644 index 0000000..1485768 --- /dev/null +++ b/src/tools/cgclear.c @@ -0,0 +1,37 @@ +/* + * Copyright IBM Corporation. 2009 + * + * Authors: Dhaval Giani <dhaval@linux.vnet.ibm.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Code initiated and designed by Dhaval Giani. All faults are most likely + * his mistake. + */ + +#include <libcgroup.h> +#include <libcgroup-internal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +int main(int argc, char *argv[]) +{ + int error; + + error = cgroup_unload_cgroups(); + + if (error) { + printf("%s failed with %s\n", argv[0], cgroup_strerror(error)); + exit(3); + } + + return 0; +} |