On Fri, Jan 11, 2013 at 5:48 PM, Ivana Hutarova Varekova <
varek...@redhat.com> wrote:

> 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);
>

OK, I messed up here ;-). The unlock hsould happen after end: but a lot
more readable now.


> +       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';
>

Wouldn't you get potentially the same effect with
strncpy(output, input, len);
output[len-1] = '/'

(also easier to reason about?)


> +
> +       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 */
>

typo?


> +               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, '/');
> +       }
>

I still think this while loop is too big and should be made bigger.


> +
> +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) {
>

(I haven't checked into it properly, so please correct me here.) strncmp ?


> +                       /* 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 Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS,
MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current
with LearnDevNow - 3,200 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_122412
_______________________________________________
Libcg-devel mailing list
Libcg-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libcg-devel

Reply via email to