On Tue, Jan 14, 2014 at 04:41:36PM -0600, Serge Hallyn wrote:
> This patch splits out most of the cgroupfs-specific code, so that
> cgroup-manager versions can be plugged in.  The case I did
> not handle is cgroup_enter at lxc_attach.  I'm hoping that case can
> be greatly simplified, but will worry about it after fleshing out the
> cgroup manager handlers.
> 
> This also simplify the freezer functions.
> 
> This seems to not regress my common tests when running without
> cgmanager, but I'd like to do a bit more testing before pushing.
> However I was hoping to get some more eyes on this so am sending it
> out now.
> 
> Signed-off-by: Serge Hallyn <[email protected]>

So I haven't spotted anything obviously wrong with it, besides the few
functions that are currently marked as unimplemented.

I also confirmed that the code still builds on all supported platforms
(without cgmanager), so if it breaks the existing code path, it doesn't
do so in any obvious way.

> ---
>  configure.ac        |  18 +++
>  src/lxc/Makefile.am |  18 +++
>  src/lxc/attach.c    |   6 +-
>  src/lxc/cgmanager.c | 367 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  src/lxc/cgroup.c    | 350 ++++++++++++++++++++++++++++++++-----------------
>  src/lxc/cgroup.h    |  61 +++++++--
>  src/lxc/commands.c  |  13 +-
>  src/lxc/conf.c      |  10 +-
>  src/lxc/conf.h      |   5 +-
>  src/lxc/freezer.c   |  14 --
>  src/lxc/lxc.h       |   8 --
>  src/lxc/start.c     |  47 ++-----
>  src/lxc/start.h     |   2 +-
>  13 files changed, 718 insertions(+), 201 deletions(-)
>  create mode 100644 src/lxc/cgmanager.c
> 
> diff --git a/configure.ac b/configure.ac
> index 8514267..e513bbe 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -240,6 +240,23 @@ AM_COND_IF([ENABLE_SECCOMP],
>               ])
>       ])
>  
> +# cgmanager
> +AC_ARG_ENABLE([cgmanager],
> +     [AC_HELP_STRING([--enable-cgmanager], [enable cgmanager support 
> [default=auto]])],
> +     [], [enable_cgmanager=auto])
> +
> +if test "x$enable_cgmanager" = "xauto" ; then
> +     
> AC_CHECK_LIB([cgmanager],[cgmanager_create],[enable_cgmanager=yes],[enable_cgmanager=no])
> +fi
> +AM_CONDITIONAL([ENABLE_CGMANAGER], [test "x$enable_cgmanager" = "xyes"])
> +
> +AM_COND_IF([ENABLE_CGMANAGER],
> +     [PKG_CHECK_MODULES([CGMANAGER], [libcgmanager])
> +     PKG_CHECK_MODULES([NIH], [libnih >= 1.0.2])
> +     PKG_CHECK_MODULES([NIH_DBUS], [libnih-dbus >= 1.0.0])
> +     PKG_CHECK_MODULES([DBUS], [dbus-1 >= 1.2.16])
> +     ])
> +
>  # Linux capabilities
>  AC_ARG_ENABLE([capabilities],
>       [AC_HELP_STRING([--enable-capabilities], [enable kernel capabilities 
> support [default=auto]])],
> @@ -684,6 +701,7 @@ Security features:
>   - Linux capabilities: $enable_capabilities
>   - seccomp: $enable_seccomp
>   - SELinux: $enable_selinux
> + - cgmanager: $enable_cgmanager
>  
>  Bindings:
>   - lua: $enable_lua
> diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
> index 1e0232b..34d69a6 100644
> --- a/src/lxc/Makefile.am
> +++ b/src/lxc/Makefile.am
> @@ -93,6 +93,10 @@ liblxc_so_SOURCES = \
>       \
>       $(LSM_SOURCES)
>  
> +if ENABLE_CGMANAGER
> +liblxc_so_SOURCES += cgmanager.c
> +endif
> +
>  if IS_BIONIC
>  liblxc_so_SOURCES += \
>       ../include/ifaddrs.c ../include/ifaddrs.h \
> @@ -122,6 +126,10 @@ if ENABLE_APPARMOR
>  AM_CFLAGS += -DHAVE_APPARMOR
>  endif
>  
> +if ENABLE_CGMANAGER
> +AM_CFLAGS += -DHAVE_CGMANAGER
> +endif
> +
>  if ENABLE_SELINUX
>  AM_CFLAGS += -DHAVE_SELINUX
>  endif
> @@ -144,6 +152,11 @@ liblxc_so_LDFLAGS = \
>  
>  liblxc_so_LDADD = $(CAP_LIBS) $(APPARMOR_LIBS) $(SECCOMP_LIBS)
>  
> +#if ENABLE_CGMANAGER
> +liblxc_so_LDADD += $(CGMANAGER_LIBS) $(DBUS_LIBS) $(NIH_LIBS) 
> $(NIH_DBUS_LIBS)
> +liblxc_so_CFLAGS += $(CGMANAGER_CFLAGS) $(DBUS_CFLAGS) $(NIH_CFLAGS) 
> $(NIH_DBUS_CFLAGS)
> +#endif
> +
>  bin_SCRIPTS = \
>       lxc-ps \
>       lxc-netstat \
> @@ -245,6 +258,11 @@ LDADD=liblxc.so @CAP_LIBS@ @APPARMOR_LIBS@ @SECCOMP_LIBS@
>  lxc_attach_SOURCES = lxc_attach.c
>  lxc_autostart_SOURCES = lxc_autostart.c
>  lxc_cgroup_SOURCES = lxc_cgroup.c
> +#if ENABLE_CGMANAGER
> +lxc_cgroup_SOURCES += cgmanager.c
> +lxc_cgroup_LDADD = $(CGMANAGER_LIBS) $(DBUS_LIBS) $(NIH_LIBS) 
> $(NIH_DBUS_LIBS) $(LDADD)
> +lxc_cgroup_CFLAGS = $(CGMANAGER_CFLAGS) $(DBUS_CFLAGS) $(NIH_CFLAGS) 
> $(NIH_DBUS_CFLAGS)
> +#endif
>  lxc_checkpoint_SOURCES = lxc_checkpoint.c
>  lxc_config_SOURCES = lxc_config.c
>  lxc_console_SOURCES = lxc_console.c
> diff --git a/src/lxc/attach.c b/src/lxc/attach.c
> index 422f24c..de32549 100644
> --- a/src/lxc/attach.c
> +++ b/src/lxc/attach.c
> @@ -748,7 +748,11 @@ int lxc_attach(const char* name, const char* lxcpath, 
> lxc_attach_exec_t exec_fun
>                               goto cleanup_error;
>                       }
>  
> -                     ret = lxc_cgroup_enter(container_info, attached_pid, 
> false);
> +                     /*
> +                      * TODO - switch over to using a cgroup_operation.  We 
> can't use
> +                      * cgroup_enter() as that takes a handler.
> +                      */
> +                     ret = lxc_cgroupfs_enter(container_info, attached_pid, 
> false);
>                       lxc_cgroup_process_info_free(container_info);
>                       if (ret < 0) {
>                               ERROR("could not move attached process %ld to 
> cgroup of container", (long)attached_pid);
> diff --git a/src/lxc/cgmanager.c b/src/lxc/cgmanager.c
> new file mode 100644
> index 0000000..92745dc
> --- /dev/null
> +++ b/src/lxc/cgmanager.c
> @@ -0,0 +1,367 @@
> +/*
> + * lxc: linux Container library
> + *
> + * (C) Copyright IBM Corp. 2007, 2008
> + *
> + * Authors:
> + * Daniel Lezcano <daniel.lezcano at free.fr>
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
> USA
> + */
> +#define _GNU_SOURCE
> +#include <stdio.h>
> +#undef _GNU_SOURCE
> +#include <stdlib.h>
> +#include <errno.h>
> +#include <unistd.h>
> +#include <string.h>
> +#include <dirent.h>
> +#include <fcntl.h>
> +#include <ctype.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <sys/param.h>
> +#include <sys/inotify.h>
> +#include <sys/mount.h>
> +#include <netinet/in.h>
> +#include <net/if.h>
> +
> +#include "error.h"
> +#include "config.h"
> +#include "commands.h"
> +#include "list.h"
> +#include "conf.h"
> +#include "utils.h"
> +#include "bdev.h"
> +#include "log.h"
> +#include "cgroup.h"
> +#include "start.h"
> +#include "state.h"
> +
> +#ifdef HAVE_CGMANAGER
> +lxc_log_define(lxc_cgmanager, lxc);
> +
> +#include <nih-dbus/dbus_connection.h>
> +#include <cgmanager-client/cgmanager-client.h>
> +NihDBusProxy *cgroup_manager = NULL;
> +
> +extern struct cgroup_ops *active_cg_ops;
> +bool cgmanager_initialized = false;
> +bool use_cgmanager = true;
> +static struct cgroup_ops cgmanager_ops;
> +
> +bool lxc_init_cgmanager(void);
> +static void cgmanager_disconnected(DBusConnection *connection)
> +{
> +     WARN("Cgroup manager connection was terminated");
> +     cgroup_manager = NULL;
> +     cgmanager_initialized = false;
> +     if (lxc_init_cgmanager()) {
> +             cgmanager_initialized = true;
> +             INFO("New cgroup manager connection was opened");
> +     }
> +}
> +
> +#define CGMANAGER_DBUS_SOCK "unix:path=/sys/fs/cgroup/cgmanager/sock"
> +bool lxc_init_cgmanager(void)
> +{
> +     DBusError dbus_error;
> +     DBusConnection *connection;
> +     dbus_error_init(&dbus_error);
> +
> +     connection = nih_dbus_connect(CGMANAGER_DBUS_SOCK, 
> cgmanager_disconnected);
> +     if (!connection) {
> +             ERROR("Error opening cgmanager connection at %s", 
> CGMANAGER_DBUS_SOCK);
> +             return false;
> +     }
> +     dbus_connection_set_exit_on_disconnect(connection, FALSE);
> +     dbus_error_free(&dbus_error);
> +     cgroup_manager = nih_dbus_proxy_new(NULL, connection,
> +                             NULL /* p2p */,
> +                             "/org/linuxcontainers/cgmanager", NULL, NULL);
> +     dbus_connection_unref(connection);
> +     if (!cgroup_manager) {
> +             return false;
> +     }
> +     active_cg_ops = &cgmanager_ops;
> +     return true;
> +}
> +
> +/*
> + * Use the cgmanager to move a task into a cgroup for a particular
> + * hierarchy.
> + * All the subsystems in this hierarchy are co-mounted, so we only
> + * need to transition the task into one of the cgroups
> + */
> +static bool lxc_cgmanager_enter(pid_t pid, char *controller, char 
> *cgroup_path)
> +{
> +     return cgmanager_move_pid_sync(NULL, cgroup_manager, controller,
> +                                    cgroup_path, pid) == 0;
> +}
> +
> +static bool lxc_cgmanager_create(const char *controller, const char 
> *cgroup_path, int32_t *existed)
> +{
> +     if ( cgmanager_create_sync(NULL, cgroup_manager, controller,
> +                                    cgroup_path, existed) != 0) {
> +             ERROR("Failed to create %s:%s", controller, cgroup_path);
> +             return false;
> +     }
> +
> +     // TODO - try to chown the cgroup to the container root
> +     return true;
> +}
> +
> +
> +struct cgm_data {
> +     int nr_subsystems;
> +     char **subsystems;
> +     char *cgroup_path;
> +};
> +
> +void cgmanager_remove_cgroup(const char *subsystem, const char *path)
> +{
> +     // TODO implement
> +     WARN("%s: not yet implemented", __func__);
> +}
> +
> +static void cgm_destroy(struct lxc_handler *handler)
> +{
> +     struct cgm_data *d = handler->cgroup_info->data;
> +     int i;
> +
> +     if (!d)
> +             return;
> +     for (i=0; i<d->nr_subsystems; i++) {
> +             if (d->cgroup_path)
> +                     cgmanager_remove_cgroup(d->subsystems[i], 
> d->cgroup_path);
> +             free(d->subsystems[i]);
> +     }
> +     free(d->subsystems);
> +     free(d->cgroup_path);
> +     free(d);
> +     handler->cgroup_info->data = NULL;
> +}
> +
> +/*
> + * remove all the cgroups created
> + */
> +static inline void cleanup_cgroups(struct cgm_data *d, char *path)
> +{
> +     int i;
> +     for (i = 0; i < d->nr_subsystems; i++) {
> +             cgmanager_remove_cgroup(d->subsystems[i], path);
> +     }
> +}
> +
> +static inline bool cgm_create(struct lxc_handler *handler)
> +{
> +     int i, index=0, baselen, ret;
> +     int32_t existed;
> +     char result[MAXPATHLEN], *tmp;
> +     struct cgm_data *d = handler->cgroup_info->data;
> +
> +// XXX we should send a hint to the cgmanager that when these
> +// cgroups become empty they should be deleted.  Requires a cgmanager
> +// extension
> +
> +     memset(result, 0, MAXPATHLEN);
> +     tmp = lxc_string_replace("%n", handler->name, 
> handler->cgroup_info->cgroup_pattern);
> +     if (!tmp)
> +             return false;
> +     if (strlen(tmp) > MAXPATHLEN)
> +             return false;
> +     strcpy(result, tmp);
> +     baselen = strlen(result);
> +     free(tmp);
> +     tmp = result;
> +     while (*tmp == '/')
> +             tmp++;
> +again:
> +     if (index == 100) { // turn this into a warn later
> +             ERROR("cgroup error?  100 cgroups with this name already 
> running");
> +             return false;
> +     }
> +     if (index) {
> +             ret = snprintf(result+baselen, MAXPATHLEN-baselen, "-%d", 
> index);
> +             if (ret < 0 || ret >= MAXPATHLEN-baselen)
> +                     return false;
> +     }
> +     existed = 0;
> +     for (i = 0; i < d->nr_subsystems; i++) {
> +             if (!lxc_cgmanager_create(d->subsystems[i], tmp, &existed)) {
> +                     ERROR("Error creating cgroup %s:%s", d->subsystems[i], 
> result);
> +                     cleanup_cgroups(d, tmp);
> +                     return false;
> +             }
> +             if (existed)
> +                     goto next;
> +     }
> +     // success
> +     d->cgroup_path = strdup(tmp);
> +     if (!d->cgroup_path) {
> +             cleanup_cgroups(d, tmp);
> +             return false;
> +     }
> +     return true;
> +next:
> +     cleanup_cgroups(d, tmp);
> +     index++;
> +     goto again;
> +}
> +
> +static inline bool cgm_enter(struct lxc_handler *handler)
> +{
> +     struct cgm_data *d = handler->cgroup_info->data;
> +     int i;
> +
> +     for (i = 0; i < d->nr_subsystems; i++) {
> +             if (!lxc_cgmanager_enter(handler->pid, d->subsystems[i], 
> d->cgroup_path))
> +                     return false;
> +     }
> +     return true;
> +}
> +
> +static char *cgm_get_cgroup(struct lxc_handler *handler, const char 
> *subsystem)
> +{
> +     struct cgm_data *d = handler->cgroup_info->data;
> +     return d->cgroup_path;
> +}
> +
> +int cgm_get(const char *filename, char *value, size_t len, const char *name, 
> const char *lxcpath)
> +{
> +     char *result, *controller, *key, *cgroup;
> +
> +     controller = alloca(strlen(filename)+1);
> +     key = strchr(controller, '.');
> +     if (!key)
> +             return false;
> +     *key = '\0';
> +     key++;
> +
> +     /* use the command interface to look for the cgroup */
> +     cgroup = lxc_cmd_get_cgroup_path(name, lxcpath, controller);
> +     if (!cgroup) {
> +             ERROR("Failed to get cgroup for controller %s for %s:%s",
> +                     controller, lxcpath, name);
> +             return false;
> +     }
> +     if (cgmanager_get_value_sync(NULL, cgroup_manager, controller, cgroup, 
> key, &result) != 0) {
> +             ERROR("Error getting value for %s from cgmanager for cgroup %s 
> (%s:%s)",
> +                     filename, cgroup, lxcpath, name);
> +             free(cgroup);
> +             return false;
> +     }
> +     free(cgroup);
> +     strncpy(value, result, len);
> +     if (strlen(result) >= len)
> +             value[len-1] = '\0';
> +     free(result);
> +     return true;
> +}
> +
> +int cgm_set(const char *filename, const char *value, const char *name, const 
> char *lxcpath)
> +{
> +     char *controller, *key, *cgroup;
> +
> +     controller = alloca(strlen(filename)+1);
> +     key = strchr(controller, '.');
> +     if (!key)
> +             return false;
> +     *key = '\0';
> +     key++;
> +
> +     /* use the command interface to look for the cgroup */
> +     cgroup = lxc_cmd_get_cgroup_path(name, lxcpath, controller);
> +     if (!cgroup) {
> +             ERROR("Failed to get cgroup for controller %s for %s:%s",
> +                     controller, lxcpath, name);
> +             return false;
> +     }
> +     if (cgmanager_set_value_sync(NULL, cgroup_manager, controller, cgroup, 
> key, value) != 0) {
> +             ERROR("Error setting value for %s from cgmanager for cgroup %s 
> (%s:%s)",
> +                     filename, cgroup, lxcpath, name);
> +             free(cgroup);
> +             return false;
> +     }
> +     free(cgroup);
> +     return true;
> +}
> +
> +/*
> + * TODO really this should be done once for global data, not once
> + * per container
> + */
> +static inline bool cgm_init(struct lxc_handler *handler)
> +{
> +     struct cgm_data *d = malloc(sizeof(*d));
> +     char *line = NULL, *tab1;
> +     size_t sz = 0, i;
> +     FILE *f;
> +
> +     if (!d)
> +             return false;
> +     d->nr_subsystems = 0;
> +     d->subsystems = NULL;
> +     f = fopen_cloexec("/proc/cgroups", "r");
> +     if (!f) {
> +             free(d);
> +             return false;
> +     }
> +     while (getline(&line, &sz, f) != -1) {
> +             char **tmp;
> +             if (line[0] == '#')
> +                     continue;
> +             if (!line[0])
> +                     continue;
> +             tab1 = strchr(line, '\t');
> +             if (!tab1)
> +                     continue;
> +             *tab1 = '\0';
> +             tmp = realloc(d->subsystems, (d->nr_subsystems+1)*sizeof(char 
> *));
> +             if (!tmp) {
> +                     goto out_free;
> +             }
> +             d->subsystems = tmp;
> +             d->subsystems[d->nr_subsystems] = strdup(line);
> +             if (!d->subsystems[d->nr_subsystems])
> +                     goto out_free;
> +             d->nr_subsystems++;
> +     }
> +     fclose(f);
> +
> +     d->cgroup_path = NULL;
> +     handler->cgroup_info->data = d;
> +     return true;
> +
> +out_free:
> +     for (i=0; i<d->nr_subsystems; i++)
> +             free(d->subsystems[i]);
> +     free(d->subsystems);
> +     free(d);
> +     return false;
> +}
> +
> +static struct cgroup_ops cgmanager_ops = {
> +     .destroy = cgm_destroy,
> +     .init = cgm_init,
> +     .create = cgm_create,
> +     .enter = cgm_enter,
> +     .create_legacy = NULL,
> +     .get_cgroup = cgm_get_cgroup,
> +     .get = cgm_get,
> +     .set = cgm_set,
> +     .name = "cgmanager"
> +};
> +#endif
> diff --git a/src/lxc/cgroup.c b/src/lxc/cgroup.c
> index 6d837f9..efc3e23 100644
> --- a/src/lxc/cgroup.c
> +++ b/src/lxc/cgroup.c
> @@ -76,6 +76,21 @@ static int cgroup_recursive_task_count(const char 
> *cgroup_path);
>  static int count_lines(const char *fn);
>  static int handle_cgroup_settings(struct cgroup_mount_point *mp, char 
> *cgroup_path);
>  
> +static struct cgroup_ops cgfs_ops;
> +struct cgroup_ops *active_cg_ops = &cgfs_ops;
> +static void init_cg_ops(void);
> +
> +#ifdef HAVE_CGMANAGER
> +/* this needs to be mutexed for api use */
> +extern bool cgmanager_initialized;
> +extern bool use_cgmanager;
> +extern bool lxc_init_cgmanager(void);
> +#else
> +static bool cgmanager_initialized = false;
> +static bool use_cgmanager = false;
> +static bool lxc_init_cgmanager(void) { return false; }
> +#endif
> +
>  static int cgroup_rmdir(char *dirname)
>  {
>       struct dirent dirent, *direntp;
> @@ -170,7 +185,7 @@ struct cgroup_meta_data *lxc_cgroup_load_meta()
>  }
>  
>  /* Step 1: determine all kernel subsystems */
> -static bool find_cgroup_subsystems(char ***kernel_subsystems)
> +bool find_cgroup_subsystems(char ***kernel_subsystems)
>  {
>       FILE *proc_cgroups;
>       bool bret = false;
> @@ -710,7 +725,7 @@ static char *cgroup_rename_nsgroup(const char *mountpath, 
> const char *oldname, p
>  }
>  
>  /* create a new cgroup */
> -extern struct cgroup_process_info *lxc_cgroup_create(const char *name, const 
> char *path_pattern, struct cgroup_meta_data *meta_data, const char 
> *sub_pattern)
> +struct cgroup_process_info *lxc_cgroupfs_create(const char *name, const char 
> *path_pattern, struct cgroup_meta_data *meta_data, const char *sub_pattern)
>  {
>       char **cgroup_path_components = NULL;
>       char **p = NULL;
> @@ -1042,7 +1057,7 @@ out_error:
>  }
>  
>  /* move a processs to the cgroups specified by the membership */
> -int lxc_cgroup_enter(struct cgroup_process_info *info, pid_t pid, bool 
> enter_sub)
> +int lxc_cgroupfs_enter(struct cgroup_process_info *info, pid_t pid, bool 
> enter_sub)
>  {
>       char pid_buf[32];
>       char *cgroup_tasks_fn;
> @@ -1126,9 +1141,11 @@ void lxc_cgroup_process_info_free_and_remove(struct 
> cgroup_process_info *info)
>       lxc_cgroup_process_info_free_and_remove(next);
>  }
>  
> -char *lxc_cgroup_get_hierarchy_path_handler(const char *subsystem, struct 
> lxc_handler *handler)
> +static char *lxc_cgroup_get_hierarchy_path_handler(const char *subsystem, 
> struct lxc_handler *handler)
>  {
> -     struct cgroup_process_info *info = 
> find_info_for_subsystem(handler->cgroup, subsystem);
> +     struct cgfs_data *d = handler->cgroup_info->data;
> +     struct cgroup_process_info *info = d->info;
> +     info = find_info_for_subsystem(info, subsystem);
>       if (!info)
>               return NULL;
>       return info->cgroup_path;
> @@ -1141,8 +1158,11 @@ char *lxc_cgroup_get_hierarchy_path(const char 
> *subsystem, const char *name, con
>  
>  char *lxc_cgroup_get_hierarchy_abs_path_handler(const char *subsystem, 
> struct lxc_handler *handler)
>  {
> +     struct cgfs_data *d = handler->cgroup_info->data;
> +     struct cgroup_process_info *info = d->info;
>       struct cgroup_mount_point *mp = NULL;
> -     struct cgroup_process_info *info = 
> find_info_for_subsystem(handler->cgroup, subsystem);
> +
> +     info = find_info_for_subsystem(info, subsystem);
>       if (!info)
>               return NULL;
>       if (info->designated_mount_point) {
> @@ -1223,7 +1243,7 @@ int lxc_cgroup_get_handler(const char *filename, char 
> *value, size_t len, struct
>       return ret;
>  }
>  
> -int lxc_cgroup_set(const char *filename, const char *value, const char 
> *name, const char *lxcpath)
> +int lxc_cgroupfs_set(const char *filename, const char *value, const char 
> *name, const char *lxcpath)
>  {
>       char *subsystem = NULL, *p, *path;
>       int ret = -1;
> @@ -1241,7 +1261,7 @@ int lxc_cgroup_set(const char *filename, const char 
> *value, const char *name, co
>       return ret;
>  }
>  
> -int lxc_cgroup_get(const char *filename, char *value, size_t len, const char 
> *name, const char *lxcpath)
> +int lxc_cgroupfs_get(const char *filename, char *value, size_t len, const 
> char *name, const char *lxcpath)
>  {
>       char *subsystem = NULL, *p, *path;
>       int ret = -1;
> @@ -1299,17 +1319,7 @@ char *lxc_cgroup_path_get(const char *filename, const 
> char *name,
>       return path;
>  }
>  
> -int lxc_setup_cgroup_without_devices(struct lxc_handler *h, struct lxc_list 
> *cgroup_settings)
> -{
> -     return do_setup_cgroup(h, cgroup_settings, false);
> -}
> -
> -int lxc_setup_cgroup_devices(struct lxc_handler *h, struct lxc_list 
> *cgroup_settings)
> -{
> -     return do_setup_cgroup(h, cgroup_settings, true);
> -}
> -
> -int lxc_setup_mount_cgroup(const char *root, struct cgroup_process_info 
> *base_info, int type)
> +int lxc_setup_mount_cgroup(const char *root, struct lxc_cgroup_info 
> *cgroup_info, int type)
>  {
>       size_t bufsz = strlen(root) + sizeof("/sys/fs/cgroup");
>       char *path = NULL;
> @@ -1317,9 +1327,20 @@ int lxc_setup_mount_cgroup(const char *root, struct 
> cgroup_process_info *base_in
>       char *dirname = NULL;
>       char *abs_path = NULL;
>       char *abs_path2 = NULL;
> -     struct cgroup_process_info *info;
> +     struct cgfs_data *cgfs_d;
> +     struct cgroup_process_info *info, *base_info;
>       int r, saved_errno = 0;
>  
> +     init_cg_ops();
> +
> +     if (strcmp(active_cg_ops->name, "cgmanager") == 0) {
> +             // todo - offer to bind-mount /sys/fs/cgroup/cgmanager/
> +             return 0;
> +     }
> +
> +     cgfs_d = cgroup_info->data;
> +     base_info = cgfs_d->info;
> +
>       if (type < LXC_AUTO_CGROUP_RO || type > LXC_AUTO_CGROUP_FULL_MIXED) {
>               ERROR("could not mount cgroups into container: invalid type 
> specified internally");
>               errno = EINVAL;
> @@ -1488,7 +1509,8 @@ out_error:
>  
>  int lxc_cgroup_nrtasks_handler(struct lxc_handler *handler)
>  {
> -     struct cgroup_process_info *info = handler->cgroup;
> +     struct cgfs_data *d = handler->cgroup_info->data;
> +     struct cgroup_process_info *info = d->info;
>       struct cgroup_mount_point *mp = NULL;
>       char *abs_path = NULL;
>       int ret;
> @@ -2020,133 +2042,227 @@ int handle_cgroup_settings(struct 
> cgroup_mount_point *mp, char *cgroup_path)
>  
>  extern void lxc_monitor_send_state(const char *name, lxc_state_t state,
>                           const char *lxcpath);
> -int do_unfreeze(const char *nsgroup, int freeze, const char *name, const 
> char *lxcpath)
> +int do_unfreeze(int freeze, const char *name, const char *lxcpath)
>  {
> -     char freezer[MAXPATHLEN], *f;
> -     char tmpf[32];
> -     int fd, ret;
> +     char v[100];
> +     const char *state = freeze ? "FROZEN" : "THAWED";
>  
> -     ret = snprintf(freezer, MAXPATHLEN, "%s/freezer.state", nsgroup);
> -     if (ret >= MAXPATHLEN) {
> -             ERROR("freezer.state name too long");
> +     if (lxc_cgroup_set("freezer.state", state, name, lxcpath) < 0) {
> +             ERROR("Failed to freeze %s:%s", lxcpath, name);
>               return -1;
>       }
> -
> -     fd = open(freezer, O_RDWR);
> -     if (fd < 0) {
> -             SYSERROR("failed to open freezer at '%s'", nsgroup);
> -             return -1;
> +     while (1) {
> +             if (lxc_cgroup_get("freezer.state", v, 100, name, lxcpath) < 0) 
> {
> +                     ERROR("Failed to get new freezer state for %s:%s", 
> lxcpath, name);
> +                     return -1;
> +             }
> +             if (v[strlen(v)-1] == '\n')
> +                     v[strlen(v)-1] = '\0';
> +             if (strncmp(v, state, strlen(state)) == 0) {
> +                     if (name)
> +                             lxc_monitor_send_state(name, freeze ? FROZEN : 
> THAWED, lxcpath);
> +                     return 0;
> +             }
> +             sleep(1);
>       }
> +}
>  
> -     if (freeze) {
> -             f = "FROZEN";
> -             ret = write(fd, f, strlen(f) + 1);
> -     } else {
> -             f = "THAWED";
> -             ret = write(fd, f, strlen(f) + 1);
> +int freeze_unfreeze(const char *name, int freeze, const char *lxcpath)
> +{
> +     return do_unfreeze(freeze, name, lxcpath);
> +}
>  
> -             /* compatibility code with old freezer interface */
> -             if (ret < 0) {
> -                     f = "RUNNING";
> -                     ret = write(fd, f, strlen(f) + 1) < 0;
> -             }
> +lxc_state_t freezer_state(const char *name, const char *lxcpath)
> +{
> +     char v[100];
> +     if (lxc_cgroup_get("freezer.state", v, 100, name, lxcpath) < 0) {
> +             ERROR("Failed to get freezer state for %s:%s", lxcpath, name);
> +             return -1;
>       }
>  
> -     if (ret < 0) {
> -             SYSERROR("failed to write '%s' to '%s'", f, freezer);
> -             goto out;
> -     }
> +     if (v[strlen(v)-1] == '\n')
> +             v[strlen(v)-1] = '\0';
> +     return lxc_str2state(v);
> +}
>  
> -     while (1) {
> -             ret = lseek(fd, 0L, SEEK_SET);
> -             if (ret < 0) {
> -                     SYSERROR("failed to lseek on file '%s'", freezer);
> -                     goto out;
> -             }
> +static void cgfs_destroy(struct lxc_handler *handler)
> +{
> +     struct cgfs_data *d = handler->cgroup_info->data;
> +     if (!d)
> +             return;
> +     if (d->info)
> +             lxc_cgroup_process_info_free_and_remove(d->info);
> +     if (d->meta)
> +             lxc_cgroup_put_meta(d->meta);
> +     free(d);
> +     handler->cgroup_info->data = NULL;
> +}
>  
> -             ret = read(fd, tmpf, sizeof(tmpf));
> -             if (ret < 0) {
> -                     SYSERROR("failed to read to '%s'", freezer);
> -                     goto out;
> -             }
> +static inline bool cgfs_init(struct lxc_handler *handler)
> +{
> +     struct cgfs_data *d = malloc(sizeof(*d));
> +     if (!d)
> +             return false;
> +     d->info = NULL;
> +     d->meta = lxc_cgroup_load_meta();
>  
> -             ret = strncmp(f, tmpf, strlen(f));
> -             if (!ret)
> -             {
> -                     if (name)
> -                             lxc_monitor_send_state(name, freeze ? FROZEN : 
> THAWED, lxcpath);
> -                     break;          /* Success */
> -             }
> +     if (!d->meta) {
> +             ERROR("cgroupfs failed to detect cgroup metadata");
> +             return false;
> +     }
> +     handler->cgroup_info->data = d;
> +     return true;
> +}
>  
> -             sleep(1);
> +static inline bool cgfs_create(struct lxc_handler *handler)
> +{
> +     struct cgfs_data *d = handler->cgroup_info->data;
> +     struct cgroup_process_info *i;
> +     struct cgroup_meta_data *md = d->meta;
> +     i = lxc_cgroupfs_create(handler->name, 
> handler->cgroup_info->cgroup_pattern, md, NULL);
> +     if (!i)
> +             return false;
> +     d->info = i;
> +     return true;
> +}
>  
> -             ret = lseek(fd, 0L, SEEK_SET);
> -             if (ret < 0) {
> -                     SYSERROR("failed to lseek on file '%s'", freezer);
> -                     goto out;
> -             }
> +static inline bool cgfs_enter(struct lxc_handler *handler)
> +{
> +     struct cgfs_data *d = handler->cgroup_info->data;
> +     struct cgroup_process_info *i = d->info;
> +     int ret;
> +     
> +     ret = lxc_cgroupfs_enter(i, handler->pid, false);
>  
> -             ret = write(fd, f, strlen(f) + 1);
> -             if (ret < 0) {
> -                     SYSERROR("failed to write '%s' to '%s'", f, freezer);
> -                     goto out;
> -             }
> +     return ret == 0;
> +}
> +
> +static inline bool cgfs_create_legacy(struct lxc_handler *handler)
> +{
> +     struct cgfs_data *d = handler->cgroup_info->data;
> +     struct cgroup_process_info *i = d->info;
> +     if (lxc_cgroup_create_legacy(i, handler->name, handler->pid) < 0) {
> +             ERROR("failed to create legacy ns cgroups for '%s'", 
> handler->name);
> +             return false;
>       }
> +     return true;
> +}
>  
> -out:
> -     close(fd);
> -     return ret;
> +static char *cgfs_get_cgroup(struct lxc_handler *handler, const char 
> *subsystem)
> +{
> +     return lxc_cgroup_get_hierarchy_path_handler(subsystem, handler);
>  }
>  
> -int freeze_unfreeze(const char *name, int freeze, const char *lxcpath)
> +static struct cgroup_ops cgfs_ops = {
> +     .destroy = cgfs_destroy,
> +     .init = cgfs_init,
> +     .create = cgfs_create,
> +     .enter = cgfs_enter,
> +     .create_legacy = cgfs_create_legacy,
> +     .get_cgroup = cgfs_get_cgroup,
> +     .get = lxc_cgroupfs_get,
> +     .set = lxc_cgroupfs_set,
> +     .name = "cgroupfs",
> +};
> +static void init_cg_ops(void)
>  {
> -     char *cgabspath;
> -     int ret;
> +     if (!use_cgmanager)
> +             return;
> +     if (cgmanager_initialized)
> +             return;
> +     if (!lxc_init_cgmanager()) {
> +             ERROR("Could not contact cgroup manager, falling back to 
> cgroupfs");
> +             active_cg_ops = &cgfs_ops;
> +     }
> +}
>  
> -     cgabspath = lxc_cgroup_get_hierarchy_abs_path("freezer", name, lxcpath);
> -     if (!cgabspath)
> -             return -1;
> +/*
> + * These are the backend-independent cgroup handlers for container
> + * start and stop
> + */
>  
> -     ret = do_unfreeze(cgabspath, freeze, name, lxcpath);
> -     free(cgabspath);
> -     return ret;
> +/* Free all cgroup info held by the handler */
> +void cgroup_destroy(struct lxc_handler *handler)
> +{
> +     if (!handler->cgroup_info)
> +             return;
> +     if (active_cg_ops)
> +             active_cg_ops->destroy(handler);
>  }
>  
> -lxc_state_t freezer_state(const char *name, const char *lxcpath)
> +/*
> + * Allocate a lxc_cgroup_info for the active cgroup
> + * backend, and assign it to the handler
> + */
> +bool cgroup_init(struct lxc_handler *handler)
>  {
> -     char *cgabspath = NULL;
> -     char freezer[MAXPATHLEN];
> -     char status[MAXPATHLEN];
> -     FILE *file;
> -     int ret;
> +     init_cg_ops();
> +     handler->cgroup_info = malloc(sizeof(struct lxc_cgroup_info));
> +     if (!handler->cgroup_info)
> +             return false;
> +     memset(handler->cgroup_info, 0, sizeof(struct lxc_cgroup_info));
> +     /* if we are running as root, use system cgroup pattern, otherwise
> +      * just create a cgroup under the current one. But also fall back to
> +      * that if for some reason reading the configuration fails and no
> +      * default value is available
> +      */
> +     if (geteuid() == 0)
> +             handler->cgroup_info->cgroup_pattern = 
> lxc_global_config_value("lxc.cgroup.pattern");
> +     if (!handler->cgroup_info->cgroup_pattern)
> +             handler->cgroup_info->cgroup_pattern = "%n";
>  
> -     cgabspath = lxc_cgroup_get_hierarchy_abs_path("freezer", name, lxcpath);
> -     if (!cgabspath)
> -             return -1;
> +     return active_cg_ops->init(handler);
> +}
>  
> -     ret = snprintf(freezer, MAXPATHLEN, "%s/freezer.state", cgabspath);
> -     if (ret < 0 || ret >= MAXPATHLEN)
> -             goto out;
> +/* Create the container cgroups for all requested controllers */
> +bool cgroup_create(struct lxc_handler *handler)
> +{
> +     return active_cg_ops->create(handler);
> +}
>  
> -     file = fopen(freezer, "r");
> -     if (!file) {
> -             ret = -1;
> -             goto out;
> -     }
> +/*
> + * Set up per-controller configuration excluding the devices
> + * cgroup
> + */
> +bool cgroup_setup_without_devices(struct lxc_handler *handler)
> +{
> +     return do_setup_cgroup(handler, &handler->conf->cgroup, false) == 0;
> +}
>  
> -     ret = fscanf(file, "%s", status);
> -     fclose(file);
> +/* Set up the devices cgroup configuration for the container */
> +bool cgroup_setup_devices(struct lxc_handler *handler)
> +{
> +     return do_setup_cgroup(handler, &handler->conf->cgroup, true) == 0;
> +}
>  
> -     if (ret == EOF) {
> -             SYSERROR("failed to read %s", freezer);
> -             ret = -1;
> -             goto out;
> -     }
> +/*
> + * Enter the container init into its new cgroups for all
> + * requested controllers */
> +bool cgroup_enter(struct lxc_handler *handler)
> +{
> +     return active_cg_ops->enter(handler);
> +}
>  
> -     ret = lxc_str2state(status);
> +bool cgroup_create_legacy(struct lxc_handler *handler)
> +{
> +     if (active_cg_ops->create_legacy)
> +             return active_cg_ops->create_legacy(handler);
> +     return true;
> +}
>  
> -out:
> -     free(cgabspath);
> -     return ret;
> +char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem)
> +{
> +     return active_cg_ops->get_cgroup(handler, subsystem);
>  }
>  
> +int lxc_cgroup_set(const char *filename, const char *value, const char 
> *name, const char *lxcpath)
> +{
> +     init_cg_ops();
> +     return active_cg_ops->set(filename, value, name, lxcpath);
> +}
> +
> +int lxc_cgroup_get(const char *filename, char *value, size_t len, const char 
> *name, const char *lxcpath)
> +{
> +     init_cg_ops();
> +     return active_cg_ops->get(filename, value, len, name, lxcpath);
> +}
> diff --git a/src/lxc/cgroup.h b/src/lxc/cgroup.h
> index 3aab12d..8316e79 100644
> --- a/src/lxc/cgroup.h
> +++ b/src/lxc/cgroup.h
> @@ -72,6 +72,9 @@ struct cgroup_mount_point {
>   * cgroup_process_info: describes the membership of a
>   *                      process to the different cgroup
>   *                      hierarchies
> + *
> + * Note this is the per-process info tracked by the cgfs_ops.
> + * This is not used with cgmanager.
>   */
>  struct cgroup_process_info {
>       struct cgroup_process_info *next;
> @@ -121,22 +124,19 @@ extern int lxc_cgroup_create_legacy(struct 
> cgroup_process_info *base_info, const
>  /* get the cgroup membership of a given container */
>  extern struct cgroup_process_info *lxc_cgroup_get_container_info(const char 
> *name, const char *lxcpath, struct cgroup_meta_data *meta_data);
>  
> -/* move a processs to the cgroups specified by the membership */
> -extern int lxc_cgroup_enter(struct cgroup_process_info *info, pid_t pid, 
> bool enter_sub);
> +/* move a processs to the cgroups specified by the membership TODO - 
> deprecated, switch users to cgroup_enter() */
> +extern int lxc_cgroupfs_enter(struct cgroup_process_info *info, pid_t pid, 
> bool enter_sub);
>  
>  /* free process membership information */
>  extern void lxc_cgroup_process_info_free(struct cgroup_process_info *info);
>  extern void lxc_cgroup_process_info_free_and_remove(struct 
> cgroup_process_info *info);
>  
>  struct lxc_handler;
> -extern char *lxc_cgroup_get_hierarchy_path_handler(const char *subsystem, 
> struct lxc_handler *handler);
>  extern char *lxc_cgroup_get_hierarchy_path(const char *subsystem, const char 
> *name, const char *lxcpath);
>  extern char *lxc_cgroup_get_hierarchy_abs_path_handler(const char 
> *subsystem, struct lxc_handler *handler);
>  extern char *lxc_cgroup_get_hierarchy_abs_path(const char *subsystem, const 
> char *name, const char *lxcpath);
>  extern int lxc_cgroup_set_handler(const char *filename, const char *value, 
> struct lxc_handler *handler);
>  extern int lxc_cgroup_get_handler(const char *filename, char *value, size_t 
> len, struct lxc_handler *handler);
> -extern int lxc_cgroup_set(const char *filename, const char *value, const 
> char *name, const char *lxcpath);
> -extern int lxc_cgroup_get(const char *filename, char *value, size_t len, 
> const char *name, const char *lxcpath);
>  
>  /*
>   * lxc_cgroup_path_get: Get the absolute pathname for a cgroup
> @@ -162,12 +162,57 @@ struct lxc_list;
>  extern int lxc_setup_cgroup_without_devices(struct lxc_handler *h, struct 
> lxc_list *cgroup_settings);
>  extern int lxc_setup_cgroup_devices(struct lxc_handler *h, struct lxc_list 
> *cgroup_settings);
>  
> -extern int lxc_setup_mount_cgroup(const char *root, struct 
> cgroup_process_info *base_info, int type);
> -
>  extern int lxc_cgroup_nrtasks_handler(struct lxc_handler *handler);
>  
> -extern int do_unfreeze(const char *nsgroup, int freeze, const char *name, 
> const char *lxcpath);
> +extern int do_unfreeze(int freeze, const char *name, const char *lxcpath);
>  extern int freeze_unfreeze(const char *name, int freeze, const char 
> *lxcpath);
>  extern const char *lxc_state2str(lxc_state_t state);
>  extern lxc_state_t freezer_state(const char *name, const char *lxcpath);
> +/* per-backend cgroup hooks */
> +struct cgroup_ops {
> +     void (*destroy)(struct lxc_handler *handler);
> +     bool (*init)(struct lxc_handler *handler);
> +     bool (*create)(struct lxc_handler *handler);
> +     bool (*enter)(struct lxc_handler *handler);
> +     bool (*create_legacy)(struct lxc_handler *handler);
> +     char *(*get_cgroup)(struct lxc_handler *handler, const char *subsystem);
> +     int (*set)(const char *filename, const char *value, const char *name, 
> const char *lxcpath);
> +     int (*get)(const char *filename, char *value, size_t len, const char 
> *name, const char *lxcpath);
> +     const char *name;
> +};
> +
> +/*
> + * cgroup-related data for backend use in start/stop of a
> + * container.  This is tacked to the lxc_handler.
> + */
> +struct lxc_cgroup_info {
> +     /* handlers to actually do the cgroup stuff */
> +     struct cgroup_ops *ops;
> +     /* extra data for the cgroup_ops, i.e. mountpoints for fs backend */
> +     void *data;
> +     const char *cgroup_pattern;
> +};
> +
> +extern int lxc_setup_mount_cgroup(const char *root, struct lxc_cgroup_info 
> *base_info, int type);
> +
> +struct cgfs_data {
> +     struct cgroup_meta_data *meta;
> +     struct cgroup_process_info *info;
> +};
> +
> +/*
> + * backend-independent cgroup handlers
> + */
> +extern void cgroup_destroy(struct lxc_handler *handler);
> +extern bool cgroup_init(struct lxc_handler *handler);
> +extern bool cgroup_create(struct lxc_handler *handler);
> +extern bool cgroup_setup_without_devices(struct lxc_handler *handler);
> +extern bool cgroup_setup_devices(struct lxc_handler *handler);
> +extern bool cgroup_enter(struct lxc_handler *handler);
> +extern void cgroup_cleanup(struct lxc_handler *handler);
> +extern bool cgroup_create_legacy(struct lxc_handler *handler);
> +extern char *cgroup_get_cgroup(struct lxc_handler *handler, const char 
> *subsystem);
> +extern int lxc_cgroup_set(const char *filename, const char *value, const 
> char *name, const char *lxcpath);
> +extern int lxc_cgroup_get(const char *filename, char *value, size_t len, 
> const char *name, const char *lxcpath);
> +
>  #endif
> diff --git a/src/lxc/commands.c b/src/lxc/commands.c
> index e993f2e..29aa905 100644
> --- a/src/lxc/commands.c
> +++ b/src/lxc/commands.c
> @@ -435,7 +435,7 @@ static int lxc_cmd_get_cgroup_callback(int fd, struct 
> lxc_cmd_req *req,
>       if (req->datalen < 1)
>               return -1;
>  
> -     path = lxc_cgroup_get_hierarchy_path_handler(req->data, handler);
> +     path = cgroup_get_cgroup(handler, req->data);
>       if (!path)
>               return -1;
>       rsp.datalen = strlen(path) + 1,
> @@ -591,17 +591,10 @@ static int lxc_cmd_stop_callback(int fd, struct 
> lxc_cmd_req *req,
>       memset(&rsp, 0, sizeof(rsp));
>       rsp.ret = kill(handler->pid, stopsignal);
>       if (!rsp.ret) {
> -             char *path = lxc_cgroup_get_hierarchy_path_handler("freezer", 
> handler);
> -             if (!path) {
> -                     ERROR("container %s:%s is not in a freezer cgroup",
> -                             handler->lxcpath, handler->name);
> -                     return 0;
> -             }
> -             ret = lxc_unfreeze_bypath(path);
> +             ret = lxc_unfreeze(handler->name, handler->lxcpath);
>               if (!ret)
>                       return 0;
> -
> -             ERROR("failed to unfreeze container");
> +             ERROR("Failed to unfreeze %s:%s", handler->lxcpath, 
> handler->name);
>               rsp.ret = ret;
>       }
>  
> diff --git a/src/lxc/conf.c b/src/lxc/conf.c
> index 7e0eddd..6552af6 100644
> --- a/src/lxc/conf.c
> +++ b/src/lxc/conf.c
> @@ -646,7 +646,7 @@ int pin_rootfs(const char *rootfs)
>       return fd;
>  }
>  
> -static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct 
> cgroup_process_info *cgroup_info)
> +static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct 
> lxc_cgroup_info *cgroup_info)
>  {
>       int r;
>       size_t i;
> @@ -3458,8 +3458,14 @@ static int check_autodev( const char *rootfs, void 
> *data )
>       return 0;
>  }
>  
> -int lxc_setup(const char *name, struct lxc_conf *lxc_conf, const char 
> *lxcpath, struct cgroup_process_info *cgroup_info, void *data)
> +int lxc_setup(struct lxc_handler *handler)
>  {
> +     const char *name = handler->name;
> +     struct lxc_conf *lxc_conf = handler->conf;
> +     const char *lxcpath = handler->lxcpath;
> +     void *data = handler->data;
> +     struct lxc_cgroup_info *cgroup_info = handler->cgroup_info;
> +
>       if (lxc_conf->inherit_ns_fd[LXC_NS_UTS] == -1) {
>               if (setup_utsname(lxc_conf->utsname)) {
>                       ERROR("failed to setup the utsname for '%s'", name);
> diff --git a/src/lxc/conf.h b/src/lxc/conf.h
> index 8efd0f3..a0ce3f7 100644
> --- a/src/lxc/conf.h
> +++ b/src/lxc/conf.h
> @@ -366,10 +366,7 @@ extern int lxc_clear_groups(struct lxc_conf *c);
>   */
>  
>  struct cgroup_process_info;
> -extern int lxc_setup(const char *name, struct lxc_conf *lxc_conf,
> -                     const char *lxcpath,
> -                     struct cgroup_process_info *cgroup_info,
> -                     void *data);
> +extern int lxc_setup(struct lxc_handler *handler);
>  
>  extern void lxc_rename_phys_nics_on_shutdown(struct lxc_conf *conf);
>  
> diff --git a/src/lxc/freezer.c b/src/lxc/freezer.c
> index 53e9f64..c33a727 100644
> --- a/src/lxc/freezer.c
> +++ b/src/lxc/freezer.c
> @@ -50,17 +50,3 @@ int lxc_unfreeze(const char *name, const char *lxcpath)
>  {
>       return freeze_unfreeze(name, 0, lxcpath);
>  }
> -
> -int lxc_unfreeze_bypath(const char *cgrelpath)
> -{
> -     char *cgabspath;
> -     int ret;
> -
> -     cgabspath = lxc_cgroup_find_abs_path("freezer", cgrelpath, true, NULL);
> -     if (!cgabspath)
> -             return -1;
> -
> -     ret = do_unfreeze(cgabspath, 0, NULL, NULL);
> -     free(cgabspath);
> -     return ret;
> -}
> diff --git a/src/lxc/lxc.h b/src/lxc/lxc.h
> index d048cf2..0682f86 100644
> --- a/src/lxc/lxc.h
> +++ b/src/lxc/lxc.h
> @@ -123,14 +123,6 @@ extern int lxc_freeze(const char *name, const char 
> *lxcpath);
>  extern int lxc_unfreeze(const char *name, const char *lxcpath);
>  
>  /*
> - * Unfreeze all previously frozen tasks.
> - * This is the function to use from inside the monitor
> - * @name : the name of the container
> - * Return 0 on sucess, < 0 otherwise
> - */
> -extern int lxc_unfreeze_bypath(const char *cgpath);
> -
> -/*
>   * Retrieve the container state
>   * @name : the name of the container
>   * Returns the state of the container on success, < 0 otherwise
> diff --git a/src/lxc/start.c b/src/lxc/start.c
> index 6c07e43..441d0f4 100644
> --- a/src/lxc/start.c
> +++ b/src/lxc/start.c
> @@ -457,10 +457,7 @@ static void lxc_fini(const char *name, struct 
> lxc_handler *handler)
>       close(handler->conf->maincmd_fd);
>       handler->conf->maincmd_fd = -1;
>       free(handler->name);
> -     if (handler->cgroup) {
> -             lxc_cgroup_process_info_free_and_remove(handler->cgroup);
> -             handler->cgroup = NULL;
> -     }
> +     cgroup_destroy(handler);
>       free(handler);
>  }
>  
> @@ -602,7 +599,7 @@ static int do_start(void *data)
>       #endif
>  
>       /* Setup the container, ip, names, utsname, ... */
> -     if (lxc_setup(handler->name, handler->conf, handler->lxcpath, 
> handler->cgroup, handler->data) ){
> +     if (lxc_setup(handler)) {
>               ERROR("failed to setup the container");
>               goto out_warn_father;
>       }
> @@ -690,8 +687,6 @@ static int lxc_spawn(struct lxc_handler *handler)
>  {
>       int failed_before_rename = 0;
>       const char *name = handler->name;
> -     struct cgroup_meta_data *cgroup_meta = NULL;
> -     const char *cgroup_pattern = NULL;
>       int saved_ns_fd[LXC_NS_MAX];
>       int preserve_mask = 0, i;
>  
> @@ -755,27 +750,13 @@ static int lxc_spawn(struct lxc_handler *handler)
>       }
>  
>  
> -     cgroup_meta = lxc_cgroup_load_meta();
> -     if (!cgroup_meta) {
> -             ERROR("failed to detect cgroup metadata");
> +     if (!cgroup_init(handler)) {
> +             ERROR("failed initializing cgroup support");
>               goto out_delete_net;
>       }
>  
> -     /* if we are running as root, use system cgroup pattern, otherwise
> -      * just create a cgroup under the current one. But also fall back to
> -      * that if for some reason reading the configuration fails and no
> -      * default value is available
> -      */
> -     if (getuid() == 0)
> -             cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern");
> -     if (!cgroup_pattern)
> -             cgroup_pattern = "%n";
> -
> -     /* Create cgroup before doing clone(), so the child will know from
> -      * handler which cgroup it is going to be put in later.
> -      */
> -     if ((handler->cgroup = lxc_cgroup_create(name, cgroup_pattern, 
> cgroup_meta, NULL)) == NULL) {
> -             ERROR("failed to create cgroups for '%s'", name);
> +     if (!cgroup_create(handler)) {
> +             ERROR("failed creating cgroups");
>               goto out_delete_net;
>       }
>  
> @@ -808,20 +789,16 @@ static int lxc_spawn(struct lxc_handler *handler)
>       if (lxc_sync_wait_child(handler, LXC_SYNC_CONFIGURE))
>               failed_before_rename = 1;
>  
> -     /* In case there is still legacy ns cgroup support in the kernel.
> -      * Should be removed at some later point in time.
> -      */
> -     if (lxc_cgroup_create_legacy(handler->cgroup, name, handler->pid) < 0) {
> -             ERROR("failed to create legacy ns cgroups for '%s'", name);
> +     if (!cgroup_create_legacy(handler)) {
> +             ERROR("failed to setup the legacy cgroups for %s", name);
>               goto out_delete_net;
>       }
> -
> -     if (lxc_setup_cgroup_without_devices(handler, &handler->conf->cgroup)) {
> +     if (!cgroup_setup_without_devices(handler)) {
>               ERROR("failed to setup the cgroups for '%s'", name);
>               goto out_delete_net;
>       }
>  
> -     if (lxc_cgroup_enter(handler->cgroup, handler->pid, false) < 0)
> +     if (!cgroup_enter(handler))
>               goto out_delete_net;
>  
>       if (failed_before_rename)
> @@ -851,7 +828,7 @@ static int lxc_spawn(struct lxc_handler *handler)
>       if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_CONFIGURE))
>               goto out_delete_net;
>  
> -     if (lxc_setup_cgroup_devices(handler, &handler->conf->cgroup)) {
> +     if (!cgroup_setup_devices(handler)) {
>               ERROR("failed to setup the devices cgroup for '%s'", name);
>               goto out_delete_net;
>       }
> @@ -878,7 +855,6 @@ static int lxc_spawn(struct lxc_handler *handler)
>               goto out_abort;
>       }
>  
> -     lxc_cgroup_put_meta(cgroup_meta);
>       lxc_sync_fini(handler);
>  
>       return 0;
> @@ -887,7 +863,6 @@ out_delete_net:
>       if (handler->clone_flags & CLONE_NEWNET)
>               lxc_delete_network(handler);
>  out_abort:
> -     lxc_cgroup_put_meta(cgroup_meta);
>       lxc_abort(name, handler);
>       lxc_sync_fini(handler);
>       if (handler->pinfd >= 0) {
> diff --git a/src/lxc/start.h b/src/lxc/start.h
> index 7d4ae59..c30c661 100644
> --- a/src/lxc/start.h
> +++ b/src/lxc/start.h
> @@ -70,7 +70,7 @@ struct lxc_handler {
>       int sv[2];
>       int pinfd;
>       const char *lxcpath;
> -     struct cgroup_process_info *cgroup;
> +     struct lxc_cgroup_info *cgroup_info;
>  };
>  
>  extern struct lxc_handler *lxc_init(const char *name, struct lxc_conf *, 
> const char *);
> -- 
> 1.8.5.2
> 
> _______________________________________________
> lxc-devel mailing list
> [email protected]
> http://lists.linuxcontainers.org/listinfo/lxc-devel

-- 
Stéphane Graber
Ubuntu developer
http://www.ubuntu.com

Attachment: signature.asc
Description: Digital signature

_______________________________________________
lxc-devel mailing list
[email protected]
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to