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
> Libcg-devel@lists.sourceforge.net
> 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
Libcg-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libcg-devel

Reply via email to