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 <varek...@redhat.com>
Acked-by: Jan Safranek<jsafr...@redhat.com>
---

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

Reply via email to