On 09/23/2011 03:53 PM, Jan Safranek wrote:
>
> ---
Oops, no log message... It should be:
libcgroup: added cgroup_config_unload_config() function
This function can be used to remove all groups and mounts defined in a
config file. See doxygen comments for details.
>
> include/libcgroup/config.h | 17 +++++
> src/config.c | 140
> ++++++++++++++++++++++++++++++++++++++++++++
> src/libcgroup.map | 1
> 3 files changed, 158 insertions(+), 0 deletions(-)
>
> diff --git a/include/libcgroup/config.h b/include/libcgroup/config.h
> index 3865603..4cf5ce0 100644
> --- a/include/libcgroup/config.h
> +++ b/include/libcgroup/config.h
> @@ -39,6 +39,23 @@ int cgroup_config_load_config(const char *pathname);
> int cgroup_unload_cgroups(void);
>
> /**
> + * Delete all cgroups and unmount all mount points defined in specified
> config
> + * file.
> + *
> + * The groups are either removed recursively or only the empty ones, based
> + * on given flags. Mount point are always umounted only if they are empty,
> + * regardless of any flags.
> + *
> + * The groups are sorted before they are removed, so the removal of empty
> ones
> + * actually works (i.e. subgroups are removed first).
> + *
> + * @param pathname Name of the configuration file to unload.
> + * @param flags Combination of CGFLAG_DELETE_* flags, which indicate what and
> + * how to delete.
> + */
> +int cgroup_config_unload_config(const char *pathname, int flags);
> +
> +/**
> * @}
> * @}
> */
> diff --git a/src/config.c b/src/config.c
> index e71a400..8548174 100644
> --- a/src/config.c
> +++ b/src/config.c
> @@ -798,6 +798,20 @@ err:
> return ret;
> }
>
> +int _cgroup_config_compare_groups(const void *p1, const void *p2)
> +{
> + const struct cgroup *g1 = p1;
> + const struct cgroup *g2 = p2;
> +
> + return strcmp(g1->name, g2->name);
> +}
> +
> +static void cgroup_config_sort_groups()
> +{
> + qsort(config_cgroup_table, cgroup_table_index, sizeof(struct cgroup),
> + _cgroup_config_compare_groups);
> +}
> +
> /*
> * The main function which does all the setup of the data structures
> * and finally creates the cgroups
> @@ -868,6 +882,132 @@ err_mnt:
> return error;
> }
>
> +/* unmounts given mount, but only if it is empty */
> +static int cgroup_config_try_unmount(struct cg_mount_table_s *mount_info)
> +{
> + char *controller, *controller_list;
> + struct cg_mount_point *mount = &(mount_info->mount);
> + void *handle = NULL;
> + int ret, lvl;
> + struct cgroup_file_info info;
> + char *saveptr = NULL;
> +
> + /* parse the first controller name from list of controllers */
> + controller_list = strdup(mount_info->name);
> + if (!controller_list) {
> + last_errno = errno;
> + return ECGOTHER;
> + }
> + controller = strtok_r(controller_list, ",", &saveptr);
> + if (!controller) {
> + free(controller_list);
> + return ECGINVAL;
> + }
> +
> + /* check if the hierarchy is empty */
> + ret = cgroup_walk_tree_begin(controller, "/", 0, &handle, &info, &lvl);
> + free(controller_list);
> + if (ret == ECGCONTROLLEREXISTS)
> + return 0;
> + if (ret)
> + return ret;
> + /* skip the first found directory, it's '/' */
> + ret = cgroup_walk_tree_next(0, &handle, &info, lvl);
> + /* find any other subdirectory */
> + while (ret == 0) {
> + if (info.type == CGROUP_FILE_TYPE_DIR)
> + break;
> + ret = cgroup_walk_tree_next(0, &handle, &info, lvl);
> + }
> + cgroup_walk_tree_end(&handle);
> + if (ret == 0) {
> + cgroup_dbg("won't unmount %s: hieararchy is not empty\n",
> + mount_info->name);
> + return 0; /* the hieararchy is not empty */
> + }
> + if (ret != ECGEOF)
> + return ret;
> +
> +
> + /*
> + * ret must be ECGEOF now = there is only root group in the hierarchy
> + * -> unmount all mount points.
> + */
> + ret = 0;
> + while (mount) {
> + int err;
> + cgroup_dbg("unmounting %s at %s\n", mount_info->name,
> + mount->path);
> + err = umount(mount->path);
> +
> + if (err && !ret) {
> + ret = ECGOTHER;
> + last_errno = errno;
> + }
> + mount = mount->next;
> + }
> + return ret;
> +}
> +
> +int cgroup_config_unload_config(const char *pathname, int flags)
> +{
> + int ret, i, error;
> + int namespace_enabled = 0;
> + int mount_enabled = 0;
> +
> + cgroup_dbg("cgroup_config_unload_config: parsing %s\n", pathname);
> + ret = cgroup_parse_config(pathname);
> + if (ret)
> + goto err;
> +
> + namespace_enabled = (config_namespace_table[0].name[0] != '\0');
> + mount_enabled = (config_mount_table[0].name[0] != '\0');
> + /*
> + * The configuration should have namespace or mount, not both.
> + */
> + if (namespace_enabled && mount_enabled) {
> + free(config_cgroup_table);
> + return ECGMOUNTNAMESPACE;
> + }
> +
> + ret = config_order_namespace_table();
> + if (ret)
> + goto err;
> +
> + ret = config_validate_namespaces();
> + if (ret)
> + goto err;
> +
> + /*
> + * Delete the groups in reverse order, i.e. subgroups first, then
> + * parents.
> + */
> + cgroup_config_sort_groups();
> + for (i = cgroup_table_index-1; i >= 0; i--) {
> + struct cgroup *cgroup = &config_cgroup_table[i];
> + cgroup_dbg("removing %s\n", pathname);
> + error = cgroup_delete_cgroup_ext(cgroup, flags);
> + if (error && !ret) {
> + /* store the error, but continue deleting the rest */
> + ret = error;
> + }
> + }
> +
> + if (mount_enabled) {
> + for (i = 0; i < config_table_index; i++) {
> + struct cg_mount_table_s *m = &(config_mount_table[i]);
> + cgroup_dbg("unmounting %s\n", m->name);
> + error = cgroup_config_try_unmount(m);
> + if (error && !ret)
> + ret = error;
> + }
> + }
> +
> +err:
> + cgroup_free_config();
> + return ret;
> +}
> +
> static int cgroup_config_unload_controller(const struct cgroup_mount_point
> *mount_info)
> {
> int ret, error;
> diff --git a/src/libcgroup.map b/src/libcgroup.map
> index f1afaf6..7a0927e 100644
> --- a/src/libcgroup.map
> +++ b/src/libcgroup.map
> @@ -102,4 +102,5 @@ CGROUP_0.38 {
> cgroup_get_subsys_mount_point_next;
> cgroup_get_subsys_mount_point_end;
> cgroup_set_permissions;
> + cgroup_config_unload_config;
> } CGROUP_0.37;
>
>
> ------------------------------------------------------------------------------
> All of the data generated in your IT infrastructure is seriously valuable.
> Why? It contains a definitive record of application performance, security
> threats, fraudulent activity, and more. Splunk takes this data and makes
> sense of it. IT sense. And common sense.
> http://p.sf.net/sfu/splunk-d2dcopy2
> _______________________________________________
> Libcg-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/libcg-devel
------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure contains a
definitive record of customers, application performance, security
threats, fraudulent activity and more. Splunk takes this data and makes
sense of it. Business sense. IT sense. Common sense.
http://p.sf.net/sfu/splunk-d2dcopy1
_______________________________________________
Libcg-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libcg-devel