[lxc-devel] [PATCH 1/1] Initial support for cgmanager
Stéphane Graber
stgraber at ubuntu.com
Wed Jan 15 15:43:40 UTC 2014
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 <serge.hallyn at ubuntu.com>
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
> lxc-devel at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/lxc-devel
--
Stéphane Graber
Ubuntu developer
http://www.ubuntu.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20140115/0455d09c/attachment.pgp>
More information about the lxc-devel
mailing list