Template cgroups mean control groups which are set in cgrules.conf file and the
name contains % variable like %U (see cgrules.conf manual page for the whole
list of variables).
This patch change cgroup_change_cgroup_flags function. Now if the wanted group
is template group and the group does not exist then cgroup_change_cgroup_flags
create the control group on the fly .
For now the created group can't be set - there is always used function
cgroup_create_cgroup. This will be changed in other patch in this patchset.
EXAMPLE:
e.g.
@students devices people/students/%U
cgroup_change_cgroup_flags will create a cgroup /people/students/john if
user john from group students run a command and the people does not exist yet.
if /people/students group does not exist it will be created as well
CHANGELOG:
backslash -> slash
cgroup_copy_with_backslash: fix the index of final '/' character
add last_errno setting
fix comments
CHANGELOGv2:
incorporate dhaval's feedback:
in cgroup_exist_in_subsystem add ret variable and handle it properly
make cgroup_create_template_group static
free template name if group_name can't be set
return '/' sign if there is a problem in cgroup_create_template_group
while cycle
add new procedure not to have cgroup_create_template_group too large
Signed-off-by: Ivana Hutarova Varekova <[email protected]>
Acked-by: Jan Safranek<[email protected]>
---
src/api.c | 200 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 200 insertions(+), 0 deletions(-)
diff --git a/src/api.c b/src/api.c
index ea75cca..dc19a3a 100644
--- a/src/api.c
+++ b/src/api.c
@@ -2635,6 +2635,199 @@ static struct cgroup_rule
*cgroup_find_matching_rule(uid_t uid,
return ret;
}
+/* Procedure the existence of cgroup "prefix" is in subsystem controller_name
+ * return 0 on success
+ */
+int cgroup_exist_in_subsystem(char *controller_name, char *prefix)
+{
+ DIR *dir;
+ char path[FILENAME_MAX];
+ char *ret_path;
+ int ret;
+
+ pthread_rwlock_rdlock(&cg_mount_table_lock);
+ ret_path = cg_build_path_locked(prefix, path, controller_name);
+ pthread_rwlock_unlock(&cg_mount_table_lock);
+ if (!ret_path) {
+ ret = 1;
+ goto end;
+ }
+
+ dir = opendir(path);
+ if (dir == NULL) {
+ /* cgroup in wanted subsystem does not exist */
+ ret = 1;
+ } else {
+ /* cgroup in wanted subsystem exists */
+ ret = 0;
+ closedir(dir);
+ }
+end:
+ return ret;
+}
+
+/* auxiliary function return a pointer to the string
+ * which is copy of input string and end with the slash
+ */
+char *cgroup_copy_with_slash(char *input)
+{
+ char *output;
+ int len = strlen(input);
+
+ /* if input does not end with '/', allocate one more space for it */
+ if ((input[len-2]) != '/')
+ len = len+1;
+
+ output = (char *)malloc(sizeof(char)*(len));
+ if (output == NULL)
+ return NULL;
+
+ strcpy(output, input);
+ output[len-1] = '/';
+ output[len] = '\0';
+
+ return output;
+}
+
+/* add controller to a group if it is not exists create it */
+static int add_controller(struct cgroup *group, char *group_name,
+ char controller_name[FILENAME_MAX])
+{
+ int ret = 0;
+ struct cgroup_controller *controller = NULL;
+
+ if (group == NULL) {
+ /* it is the first controllerc the group have to be created */
+ group = cgroup_new_cgroup(group_name);
+ if (group == NULL) {
+ ret = ECGFAIL;
+ goto end;
+ }
+ }
+
+ controller = cgroup_add_controller(
+ group, controller_name);
+ if (controller == NULL) {
+ cgroup_free(&group);
+ ret = ECGFAIL;
+ }
+end:
+ return ret;
+}
+
+
+
+/* create control group based given template
+ * if the group already don't exist
+ * dest is template name with substitute variables
+ * tmp is used cgrules rule
+ */
+static int cgroup_create_template_group(char *orig_group_name,
+ struct cgroup_rule *tmp, int flags)
+{
+
+ char *template_name = NULL; /* name of the template */
+ char *group_name = NULL; /* name of the group based on template -
+ variables are substituted */
+ char *template_position; /* denotes directory in template path
+ which is investigated */
+ char *group_position; /* denotes directory in cgroup path
+ which is investigated */
+
+ struct cgroup *template_group = NULL;
+ int ret = 0;
+ int i;
+ int exist;
+
+ /* template name and group name have to have '/' sign at the end */
+ template_name = cgroup_copy_with_slash(tmp->destination);
+ if (template_name == NULL) {
+ ret = ECGOTHER;
+ last_errno = errno;
+ goto end;
+ }
+ group_name = cgroup_copy_with_slash(orig_group_name);
+ if (group_name == NULL) {
+ ret = ECGOTHER;
+ last_errno = errno;
+ free(template_name);
+ goto end;
+ }
+
+ /* set start positions */
+ template_position = strchr(template_name, '/');
+ group_position = strchr(group_name, '/');
+
+ /* go recursively through whole path to template group and create given
+ * directory if it does not exist yet
+ */
+ while ((group_position != NULL) && (template_position != NULL)) {
+ /* set new subpath */
+ group_position[0] = '\0';
+ template_position[0] = '\0';
+ template_group = NULL;
+
+ /* test for which controllers wanted group does not exist */
+ i = 0;
+ while (tmp->controllers[i] != NULL) {
+ exist = cgroup_exist_in_subsystem(tmp->controllers[i],
+ group_name);
+
+ if (exist != 0) {
+ /* the cgroup does not exist */
+ ret = add_controller(template_group, group_name,
+ tmp->controllers[i]);
+ if (ret != 0)
+ goto while_end;
+ }
+ i++;
+ }
+
+ if (template_group != NULL) {
+ /* new group have to be created */
+ if (strcmp(group_name, template_name) == 0) {
+ /* the prefix cgroup without template */
+ ret = cgroup_create_cgroup(template_group, 0);
+ } else {
+ /* TODO: this will be a function which use
+ * template to create relevant cgroup
+ * now cgroup_create_cgroup is used
+ ret = cgroup_config_create_template_group(
+ template_group, template_name,
+ 0, flags);
+ */
+ ret = cgroup_create_cgroup(template_group, 0);
+ }
+
+ if (ret != 0) {
+ cgroup_free(&template_group);
+ goto while_end;
+ }
+ cgroup_dbg("Group %s created - based on template %s\n",
+ group_name, template_name);
+
+ cgroup_free(&template_group);
+ }
+ template_position[0] = '/';
+ group_position[0] = '/';
+ template_position = strchr(++template_position, '/');
+ group_position = strchr(++group_position, '/');
+ }
+
+while_end:
+ if (template_position[0] == '\0')
+ template_position[0] = '/';
+ if (group_position[0] == '\0')
+ group_position[0] = '/';
+
+end:
+ if (group_name != NULL)
+ free(group_name);
+ if (template_name != NULL)
+ free(template_name);
+ return ret;
+}
+
int cgroup_change_cgroup_flags(uid_t uid, gid_t gid,
const char *procname, pid_t pid, int flags)
{
@@ -2783,7 +2976,14 @@ int cgroup_change_cgroup_flags(uid_t uid, gid_t gid,
newdest[j] = tmp->destination[i];
}
}
+
newdest[j] = 0;
+ if (strcmp(newdest, tmp->destination) != 0) {
+ /* destination tag contains templates */
+
+ cgroup_dbg("control group %s is template\n", newdest);
+ ret = cgroup_create_template_group(newdest, tmp, flags);
+ }
/* Apply the rule */
ret = cgroup_change_cgroup_path(newdest,
------------------------------------------------------------------------------
Master HTML5, CSS3, ASP.NET, MVC, AJAX, Knockout.js, Web API and
much more. Get web development skills now with LearnDevNow -
350+ hours of step-by-step video tutorials by Microsoft MVPs and experts.
SALE $99.99 this month only -- learn more at:
http://p.sf.net/sfu/learnmore_122812
_______________________________________________
Libcg-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libcg-devel