Now, cgclear always destroys everything, which does not work well with systemd, which manages its hierarchy by its own.. This patch adds option '-l <config file>', which lets cgclear to destroy only hierarchies explicitly mounted in provided config file, omitting all others. I.e. cgconfig destroys only the hierarchies which cgconfigparser created and does not touch systemd hierarchy.
The -l option does not work with config files with 'namespace' section, I'll try to add this functionality soon. Signed-off-by: Jan Safranek <[email protected]> --- src/config.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/libcgroup.map | 1 + src/tools/cgclear.c | 60 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 128 insertions(+), 8 deletions(-) diff --git a/doc/man/cgclear.1 b/doc/man/cgclear.1 index 9551cfa..7f3d6a9 100644 --- a/doc/man/cgclear.1 +++ b/doc/man/cgclear.1 @@ -6,7 +6,19 @@ cgclear \- unload the cgroup filesystem .SH SYNOPSIS -\fBcgclear\fR +\fBcgclear\fR [\fB-h\fR | \fB-l\fR \fI<filename>\fR] +.SH OPTIONS +.TP +.B -h|--help +Displays help. +.TP +.B -l, --load=FILE +Parses the control groups configuration file and +destroys all hierarchies specified in \fBmount\fR section +of the configuration file. +The format of the file is described in \fBcgconfig.conf\fR. + +Without this option, \fBcgclear\fR destroys all existing hierarchies. .SH DESCRIPTION @@ -15,5 +27,5 @@ to the root cgroup, deletes all the cgroups and finally unmounts the cgroup filesystem from the system. .SH SEE ALSO -cgconfigparser(1) +cgconfigparser(1) cgconfig.conf(5) diff --git a/include/libcgroup/config.h b/include/libcgroup/config.h index dc4719d..2872da1 100644 --- a/include/libcgroup/config.h +++ b/include/libcgroup/config.h @@ -37,6 +37,14 @@ int cgroup_config_load_config(const char *pathname); int cgroup_unload_cgroups(void); /** + * Unload configuration file. + * #- unmount all hierarchies created by 'mount' statement. + * #- (recursively) remove all groups inside 'namespace' statement. + * @param filename Name of the configuration file to parse. + */ +int cgroup_config_unload_config(const char *filename); + +/** * @} * @} */ diff --git a/src/config.c b/src/config.c index bce7178..88fd392 100644 --- a/src/config.c +++ b/src/config.c @@ -67,6 +67,8 @@ static pthread_rwlock_t namespace_table_lock = PTHREAD_RWLOCK_INITIALIZER; static struct cgroup *config_cgroup_table; static int cgroup_table_index; +static int cgroup_config_unload_controller(const char *name, const char *path); + /* * Needed for the type while mounting cgroupfs. */ @@ -642,6 +644,69 @@ error_out: return error; } +int cgroup_config_unload_mount() +{ + int error = 0; + int ret = 0; + int i; + for (i = 0; i < config_table_index; i++) { + struct cg_mount_table_s *curr = &(config_mount_table[i]); + ret = cgroup_config_unload_controller(curr->name, curr->path); + if (ret != 0) + error = ret; + } + return error; +} + +int cgroup_config_unload_namespace() +{ + return ECGFAIL; /* TODO: not implemented for now */ +} + +int cgroup_config_unload_config(const char *filename) +{ + int error = 0; + int namespace_enabled = 0; + int mount_enabled = 0; + yyin = fopen(filename, "re"); + + if (!yyin) { + cgroup_dbg("Failed to open file %s\n", pathname); + last_errno = errno; + return ECGOTHER; + } + + config_cgroup_table = malloc(MAX_CGROUPS * sizeof(struct cgroup)); + if (yyparse() != 0) { + cgroup_dbg("Failed to parse file %s\n", pathname); + fclose(yyin); + free(config_cgroup_table); + return ECGCONFIGPARSEFAIL; + } + fclose(yyin); + + namespace_enabled = (config_namespace_table[0].name[0] != '\0'); + mount_enabled = (config_mount_table[0].name[0] != '\0'); + + /* + * The configuration should have either namespace or mount. + * Not both and not none. + */ + if (namespace_enabled == mount_enabled) { + free(config_cgroup_table); + return ECGMOUNTNAMESPACE; + } + + if (namespace_enabled) { + error = cgroup_config_unload_namespace(); + } + if (mount_enabled) { + error = cgroup_config_unload_mount(); + } + + return error; +} + /* * The main function which does all the setup of the data structures * and finally creates the cgroups @@ -721,7 +786,7 @@ err_mnt: return error; } -static int cgroup_config_unload_controller(const struct cgroup_mount_point *mount_info) +static int cgroup_config_unload_controller(const char *name, const char *path) { int ret, error; struct cgroup *cgroup = NULL; @@ -731,7 +796,7 @@ static int cgroup_config_unload_controller(const struct cgroup_mount_point *moun if (cgroup == NULL) return ECGFAIL; - cgc = cgroup_add_controller(cgroup, mount_info->name); + cgc = cgroup_add_controller(cgroup, name); if (cgc == NULL) { ret = ECGFAIL; goto out_error; @@ -741,14 +806,14 @@ static int cgroup_config_unload_controller(const struct cgroup_mount_point *moun if (ret != 0) goto out_error; - error = umount(mount_info->path); + error = umount(path); if (error) { last_errno = errno; ret = ECGOTHER; goto out_error; } - error = rmdir(mount_info->path); + error = rmdir(path); if (error) { last_errno = errno; ret = ECGOTHER; @@ -792,7 +857,7 @@ int cgroup_unload_cgroups(void) if (!curr_path) goto out_errno; - ret = cgroup_config_unload_controller(&info); + ret = cgroup_config_unload_controller(info.name, info.path); if (ret) goto out_error; diff --git a/src/libcgroup.map b/src/libcgroup.map index 130fc76..056380f 100644 --- a/src/libcgroup.map +++ b/src/libcgroup.map @@ -91,4 +91,5 @@ CGROUP_0.36 { CGROUP_0.37 { cgroup_get_procs; + cgroup_config_unload_config; } CGROUP_0.36; diff --git a/src/tools/cgclear.c b/src/tools/cgclear.c index c286272..80e5ee9 100644 --- a/src/tools/cgclear.c +++ b/src/tools/cgclear.c @@ -17,20 +17,74 @@ #include <libcgroup.h> #include <libcgroup-internal.h> +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> +#include <getopt.h> + +void usage(const char *name, int exitcode) +{ + printf("Usage: %s [OPTION]\n", name); + printf("Destroy control group hierarchies.\n"); + printf("\n"); + printf(" -h, --help Display this help\n"); + printf(" -l, --load=FILE Parse and unload the cgroups from " \ + "configuration file\n"); + exit(exitcode); + +} int main(int argc, char *argv[]) { - int error; + int error = 0, new_error; + int unload_all = 1; + int c; + + static struct option options[] = { + {"help", 0, 0, 'h'}, + {"load", 1, 0, 'l'}, + {0, 0, 0, 0} + }; - error = cgroup_unload_cgroups(); + while ((c = getopt_long(argc, argv, "hl:", options, NULL)) > 0) { + switch (c) { + case 'h': + usage(argv[0], 0); + break; + case 'l': + if (unload_all) { + error = cgroup_init(); + if (error != 0) { + fprintf(stderr, "%s: %s\n", + cgroup_strerror(error)); + exit(1); + } + } + + unload_all = 0; + /* do not overwrite previous errors */ + new_error = cgroup_config_unload_config(optarg); + if (new_error != 0) { + error = new_error; + } + break; + default: + usage(argv[0], 1); + break; + } + } + + if (unload_all) { + error = cgroup_unload_cgroups(); + } /* Don't spit an error when there is nothing to clear. */ if (error == ECGROUPNOTMOUNTED) error = 0; - if (error) { printf("%s failed with %s\n", argv[0], cgroup_strerror(error)); exit(3); ------------------------------------------------------------------------------ Sell apps to millions through the Intel(R) Atom(Tm) Developer Program Be part of this innovative community and reach millions of netbook users worldwide. Take advantage of special opportunities to increase revenue and speed time-to-market. Join now, and jumpstart your future. http://p.sf.net/sfu/intel-atom-d2d _______________________________________________ Libcg-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/libcg-devel
