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