Quoting Dwight Engen (dwight.en...@oracle.com):
> There were several memory leaks in the cgroup functions, notably in the
> success cases.
> 
> The cgpath test program was refactored and additional tests added to it.
> It was used in various modes under valgrind to test that the leaks were
> fixed.
> 
> Simplify lxc_cgroup_path_get() and cgroup_path_get by having them return a
> char * instead of an int and an output char * argument. The only return
> values ever used were -1 and 0, which are now handled with NULL and non-NULL
> returns respectively.
> 
> Use consistent variable names of cgabspath when refering to an absolute path
> to a cgroup subsystem or file, and cgrelpath when refering to a container
> "group/name" within the cgroup heirarchy.

Excellent.

> Remove unused subsystem argument to lxc_cmd_get_cgroup_path().
> 
> Remove unused #define MAXPRIOLEN
> 
> Make template arg to lxcapi_create() const
> 
> Signed-off-by: Dwight Engen <dwight.en...@oracle.com>

This is great, thanks Dwight.

Acked-by: Serge E. Hallyn <serge.hal...@ubuntu.com>

Except for one thing below,

> ---
>  src/lxc/cgroup.c       | 270 ++++++++++++++++++-----------------
>  src/lxc/cgroup.h       |   6 +-
>  src/lxc/commands.c     |   4 +-
>  src/lxc/commands.h     |   3 +-
>  src/lxc/freezer.c      |  36 ++---
>  src/lxc/lxccontainer.c |   6 +-
>  src/lxc/lxccontainer.h |   4 +-
>  src/lxc/state.c        |  38 ++---
>  src/tests/cgpath.c     | 372 
> +++++++++++++++++++++++++++++++++++++------------
>  9 files changed, 463 insertions(+), 276 deletions(-)
> 
> diff --git a/src/lxc/cgroup.c b/src/lxc/cgroup.c
> index bb1268b..f04d59a 100644
> --- a/src/lxc/cgroup.c
> +++ b/src/lxc/cgroup.c
> @@ -147,102 +147,113 @@ out:
>  }
>  
>  /*
> - * cgroup_path_get: Calculate the full path for a particular subsystem, plus
> - * a passed-in (to be appended) relative cgpath for a container.
> - * @path: a char** into which a pointer to the answer is copied
> - * @subsystem: subsystem of interest (i.e. freezer).
> - * @cgpath: a container's (relative) cgroup path, i.e. "/lxc/c1".
> + * cgroup_path_get: Get the absolute path to a particular subsystem,
> + * plus a passed-in (to be appended) relative cgpath for a container.
>   *
> - * Returns 0 on success, -1 on error.
> + * @subsystem : subsystem of interest (e.g. "freezer")
> + * @cgrelpath : a container's relative cgroup path (e.g. "lxc/c1")
> + *
> + * Returns absolute path on success, NULL on error. The caller must free()
> + * the returned path.
>   *
> + * Note that @subsystem may be the name of an item (e.g. "freezer.state")
> + * in which case the subsystem will be determined by taking the string up
> + * to the first '.'
>   */
> -extern int cgroup_path_get(char **path, const char *subsystem, const char 
> *cgpath)
> +char *cgroup_path_get(const char *subsystem, const char *cgrelpath)
>  {
>       int rc;
>  
>       char *buf = NULL;
> -     char *retbuf = NULL;
> +     char *cgabspath = NULL;
>  
>       buf = malloc(MAXPATHLEN * sizeof(char));
>       if (!buf) {
>               ERROR("malloc failed");
> -             goto fail;
> +             goto out1;
>       }
>  
> -     retbuf = malloc(MAXPATHLEN * sizeof(char));
> -     if (!retbuf) {
> +     cgabspath = malloc(MAXPATHLEN * sizeof(char));
> +     if (!cgabspath) {
>               ERROR("malloc failed");
> -             goto fail;
> +             goto out2;
>       }
>  
>       /* lxc_cgroup_set passes a state object for the subsystem,
>        * so trim it to just the subsystem part */
>       if (subsystem) {
> -             rc = snprintf(retbuf, MAXPATHLEN, "%s", subsystem);
> +             rc = snprintf(cgabspath, MAXPATHLEN, "%s", subsystem);
>               if (rc < 0 || rc >= MAXPATHLEN) {
>                       ERROR("subsystem name too long");
> -                     goto fail;
> +                     goto err3;
>               }
> -             char *s = index(retbuf, '.');
> +             char *s = index(cgabspath, '.');
>               if (s)
>                       *s = '\0';
> -             DEBUG("%s: called for subsys %s name %s\n", __func__, retbuf, 
> cgpath);
> +             DEBUG("%s: called for subsys %s name %s\n", __func__,
> +                   subsystem, cgrelpath);
>       }
> -     if (get_cgroup_mount(subsystem ? retbuf : NULL, buf)) {
> +     if (get_cgroup_mount(subsystem ? cgabspath : NULL, buf)) {
>               ERROR("cgroup is not mounted");
> -             goto fail;
> +             goto err3;
>       }
>  
> -     rc = snprintf(retbuf, MAXPATHLEN, "%s/%s", buf, cgpath);
> +     rc = snprintf(cgabspath, MAXPATHLEN, "%s/%s", buf, cgrelpath);
>       if (rc < 0 || rc >= MAXPATHLEN) {
>               ERROR("name too long");
> -             goto fail;
> +             goto err3;
>       }
>  
> -     DEBUG("%s: returning %s for subsystem %s", __func__, retbuf, subsystem);
> +     DEBUG("%s: returning %s for subsystem %s relpath %s", __func__,
> +             cgabspath, subsystem, cgrelpath);
> +     goto out2;
>  
> -     if(buf)
> -             free(buf);
> -
> -     *path = retbuf;
> -     return 0;
> -fail:
> -     if (buf)
> -             free(buf);
> -     if (retbuf)
> -             free(retbuf);
> -     return -1;
> +err3:
> +     free(cgabspath);
> +     cgabspath = NULL;
> +out2:
> +     free(buf);
> +out1:
> +     return cgabspath;
>  }
>  
>  /*
> - * lxc_cgroup_path_get: determine full pathname for a cgroup
> - * file for a specific container.
> - * @path: char ** used to return the answer.
> - * @subsystem: cgroup subsystem (i.e. "freezer") for which to
> - * return an answer.  If NULL, then the first cgroup entry in
> - * mtab will be used.
> + * lxc_cgroup_path_get: Get the absolute pathname for a cgroup
> + * file for a running container.
> + *
> + * @subsystem : subsystem of interest (e.g. "freezer"). If NULL, then
> + *              the first cgroup entry in mtab will be used.
> + * @name      : name of container to connect to
> + * @lxcpath   : the lxcpath in which the container is running
>   *
>   * This is the exported function, which determines cgpath from the
> - * monitor running in lxcpath.
> + * lxc-start of the @name container running in @lxcpath.
>   *
> - * Returns 0 on success, < 0 on error.
> + * Returns path on success, NULL on error. The caller must free()
> + * the returned path.
>   */
> -int lxc_cgroup_path_get(char **path, const char *subsystem, const char 
> *name, const char *lxcpath)
> +char *lxc_cgroup_path_get(const char *subsystem, const char *name,
> +                       const char *lxcpath)
>  {
> -     int ret;
> -     char *cgpath;
> +     char *cgabspath;
> +     char *cgrelpath;
>  
> -     cgpath = lxc_cmd_get_cgroup_path(subsystem, name, lxcpath);
> -     if (!cgpath)
> -             return -1;
> +     cgrelpath = lxc_cmd_get_cgroup_path(name, lxcpath);
> +     if (!cgrelpath)
> +             return NULL;
>  
> -     ret = cgroup_path_get(path, subsystem, cgpath);
> -     free(cgpath);
> -     return ret;
> +     cgabspath = cgroup_path_get(subsystem, cgrelpath);
> +     free(cgrelpath);
> +     return cgabspath;
>  }
>  
>  /*
> - * small helper which simply write a value into a (cgroup) file
> + * do_cgroup_set: Write a value into a cgroup file
> + *
> + * @path      : absolute path to cgroup file
> + * @value     : value to write into file
> + *
> + * Returns 0 on success, < 0 on error.
>   */
>  static int do_cgroup_set(const char *path, const char *value)
>  {
> @@ -267,87 +278,86 @@ static int do_cgroup_set(const char *path, const char 
> *value)
>  }
>  
>  /*
> - * small helper to write a value into a file in a particular directory.
> - * @cgpath: the directory in which to find the file
> - * @filename: the file (under cgpath) to which to write
> - * @value: what to write
> + * lxc_cgroup_set_bypath: Write a value into a cgroup file
> + *
> + * @cgrelpath : a container's relative cgroup path (e.g. "lxc/c1")
> + * @filename  : the cgroup file to write (e.g. "freezer.state")
> + * @value     : value to write into file
>   *
>   * Returns 0 on success, < 0 on error.
>   */
> -int lxc_cgroup_set_bypath(const char *cgpath, const char *filename, const 
> char *value)
> +int lxc_cgroup_set_bypath(const char *cgrelpath, const char *filename, const 
> char *value)
>  {
>       int ret;
> -     char *dirpath = NULL;
> +     char *cgabspath;
>       char path[MAXPATHLEN];
>  
> -     ret = cgroup_path_get(&dirpath, filename, cgpath);
> -     if (ret)
> -             goto fail;
> +     cgabspath = cgroup_path_get(filename, cgrelpath);
> +     if (!cgabspath)
> +             return -1;
>  
> -     ret = snprintf(path, MAXPATHLEN, "%s/%s", dirpath, filename);
> +     ret = snprintf(path, MAXPATHLEN, "%s/%s", cgabspath, filename);
>       if (ret < 0 || ret >= MAXPATHLEN) {
>               ERROR("pathname too long");
> -             goto fail;
> +             ret = -1;
> +             goto out;
>       }
>  
> -     return do_cgroup_set(path, value);
> +     ret = do_cgroup_set(path, value);
>  
> -fail:
> -     if(dirpath)
> -             free(dirpath);
> -     return -1;
> +out:
> +     free(cgabspath);
> +     return ret;
>  }
>  
>  /*
> - * set a cgroup value for a container
> + * lxc_cgroup_set: Write a value into a cgroup file
>   *
> - * @name: name of the container
> - * @filename: the cgroup file (i.e. freezer.state) whose value to change
> - * @value: the value to write to the file
> - * @lxcpath: the lxcpath under which the container is running.
> + * @name      : name of container to connect to
> + * @filename  : the cgroup file to write (e.g. "freezer.state")
> + * @value     : value to write into file
> + * @lxcpath   : the lxcpath in which the container is running
>   *
>   * Returns 0 on success, < 0 on error.
>   */
> -
>  int lxc_cgroup_set(const char *name, const char *filename, const char *value,
>                  const char *lxcpath)
>  {
>       int ret;
> -     char *dirpath = NULL;
> +     char *cgabspath;
>       char path[MAXPATHLEN];
>  
> -     ret = lxc_cgroup_path_get(&dirpath, filename, name, lxcpath);
> -     if (ret)
> -             goto fail;
> +     cgabspath = lxc_cgroup_path_get(filename, name, lxcpath);
> +     if (!cgabspath)
> +             return -1;
>  
> -     ret = snprintf(path, MAXPATHLEN, "%s/%s", dirpath, filename);
> +     ret = snprintf(path, MAXPATHLEN, "%s/%s", cgabspath, filename);
>       if (ret < 0 || ret >= MAXPATHLEN) {
>               ERROR("pathname too long");
> -             goto fail;
> +             ret = -1;
> +             goto out;
>       }
>  
> -     return do_cgroup_set(path, value);
> +     ret = do_cgroup_set(path, value);
>  
> -fail:
> -     if(dirpath)
> -             free(dirpath);
> -     return -1;
> +out:
> +     free(cgabspath);
> +     return ret;
>  }
>  
>  /*
> - * Get value of a cgroup setting for a container.
> + * lxc_cgroup_get: Read value from a cgroup file
>   *
> - * @name: name of the container
> - * @filename: the cgroup file to read (i.e. 'freezer.state')
> - * @value: a preallocated char* into which to copy the answer
> - * @len: the length of pre-allocated @value
> - * @lxcpath: the lxcpath in which the container is running (i.e.
> - * /var/lib/lxc)
> + * @name      : name of container to connect to
> + * @filename  : the cgroup file to read (e.g. "freezer.state")
> + * @value     : a pre-allocated buffer to copy the answer into
> + * @len       : the length of pre-allocated @value
> + * @lxcpath   : the lxcpath in which the container is running
>   *
> - * Returns < 0 on error, or the number of bytes read.
> + * Returns the number of bytes read on success, < 0 on error
>   *
> - * If you pass in NULL value or 0 len, then you are asking for the size of 
> the
> - * file.
> + * If you pass in NULL value or 0 len, the return value will be the size of
> + * the file, and @value will not contain the contents.
>   *
>   * Note that we can't get the file size quickly through stat or lseek.
>   * Therefore if you pass in len > 0 but less than the file size, your only
> @@ -357,25 +367,26 @@ fail:
>  int lxc_cgroup_get(const char *name, const char *filename, char *value,
>                  size_t len, const char *lxcpath)
>  {
> -     int fd, ret = -1;
> -     char *dirpath = NULL;
> +     int fd, ret;
> +     char *cgabspath;
>       char path[MAXPATHLEN];
> -     int rc;
>  
> -     ret = lxc_cgroup_path_get(&dirpath, filename, name, lxcpath);
> -     if (ret)
> -             goto fail;
> +     cgabspath = lxc_cgroup_path_get(filename, name, lxcpath);
> +     if (!cgabspath)
> +             return -1;
>  
> -     rc = snprintf(path, MAXPATHLEN, "%s/%s", dirpath, filename);
> -     if (rc < 0 || rc >= MAXPATHLEN) {
> +     ret = snprintf(path, MAXPATHLEN, "%s/%s", cgabspath, filename);
> +     if (ret < 0 || ret >= MAXPATHLEN) {
>               ERROR("pathname too long");
> -             goto fail;
> +             ret = -1;
> +             goto out;
>       }
>  
>       fd = open(path, O_RDONLY);
>       if (fd < 0) {
>               ERROR("open %s : %s", path, strerror(errno));
> -             goto fail;
> +             ret = -1;
> +             goto out;
>       }
>  
>       if (!len || !value) {
> @@ -394,47 +405,45 @@ int lxc_cgroup_get(const char *name, const char 
> *filename, char *value,
>               ERROR("read %s : %s", path, strerror(errno));
>  
>       close(fd);
> +out:
> +     free(cgabspath);
>       return ret;
> -fail:
> -     if(dirpath)
> -             free(dirpath);
> -     return -1;
>  }
>  
> -int lxc_cgroup_nrtasks(const char *cgpath)
> +int lxc_cgroup_nrtasks(const char *cgrelpath)
>  {
> -     char *dirpath = NULL;
> +     char *cgabspath = NULL;
>       char path[MAXPATHLEN];
> -     int pid, ret, count = 0;
> +     int pid, ret;
>       FILE *file;
> -     int rc;
>  
> -     ret = cgroup_path_get(&dirpath, NULL, cgpath);
> -     if (ret)
> -             goto fail;
> +     cgabspath = cgroup_path_get(NULL, cgrelpath);
> +     if (!cgabspath)
> +             return -1;
>  
> -     rc = snprintf(path, MAXPATHLEN, "%s/tasks", dirpath);
> -     if (rc < 0 || rc >= MAXPATHLEN) {
> +     ret = snprintf(path, MAXPATHLEN, "%s/tasks", cgabspath);
> +     if (ret < 0 || ret >= MAXPATHLEN) {
>               ERROR("pathname too long");
> -             goto fail;
> +             ret = -1;
> +             goto out;
>       }
>  
>       file = fopen(path, "r");
>       if (!file) {
>               SYSERROR("fopen '%s' failed", path);
> -             return -1;
> +             ret = -1;
> +             goto out;
>       }
>  
> +     ret = 0;
>       while (fscanf(file, "%d", &pid) != EOF)
> -             count++;
> +             ret++;
>  
>       fclose(file);
>  
> -     return count;
> -fail:
> -     if(dirpath)
> -             free(dirpath);
> -     return -1;
> +out:
> +     free(cgabspath);
> +     return ret;
>  }
>  
>  /*
> @@ -654,12 +663,12 @@ char *lxc_cgroup_path_create(const char *lxcgroup, 
> const char *name)
>  
>       char buf[LARGE_MAXPATHLEN] = {0};
>  
> -     if (create_lxcgroups(lxcgroup) < 0)
> -             return NULL;
> -
>       if (!allcgroups)
>               return NULL;
>  
> +     if (create_lxcgroups(lxcgroup) < 0)
> +             goto err1;
> +
>  again:
>       if (visited) {
>               /* we're checking for a new name, so start over with all cgroup
> @@ -670,9 +679,7 @@ again:
>       file = setmntent(MTAB, "r");
>       if (!file) {
>               SYSERROR("failed to open %s", MTAB);
> -             if (allcgroups)
> -                     free(allcgroups);
> -             return NULL;
> +             goto err1;
>       }
>  
>       if (i)
> @@ -730,6 +737,7 @@ next:
>  
>  fail:
>       endmntent(file);
> +err1:
>       free(allcgroups);
>       if (visited)
>               free(visited);
> @@ -880,7 +888,7 @@ int lxc_cgroup_attach(pid_t pid, const char *name, const 
> char *lxcpath)
>       int ret;
>       char *dirpath;
>  
> -     dirpath = lxc_cmd_get_cgroup_path(NULL, name, lxcpath);
> +     dirpath = lxc_cmd_get_cgroup_path(name, lxcpath);
>       if (!dirpath) {
>               ERROR("Error getting cgroup for container %s: %s", lxcpath, 
> name);
>               return -1;
> diff --git a/src/lxc/cgroup.h b/src/lxc/cgroup.h
> index 971311e..747ff5c 100644
> --- a/src/lxc/cgroup.h
> +++ b/src/lxc/cgroup.h
> @@ -23,15 +23,13 @@
>  #ifndef _cgroup_h
>  #define _cgroup_h
>  
> -#define MAXPRIOLEN 24
> -
>  struct lxc_handler;
>  extern int lxc_cgroup_destroy(const char *cgpath);
> -extern int lxc_cgroup_path_get(char **path, const char *subsystem, const 
> char *name,
> +extern char *lxc_cgroup_path_get(const char *subsystem, const char *name,
>                             const char *lxcpath);
>  extern int lxc_cgroup_nrtasks(const char *cgpath);
>  extern char *lxc_cgroup_path_create(const char *lxcgroup, const char *name);
>  extern int lxc_cgroup_enter(const char *cgpath, pid_t pid);
>  extern int lxc_cgroup_attach(pid_t pid, const char *name, const char 
> *lxcpath);
> -extern int cgroup_path_get(char **path, const char *subsystem, const char 
> *cgpath);
> +extern char *cgroup_path_get(const char *subsystem, const char *cgpath);
>  #endif
> diff --git a/src/lxc/commands.c b/src/lxc/commands.c
> index 3f21488..169914e 100644
> --- a/src/lxc/commands.c
> +++ b/src/lxc/commands.c
> @@ -335,15 +335,13 @@ static int lxc_cmd_get_clone_flags_callback(int fd, 
> struct lxc_cmd_req *req,
>   * particular subsystem. This is the cgroup path relative to the root
>   * of the cgroup filesystem.
>   *
> - * @subsystem : the cgroup subsystem of interest (i.e. freezer)
>   * @name      : name of container to connect to
>   * @lxcpath   : the lxcpath in which the container is running
>   *
>   * Returns the path on success, NULL on failure. The caller must free() the
>   * returned path.
>   */
> -char *lxc_cmd_get_cgroup_path(const char *subsystem, const char *name,
> -                           const char *lxcpath)
> +char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath)
>  {
>       int ret, stopped = 0;
>       struct lxc_cmd_rr cmd = {
> diff --git a/src/lxc/commands.h b/src/lxc/commands.h
> index b5b4788..08bde9c 100644
> --- a/src/lxc/commands.h
> +++ b/src/lxc/commands.h
> @@ -67,8 +67,7 @@ struct lxc_cmd_console_rsp_data {
>  
>  extern int lxc_cmd_console(const char *name, int *ttynum, int *fd,
>                          const char *lxcpath);
> -extern char *lxc_cmd_get_cgroup_path(const char *subsystem,
> -                                  const char *name, const char *lxcpath);
> +extern char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath);
>  extern int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath);
>  extern char *lxc_cmd_get_config_item(const char *name, const char *item, 
> const char *lxcpath);
>  extern pid_t lxc_cmd_get_init_pid(const char *name, const char *lxcpath);
> diff --git a/src/lxc/freezer.c b/src/lxc/freezer.c
> index 35bf3a7..37a07fd 100644
> --- a/src/lxc/freezer.c
> +++ b/src/lxc/freezer.c
> @@ -120,19 +120,16 @@ out:
>  
>  static int freeze_unfreeze(const char *name, int freeze, const char *lxcpath)
>  {
> -     char *nsgroup = NULL;
> +     char *cgabspath;
>       int ret;
> -     
> -     ret = lxc_cgroup_path_get(&nsgroup, "freezer", name, lxcpath);
> -     if (ret)
> -             goto fail;
>  
> -     return do_unfreeze(nsgroup, freeze, name, lxcpath);
> +     cgabspath = lxc_cgroup_path_get("freezer", name, lxcpath);
> +     if (!cgabspath)
> +             return -1;
>  
> -fail:
> -     if (nsgroup)
> -             free(nsgroup);
> -     return -1;
> +     ret = do_unfreeze(cgabspath, freeze, name, lxcpath);
> +     free(cgabspath);
> +     return ret;
>  }
>  
>  int lxc_freeze(const char *name, const char *lxcpath)
> @@ -146,19 +143,16 @@ int lxc_unfreeze(const char *name, const char *lxcpath)
>       return freeze_unfreeze(name, 0, lxcpath);
>  }
>  
> -int lxc_unfreeze_bypath(const char *cgpath)
> +int lxc_unfreeze_bypath(const char *cgrelpath)
>  {
> -     char *nsgroup = NULL;
> +     char *cgabspath;
>       int ret;
> -     
> -     ret = cgroup_path_get(&nsgroup, "freezer", cgpath);
> -     if (ret)
> -             goto fail;
>  
> -     return do_unfreeze(nsgroup, 0, NULL, NULL);
> +     cgabspath = cgroup_path_get("freezer", cgrelpath);
> +     if (!cgabspath)
> +             return -1;
>  
> -fail:
> -     if (nsgroup)
> -             free(nsgroup);
> -     return -1;
> +     ret = do_unfreeze(cgabspath, 0, NULL, NULL);
> +     free(cgabspath);
> +     return ret;
>  }
> diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
> index 2934afa..b2e5e36 100644
> --- a/src/lxc/lxccontainer.c
> +++ b/src/lxc/lxccontainer.c
> @@ -570,7 +570,7 @@ static bool create_container_dir(struct lxc_container *c)
>   * for ->create, argv contains the arguments to pass to the template,
>   * terminated by NULL.  If no arguments, you can just pass NULL.
>   */
> -static bool lxcapi_create(struct lxc_container *c, char *t, char *const 
> argv[])
> +static bool lxcapi_create(struct lxc_container *c, const char *t, char 
> *const argv[])
>  {
>       bool bret = false;
>       pid_t pid;
> @@ -636,7 +636,7 @@ static bool lxcapi_create(struct lxc_container *c, char 
> *t, char *const argv[])
>               newargv = malloc(nargs * sizeof(*newargv));
>               if (!newargv)
>                       exit(1);
> -             newargv[0] = t;
> +             newargv[0] = (char *)t;

You're typecasting const char* to char*?

I agree with making the template arg const char *, but then if you need
to do this, it's better to make newargv a char *const (or whatever :) right?

------------------------------------------------------------------------------
Try New Relic Now & We'll Send You this Cool Shirt
New Relic is the only SaaS-based application performance monitoring service 
that delivers powerful full stack analytics. Optimize and monitor your
browser, app, & servers with just a few lines of code. Try New Relic
and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_may
_______________________________________________
Lxc-devel mailing list
Lxc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-devel

Reply via email to