[lxc-devel] [PATCH 2/2] split cgroup handling into discrete backends
Serge Hallyn
serge.hallyn at ubuntu.com
Thu Feb 6 04:51:53 UTC 2014
Quoting Dwight Engen (dwight.engen at oracle.com):
> - refactor cgroup into two backends, the classic cgfs driver and the new
> cgmanager. Instead of lxc_handler knowing about the internals of each,
> have it just store an opaque pointer to a struct that is private to
> each backend.
>
> - rename a couple of cgroup functions for consistency: those that are
> considered an API (ie. exported by lxc.h) begin with lxc_ and those that
> are not are just cgroup_*
>
> - made as many backend routines static as possible, only cg*_ops_init is
> exported
>
> - made a nrtasks op which is needed by the utmp code for monitoring
> container shutdown, currently only implemented for the cgfs backend
Hi Dwight,
boy this diff got into some unfortunate strides (with near-identical
code being removed then inserted pages later) making it harder
to read than necessary :)
> Signed-off-by: Dwight Engen <dwight.engen at oracle.com>
Acked-by: Serge E. Hallyn <serge.hallyn at ubuntu.com>
(I'll apply after I run some tests)
> ---
> src/lxc/Makefile.am | 3 +-
> src/lxc/attach.c | 2 +-
> src/lxc/cgfs.c | 524 +++++++++++++++++++++-------------------------------
> src/lxc/cgmanager.c | 272 ++++++++++++++++-----------
> src/lxc/cgroup.c | 169 +++++++++++++++++
> src/lxc/cgroup.h | 207 +++------------------
> src/lxc/commands.c | 11 +-
> src/lxc/conf.c | 12 +-
> src/lxc/freezer.c | 41 +++-
> src/lxc/lxc.h | 11 --
> src/lxc/lxcutmp.c | 2 +-
> src/lxc/start.h | 2 +-
> src/lxc/state.c | 2 +
> src/tests/cgpath.c | 28 +--
> 14 files changed, 631 insertions(+), 655 deletions(-)
> create mode 100644 src/lxc/cgroup.c
>
> diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
> index b4aa924..19511a4 100644
> --- a/src/lxc/Makefile.am
> +++ b/src/lxc/Makefile.am
> @@ -62,7 +62,8 @@ liblxc_so_SOURCES = \
> freezer.c \
> error.h error.c \
> parse.c parse.h \
> - cgfs.c cgroup.h \
> + cgfs.c \
> + cgroup.c cgroup.h \
> lxc.h \
> utils.c utils.h \
> sync.c sync.h \
> diff --git a/src/lxc/attach.c b/src/lxc/attach.c
> index 5c4adcd..8782652 100644
> --- a/src/lxc/attach.c
> +++ b/src/lxc/attach.c
> @@ -699,7 +699,7 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
>
> /* attach to cgroup, if requested */
> if (options->attach_flags & LXC_ATTACH_MOVE_TO_CGROUP) {
> - if (!lxc_cgroup_attach(name, lxcpath, pid))
> + if (!cgroup_attach(name, lxcpath, pid))
> goto cleanup_error;
> }
>
> diff --git a/src/lxc/cgfs.c b/src/lxc/cgfs.c
> index c23b784..f576ba1 100644
> --- a/src/lxc/cgfs.c
> +++ b/src/lxc/cgfs.c
> @@ -55,7 +55,75 @@
> #include <mntent.h>
> #endif
>
> -lxc_log_define(lxc_cgroup, lxc);
> +struct cgroup_hierarchy;
> +struct cgroup_meta_data;
> +struct cgroup_mount_point;
> +
> +/*
> + * cgroup_meta_data: the metadata about the cgroup infrastructure on this
> + * host
> + */
> +struct cgroup_meta_data {
> + ptrdiff_t ref; /* simple refcount */
> + struct cgroup_hierarchy **hierarchies;
> + struct cgroup_mount_point **mount_points;
> + int maximum_hierarchy;
> +};
> +
> +/*
> + * cgroup_hierarchy: describes a single cgroup hierarchy
> + * (may have multiple mount points)
> + */
> +struct cgroup_hierarchy {
> + int index;
> + bool used; /* false if the hierarchy should be ignored by lxc */
> + char **subsystems;
> + struct cgroup_mount_point *rw_absolute_mount_point;
> + struct cgroup_mount_point *ro_absolute_mount_point;
> + struct cgroup_mount_point **all_mount_points;
> + size_t all_mount_point_capacity;
> +};
> +
> +/*
> + * cgroup_mount_point: a mount point to where a hierarchy
> + * is mounted to
> + */
> +struct cgroup_mount_point {
> + struct cgroup_hierarchy *hierarchy;
> + char *mount_point;
> + char *mount_prefix;
> + bool read_only;
> + bool need_cpuset_init;
> +};
> +
> +/*
> + * 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;
> + struct cgroup_meta_data *meta_ref;
> + struct cgroup_hierarchy *hierarchy;
> + char *cgroup_path;
> + char *cgroup_path_sub;
> + char **created_paths;
> + size_t created_paths_capacity;
> + size_t created_paths_count;
> + struct cgroup_mount_point *designated_mount_point;
> +};
> +
> +struct cgfs_data {
> + char *name;
> + const char *cgroup_pattern;
> + struct cgroup_meta_data *meta;
> + struct cgroup_process_info *info;
> +};
> +
> +lxc_log_define(lxc_cgfs, lxc);
>
> static struct cgroup_process_info *lxc_cgroup_process_info_getx(const char *proc_pid_cgroup_str, struct cgroup_meta_data *meta);
> static char **subsystems_from_mount_options(const char *mount_options, char **kernel_list);
> @@ -68,27 +136,22 @@ static char *cgroup_to_absolute_path(struct cgroup_mount_point *mp, const char *
> static struct cgroup_process_info *find_info_for_subsystem(struct cgroup_process_info *info, const char *subsystem);
> static int do_cgroup_get(const char *cgroup_path, const char *sub_filename, char *value, size_t len);
> static int do_cgroup_set(const char *cgroup_path, const char *sub_filename, const char *value);
> -static bool cgroup_devices_has_allow_or_deny(struct lxc_handler *h, char *v, bool for_allow);
> -static int do_setup_cgroup_limits(struct lxc_handler *h, struct lxc_list *cgroup_settings, bool do_devices);
> +static bool cgroup_devices_has_allow_or_deny(struct cgfs_data *d, char *v, bool for_allow);
> +static int do_setup_cgroup_limits(struct cgfs_data *d, struct lxc_list *cgroup_settings, bool do_devices);
> 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 bool init_cpuset_if_needed(struct cgroup_mount_point *mp, const char *path);
>
> +static struct cgroup_meta_data *lxc_cgroup_load_meta2(const char **subsystem_whitelist);
> +static struct cgroup_meta_data *lxc_cgroup_get_meta(struct cgroup_meta_data *meta_data);
> +static struct cgroup_meta_data *lxc_cgroup_put_meta(struct cgroup_meta_data *meta_data);
> +
> +/* free process membership information */
> +static void lxc_cgroup_process_info_free(struct cgroup_process_info *info);
> +static void lxc_cgroup_process_info_free_and_remove(struct cgroup_process_info *info);
> +
> 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)
> {
> @@ -159,7 +222,7 @@ static int cgroup_rmdir(char *dirname)
> return failed ? -1 : 0;
> }
>
> -struct cgroup_meta_data *lxc_cgroup_load_meta()
> +static struct cgroup_meta_data *lxc_cgroup_load_meta()
> {
> const char *cgroup_use = NULL;
> char **cgroup_use_list = NULL;
> @@ -184,7 +247,7 @@ struct cgroup_meta_data *lxc_cgroup_load_meta()
> }
>
> /* Step 1: determine all kernel subsystems */
> -bool find_cgroup_subsystems(char ***kernel_subsystems)
> +static bool find_cgroup_subsystems(char ***kernel_subsystems)
> {
> FILE *proc_cgroups;
> bool bret = false;
> @@ -470,7 +533,7 @@ out:
> return bret;
> }
>
> -struct cgroup_meta_data *lxc_cgroup_load_meta2(const char **subsystem_whitelist)
> +static struct cgroup_meta_data *lxc_cgroup_load_meta2(const char **subsystem_whitelist)
> {
> bool all_kernel_subsystems = true;
> bool all_named_subsystems = false;
> @@ -526,13 +589,13 @@ out_error:
> return NULL;
> }
>
> -struct cgroup_meta_data *lxc_cgroup_get_meta(struct cgroup_meta_data *meta_data)
> +static struct cgroup_meta_data *lxc_cgroup_get_meta(struct cgroup_meta_data *meta_data)
> {
> meta_data->ref++;
> return meta_data;
> }
>
> -struct cgroup_meta_data *lxc_cgroup_put_meta(struct cgroup_meta_data *meta_data)
> +static struct cgroup_meta_data *lxc_cgroup_put_meta(struct cgroup_meta_data *meta_data)
> {
> size_t i;
> if (!meta_data)
> @@ -549,7 +612,7 @@ struct cgroup_meta_data *lxc_cgroup_put_meta(struct cgroup_meta_data *meta_data)
> return NULL;
> }
>
> -struct cgroup_hierarchy *lxc_cgroup_find_hierarchy(struct cgroup_meta_data *meta_data, const char *subsystem)
> +static struct cgroup_hierarchy *lxc_cgroup_find_hierarchy(struct cgroup_meta_data *meta_data, const char *subsystem)
> {
> size_t i;
> for (i = 0; i <= meta_data->maximum_hierarchy; i++) {
> @@ -560,7 +623,7 @@ struct cgroup_hierarchy *lxc_cgroup_find_hierarchy(struct cgroup_meta_data *meta
> return NULL;
> }
>
> -struct cgroup_mount_point *lxc_cgroup_find_mount_point(struct cgroup_hierarchy *hierarchy, const char *group, bool should_be_writable)
> +static struct cgroup_mount_point *lxc_cgroup_find_mount_point(struct cgroup_hierarchy *hierarchy, const char *group, bool should_be_writable)
> {
> struct cgroup_mount_point **mps;
> struct cgroup_mount_point *current_result = NULL;
> @@ -600,7 +663,7 @@ struct cgroup_mount_point *lxc_cgroup_find_mount_point(struct cgroup_hierarchy *
> return current_result;
> }
>
> -char *lxc_cgroup_find_abs_path(const char *subsystem, const char *group, bool should_be_writable, const char *suffix)
> +static char *lxc_cgroup_find_abs_path(const char *subsystem, const char *group, bool should_be_writable, const char *suffix)
> {
> struct cgroup_meta_data *meta_data;
> struct cgroup_hierarchy *h;
> @@ -634,19 +697,19 @@ out_error:
> return NULL;
> }
>
> -struct cgroup_process_info *lxc_cgroup_process_info_get(pid_t pid, struct cgroup_meta_data *meta)
> +static struct cgroup_process_info *lxc_cgroup_process_info_get(pid_t pid, struct cgroup_meta_data *meta)
> {
> char pid_buf[32];
> snprintf(pid_buf, 32, "/proc/%lu/cgroup", (unsigned long)pid);
> return lxc_cgroup_process_info_getx(pid_buf, meta);
> }
>
> -struct cgroup_process_info *lxc_cgroup_process_info_get_init(struct cgroup_meta_data *meta)
> +static struct cgroup_process_info *lxc_cgroup_process_info_get_init(struct cgroup_meta_data *meta)
> {
> return lxc_cgroup_process_info_get(1, meta);
> }
>
> -struct cgroup_process_info *lxc_cgroup_process_info_get_self(struct cgroup_meta_data *meta)
> +static struct cgroup_process_info *lxc_cgroup_process_info_get_self(struct cgroup_meta_data *meta)
> {
> struct cgroup_process_info *i;
> i = lxc_cgroup_process_info_getx("/proc/self/cgroup", meta);
> @@ -724,7 +787,7 @@ static char *cgroup_rename_nsgroup(const char *mountpath, const char *oldname, p
> }
>
> /* create a new cgroup */
> -struct cgroup_process_info *lxc_cgroupfs_create(const char *name, const char *path_pattern, struct cgroup_meta_data *meta_data, const char *sub_pattern)
> +static 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;
> @@ -817,7 +880,7 @@ struct cgroup_process_info *lxc_cgroupfs_create(const char *name, const char *pa
> }
>
> goto find_name_on_this_level;
> -
> +
> cleanup_name_on_this_level:
> /* This is reached if we found a name clash.
> * In that case, remove the cgroup from all previous hierarchies
> @@ -836,7 +899,7 @@ struct cgroup_process_info *lxc_cgroupfs_create(const char *name, const char *pa
> current_component = current_subpath = NULL;
> /* try again with another suffix */
> ++suffix;
> -
> +
> find_name_on_this_level:
> /* determine name of the path component we should create */
> if (contains_name && suffix > 0) {
> @@ -937,7 +1000,7 @@ struct cgroup_process_info *lxc_cgroupfs_create(const char *name, const char *pa
> free(current_component);
> current_component = current_subpath = NULL;
> continue;
> -
> +
> cleanup_from_error:
> /* called if an error occured in the loop, so we
> * do some additional cleanup here
> @@ -985,7 +1048,7 @@ out_initial_error:
> return NULL;
> }
>
> -int lxc_cgroup_create_legacy(struct cgroup_process_info *base_info, const char *name, pid_t pid)
> +static int lxc_cgroup_create_legacy(struct cgroup_process_info *base_info, const char *name, pid_t pid)
> {
> struct cgroup_process_info *info_ptr;
> int r;
> @@ -1016,7 +1079,7 @@ int lxc_cgroup_create_legacy(struct cgroup_process_info *base_info, const char *
> }
>
> /* get the cgroup membership of a given container */
> -struct cgroup_process_info *lxc_cgroup_get_container_info(const char *name, const char *lxcpath, struct cgroup_meta_data *meta_data)
> +static struct cgroup_process_info *lxc_cgroup_get_container_info(const char *name, const char *lxcpath, struct cgroup_meta_data *meta_data)
> {
> struct cgroup_process_info *result = NULL;
> int saved_errno = 0;
> @@ -1064,7 +1127,7 @@ out_error:
> }
>
> /* move a processs to the cgroups specified by the membership */
> -int lxc_cgroupfs_enter(struct cgroup_process_info *info, pid_t pid, bool enter_sub)
> +static int lxc_cgroupfs_enter(struct cgroup_process_info *info, pid_t pid, bool enter_sub)
> {
> char pid_buf[32];
> char *cgroup_tasks_fn;
> @@ -1148,9 +1211,8 @@ void lxc_cgroup_process_info_free_and_remove(struct cgroup_process_info *info)
> lxc_cgroup_process_info_free_and_remove(next);
> }
>
> -static char *lxc_cgroup_get_hierarchy_path_handler(const char *subsystem, struct lxc_handler *handler)
> +static char *lxc_cgroup_get_hierarchy_path_data(const char *subsystem, struct cgfs_data *d)
> {
> - struct cgfs_data *d = handler->cgroup_info->data;
> struct cgroup_process_info *info = d->info;
> info = find_info_for_subsystem(info, subsystem);
> if (!info)
> @@ -1158,14 +1220,8 @@ static char *lxc_cgroup_get_hierarchy_path_handler(const char *subsystem, struct
> return info->cgroup_path;
> }
>
> -char *lxc_cgroup_get_hierarchy_path(const char *subsystem, const char *name, const char *lxcpath)
> -{
> - return lxc_cmd_get_cgroup_path(name, lxcpath, subsystem);
> -}
> -
> -char *lxc_cgroup_get_hierarchy_abs_path_handler(const char *subsystem, struct lxc_handler *handler)
> +static char *lxc_cgroup_get_hierarchy_abs_path_data(const char *subsystem, struct cgfs_data *d)
> {
> - struct cgfs_data *d = handler->cgroup_info->data;
> struct cgroup_process_info *info = d->info;
> struct cgroup_mount_point *mp = NULL;
>
> @@ -1182,7 +1238,7 @@ char *lxc_cgroup_get_hierarchy_abs_path_handler(const char *subsystem, struct lx
> return cgroup_to_absolute_path(mp, info->cgroup_path, NULL);
> }
>
> -char *lxc_cgroup_get_hierarchy_abs_path(const char *subsystem, const char *name, const char *lxcpath)
> +static char *lxc_cgroup_get_hierarchy_abs_path(const char *subsystem, const char *name, const char *lxcpath)
> {
> struct cgroup_meta_data *meta;
> struct cgroup_process_info *base_info, *info;
> @@ -1214,7 +1270,7 @@ out1:
> return result;
> }
>
> -int lxc_cgroup_set_handler(const char *filename, const char *value, struct lxc_handler *handler)
> +static int lxc_cgroup_set_data(const char *filename, const char *value, struct cgfs_data *d)
> {
> char *subsystem = NULL, *p, *path;
> int ret = -1;
> @@ -1224,7 +1280,7 @@ int lxc_cgroup_set_handler(const char *filename, const char *value, struct lxc_h
> if ((p = index(subsystem, '.')) != NULL)
> *p = '\0';
>
> - path = lxc_cgroup_get_hierarchy_abs_path_handler(subsystem, handler);
> + path = lxc_cgroup_get_hierarchy_abs_path_data(subsystem, d);
> if (path) {
> ret = do_cgroup_set(path, filename, value);
> free(path);
> @@ -1232,25 +1288,7 @@ int lxc_cgroup_set_handler(const char *filename, const char *value, struct lxc_h
> return ret;
> }
>
> -int lxc_cgroup_get_handler(const char *filename, char *value, size_t len, struct lxc_handler *handler)
> -{
> - char *subsystem = NULL, *p, *path;
> - int ret = -1;
> -
> - subsystem = alloca(strlen(filename) + 1);
> - strcpy(subsystem, filename);
> - if ((p = index(subsystem, '.')) != NULL)
> - *p = '\0';
> -
> - path = lxc_cgroup_get_hierarchy_abs_path_handler(subsystem, handler);
> - if (path) {
> - ret = do_cgroup_get(path, filename, value, len);
> - free(path);
> - }
> - return ret;
> -}
> -
> -int lxc_cgroupfs_set(const char *filename, const char *value, const char *name, const char *lxcpath)
> +static int lxc_cgroupfs_set(const char *filename, const char *value, const char *name, const char *lxcpath)
> {
> char *subsystem = NULL, *p, *path;
> int ret = -1;
> @@ -1268,7 +1306,7 @@ int lxc_cgroupfs_set(const char *filename, const char *value, const char *name,
> return ret;
> }
>
> -int lxc_cgroupfs_get(const char *filename, char *value, size_t len, const char *name, const char *lxcpath)
> +static 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;
> @@ -1286,48 +1324,7 @@ int lxc_cgroupfs_get(const char *filename, char *value, size_t len, const char *
> return ret;
> }
>
> -/*
> - * lxc_cgroup_path_get: Get the absolute pathname for a cgroup
> - * file for a running container.
> - *
> - * @filename : the file of interest (e.g. "freezer.state") or
> - * the subsystem name (e.g. "freezer") in which case
> - * the directory where the cgroup may be modified
> - * will be returned
> - * @name : name of container to connect to
> - * @lxcpath : the lxcpath in which the container is running
> - *
> - * This is the exported function, which determines cgpath from the
> - * lxc-start of the @name container running in @lxcpath.
> - *
> - * Returns path on success, NULL on error. The caller must free()
> - * the returned path.
> - */
> -char *lxc_cgroup_path_get(const char *filename, const char *name,
> - const char *lxcpath)
> -{
> - char *subsystem = NULL, *longer_file = NULL, *p, *group, *path;
> -
> - subsystem = alloca(strlen(filename) + 1);
> - strcpy(subsystem, filename);
> - if ((p = index(subsystem, '.')) != NULL) {
> - *p = '\0';
> - longer_file = alloca(strlen(filename) + 2);
> - longer_file[0] = '/';
> - strcpy(longer_file + 1, filename);
> - }
> -
> - group = lxc_cgroup_get_hierarchy_path(subsystem, name, lxcpath);
> - if (!group)
> - return NULL;
> -
> - path = lxc_cgroup_find_abs_path(subsystem, group, true, p ? longer_file : NULL);
> - free(group);
> - return path;
> -}
> -
> -static bool cgroupfs_mount_cgroup(const char *root,
> - struct lxc_cgroup_info *cgroup_info, int type)
> +static bool cgroupfs_mount_cgroup(void *hdata, const char *root, int type)
> {
> size_t bufsz = strlen(root) + sizeof("/sys/fs/cgroup");
> char *path = NULL;
> @@ -1339,9 +1336,9 @@ static bool cgroupfs_mount_cgroup(const char *root,
> struct cgroup_process_info *info, *base_info;
> int r, saved_errno = 0;
>
> - init_cg_ops();
> -
> - cgfs_d = cgroup_info->data;
> + cgfs_d = hdata;
> + if (!cgfs_d)
> + return false;
> base_info = cgfs_d->info;
>
> if (type < LXC_AUTO_CGROUP_RO || type > LXC_AUTO_CGROUP_FULL_MIXED) {
> @@ -1510,14 +1507,20 @@ out_error:
> return false;
> }
>
> -int lxc_cgroup_nrtasks_handler(struct lxc_handler *handler)
> +static int cgfs_nrtasks(void *hdata)
> {
> - struct cgfs_data *d = handler->cgroup_info->data;
> - struct cgroup_process_info *info = d->info;
> + struct cgfs_data *d = hdata;
> + struct cgroup_process_info *info;
> struct cgroup_mount_point *mp = NULL;
> char *abs_path = NULL;
> int ret;
>
> + if (!d) {
> + errno = ENOENT;
> + return -1;
> + }
> +
> + info = d->info;
> if (!info) {
> errno = ENOENT;
> return -1;
> @@ -1842,7 +1845,7 @@ static int do_cgroup_set(const char *cgroup_path, const char *sub_filename,
> return ret;
> }
>
> -static int do_setup_cgroup_limits(struct lxc_handler *h,
> +static int do_setup_cgroup_limits(struct cgfs_data *d,
> struct lxc_list *cgroup_settings, bool do_devices)
> {
> struct lxc_list *iterator;
> @@ -1857,14 +1860,14 @@ static int do_setup_cgroup_limits(struct lxc_handler *h,
>
> if (do_devices == !strncmp("devices", cg->subsystem, 7)) {
> if (strcmp(cg->subsystem, "devices.deny") == 0 &&
> - cgroup_devices_has_allow_or_deny(h, cg->value, false))
> + cgroup_devices_has_allow_or_deny(d, cg->value, false))
> continue;
> if (strcmp(cg->subsystem, "devices.allow") == 0 &&
> - cgroup_devices_has_allow_or_deny(h, cg->value, true))
> + cgroup_devices_has_allow_or_deny(d, cg->value, true))
> continue;
> - if (lxc_cgroup_set_handler(cg->subsystem, cg->value, h)) {
> + if (lxc_cgroup_set_data(cg->subsystem, cg->value, d)) {
> ERROR("Error setting %s to %s for %s\n",
> - cg->subsystem, cg->value, h->name);
> + cg->subsystem, cg->value, d->name);
> goto out;
> }
> }
> @@ -1878,7 +1881,7 @@ out:
> return ret;
> }
>
> -static bool cgroup_devices_has_allow_or_deny(struct lxc_handler *h,
> +static bool cgroup_devices_has_allow_or_deny(struct cgfs_data *d,
> char *v, bool for_allow)
> {
> char *path;
> @@ -1898,7 +1901,7 @@ static bool cgroup_devices_has_allow_or_deny(struct lxc_handler *h,
> if (!for_allow && strcmp(v, "a") != 0 && strcmp(v, "a *:* rwm") != 0)
> return false;
>
> - parts[0] = (const char *)lxc_cgroup_get_hierarchy_abs_path_handler("devices", h);
> + parts[0] = (const char *)lxc_cgroup_get_hierarchy_abs_path_data("devices", d);
> if (!parts[0])
> return false;
> path = lxc_string_join("/", parts, false);
> @@ -2167,124 +2170,127 @@ static bool init_cpuset_if_needed(struct cgroup_mount_point *mp,
> do_init_cpuset_file(mp, path, "/cpuset.mems") );
> }
>
> -extern void lxc_monitor_send_state(const char *name, lxc_state_t state,
> - const char *lxcpath);
> -int do_unfreeze(int freeze, const char *name, const char *lxcpath)
> +struct cgroup_ops *cgfs_ops_init(void)
> {
> - char v[100];
> - const char *state = freeze ? "FROZEN" : "THAWED";
> -
> - if (lxc_cgroup_set("freezer.state", state, name, lxcpath) < 0) {
> - ERROR("Failed to freeze %s:%s", lxcpath, name);
> - 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);
> - }
> + return &cgfs_ops;
> }
>
> -int freeze_unfreeze(const char *name, int freeze, const char *lxcpath)
> +static void *cgfs_init(const char *name)
> {
> - return do_unfreeze(freeze, name, lxcpath);
> -}
> + struct cgfs_data *d;
>
> -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)
> - return -1;
> + d = malloc(sizeof(*d));
> + if (!d)
> + return NULL;
>
> - if (v[strlen(v)-1] == '\n')
> - v[strlen(v)-1] = '\0';
> - return lxc_str2state(v);
> + memset(d, 0, sizeof(*d));
> + d->name = strdup(name);
> + if (!d->name)
> + goto err1;
> +
> + /* 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)
> + d->cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern");
> + if (!d->cgroup_pattern)
> + d->cgroup_pattern = "%n";
> +
> + d->meta = lxc_cgroup_load_meta();
> + if (!d->meta) {
> + ERROR("cgroupfs failed to detect cgroup metadata");
> + goto err2;
> + }
> + return d;
> +
> +err2:
> + free(d->name);
> +err1:
> + free(d);
> + return NULL;
> }
>
> -static void cgfs_destroy(struct lxc_handler *handler)
> +static void cgfs_destroy(void *hdata)
> {
> - struct cgfs_data *d = handler->cgroup_info->data;
> + struct cgfs_data *d = hdata;
> +
> if (!d)
> return;
> + if (d->name)
> + free(d->name);
> 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;
> }
>
> -static inline bool cgfs_init(struct lxc_handler *handler)
> +static inline bool cgfs_create(void *hdata)
> {
> - struct cgfs_data *d = malloc(sizeof(*d));
> - if (!d)
> - return false;
> - d->info = NULL;
> - d->meta = lxc_cgroup_load_meta();
> + struct cgfs_data *d = hdata;
> + struct cgroup_process_info *i;
> + struct cgroup_meta_data *md;
>
> - if (!d->meta) {
> - ERROR("cgroupfs failed to detect cgroup metadata");
> - free(d);
> + if (!d)
> return false;
> - }
> - handler->cgroup_info->data = d;
> - return true;
> -}
> -
> -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);
> + md = d->meta;
> + i = lxc_cgroupfs_create(d->name, d->cgroup_pattern, md, NULL);
> if (!i)
> return false;
> d->info = i;
> return true;
> }
>
> -static inline bool cgfs_enter(struct lxc_handler *handler)
> +static inline bool cgfs_enter(void *hdata, pid_t pid)
> {
> - struct cgfs_data *d = handler->cgroup_info->data;
> - struct cgroup_process_info *i = d->info;
> + struct cgfs_data *d = hdata;
> + struct cgroup_process_info *i;
> int ret;
> -
> - ret = lxc_cgroupfs_enter(i, handler->pid, false);
> +
> + if (!d)
> + return false;
> + i = d->info;
> + ret = lxc_cgroupfs_enter(i, pid, false);
>
> return ret == 0;
> }
>
> -static inline bool cgfs_create_legacy(struct lxc_handler *handler)
> +static inline bool cgfs_create_legacy(void *hdata, pid_t pid)
> {
> - 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);
> + struct cgfs_data *d = hdata;
> + struct cgroup_process_info *i;
> +
> + if (!d)
> + return false;
> + i = d->info;
> + if (lxc_cgroup_create_legacy(i, d->name, pid) < 0) {
> + ERROR("failed to create legacy ns cgroups for '%s'", d->name);
> return false;
> }
> return true;
> }
>
> -static char *cgfs_get_cgroup(struct lxc_handler *handler, const char *subsystem)
> +static const char *cgfs_get_cgroup(void *hdata, const char *subsystem)
> {
> - return lxc_cgroup_get_hierarchy_path_handler(subsystem, handler);
> + struct cgfs_data *d = hdata;
> +
> + if (!d)
> + return NULL;
> + return lxc_cgroup_get_hierarchy_path_data(subsystem, d);
> }
>
> -static bool cgfs_unfreeze_fromhandler(struct lxc_handler *handler)
> +static bool cgfs_unfreeze(void *hdata)
> {
> + struct cgfs_data *d = hdata;
> char *cgabspath, *cgrelpath;
> int ret;
>
> - cgrelpath = lxc_cgroup_get_hierarchy_path_handler("freezer", handler);
> + if (!d)
> + return false;
> +
> + cgrelpath = lxc_cgroup_get_hierarchy_path_data("freezer", d);
> cgabspath = lxc_cgroup_find_abs_path("freezer", cgrelpath, true, NULL);
> if (!cgabspath)
> return false;
> @@ -2294,12 +2300,17 @@ static bool cgfs_unfreeze_fromhandler(struct lxc_handler *handler)
> return ret == 0;
> }
>
> -bool cgroupfs_setup_limits(struct lxc_handler *h, bool with_devices)
> +static bool cgroupfs_setup_limits(void *hdata, struct lxc_list *cgroup_conf,
> + bool with_devices)
> {
> - return do_setup_cgroup_limits(h, &h->conf->cgroup, with_devices) == 0;
> + struct cgfs_data *d = hdata;
> +
> + if (!d)
> + return false;
> + return do_setup_cgroup_limits(d, cgroup_conf, with_devices) == 0;
> }
>
> -bool lxc_cgroupfs_attach(const char *name, const char *lxcpath, pid_t pid)
> +static bool lxc_cgroupfs_attach(const char *name, const char *lxcpath, pid_t pid)
> {
> struct cgroup_meta_data *meta_data;
> struct cgroup_process_info *container_info;
> @@ -2328,134 +2339,19 @@ bool lxc_cgroupfs_attach(const char *name, const char *lxcpath, pid_t pid)
> }
>
> static struct cgroup_ops cgfs_ops = {
> - .destroy = cgfs_destroy,
> .init = cgfs_init,
> + .destroy = cgfs_destroy,
> .create = cgfs_create,
> .enter = cgfs_enter,
> .create_legacy = cgfs_create_legacy,
> .get_cgroup = cgfs_get_cgroup,
> .get = lxc_cgroupfs_get,
> .set = lxc_cgroupfs_set,
> - .unfreeze_fromhandler = cgfs_unfreeze_fromhandler,
> + .unfreeze = cgfs_unfreeze,
> .setup_limits = cgroupfs_setup_limits,
> .name = "cgroupfs",
> .attach = lxc_cgroupfs_attach,
> .chown = NULL,
> .mount_cgroup = cgroupfs_mount_cgroup,
> + .nrtasks = cgfs_nrtasks,
> };
> -static void init_cg_ops(void)
> -{
> - 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;
> - }
> -}
> -
> -/*
> - * These are the backend-independent cgroup handlers for container
> - * start and stop
> - */
> -
> -/* 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);
> -}
> -
> -/*
> - * Allocate a lxc_cgroup_info for the active cgroup
> - * backend, and assign it to the handler
> - */
> -bool cgroup_init(struct lxc_handler *handler)
> -{
> - 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";
> -
> - return active_cg_ops->init(handler);
> -}
> -
> -/* Create the container cgroups for all requested controllers */
> -bool cgroup_create(struct lxc_handler *handler)
> -{
> - return active_cg_ops->create(handler);
> -}
> -
> -/*
> - * 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);
> -}
> -
> -bool cgroup_create_legacy(struct lxc_handler *handler)
> -{
> - if (active_cg_ops->create_legacy)
> - return active_cg_ops->create_legacy(handler);
> - return true;
> -}
> -
> -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);
> -}
> -
> -bool lxc_unfreeze_fromhandler(struct lxc_handler *handler)
> -{
> - return active_cg_ops->unfreeze_fromhandler(handler);
> -}
> -
> -bool cgroup_setup_limits(struct lxc_handler *handler, bool with_devices)
> -{
> - return active_cg_ops->setup_limits(handler, with_devices);
> -}
> -
> -bool cgroup_chown(struct lxc_handler *handler)
> -{
> - if (active_cg_ops->chown)
> - return active_cg_ops->chown(handler);
> - return true;
> -}
> -
> -bool lxc_cgroup_attach(const char *name, const char *lxcpath, pid_t pid)
> -{
> - init_cg_ops();
> - return active_cg_ops->attach(name, lxcpath, pid);
> -}
> -
> -bool lxc_setup_mount_cgroup(const char *root,
> - struct lxc_cgroup_info *cgroup_info, int type)
> -{
> - return active_cg_ops->mount_cgroup(root, cgroup_info, type);
> -}
> diff --git a/src/lxc/cgmanager.c b/src/lxc/cgmanager.c
> index a3faac1..6798b6b 100644
> --- a/src/lxc/cgmanager.c
> +++ b/src/lxc/cgmanager.c
> @@ -58,24 +58,74 @@ lxc_log_define(lxc_cgmanager, lxc);
> #include <nih/alloc.h>
> #include <nih/error.h>
> #include <nih/string.h>
> -NihDBusProxy *cgroup_manager = NULL;
>
> -extern struct cgroup_ops *active_cg_ops;
> -bool cgmanager_initialized = false;
> -bool use_cgmanager = true;
> +struct cgm_data {
> + char *name;
> + char *cgroup_path;
> + const char *cgroup_pattern;
> +};
> +
> +static NihDBusProxy *cgroup_manager = NULL;
> static struct cgroup_ops cgmanager_ops;
> static int nr_subsystems;
> static char **subsystems;
>
> -bool lxc_init_cgmanager(void);
> -static void cgmanager_disconnected(DBusConnection *connection)
> +#define CGMANAGER_DBUS_SOCK "unix:path=/sys/fs/cgroup/cgmanager/sock"
> +static void cgm_dbus_disconnected(DBusConnection *connection);
> +static bool cgm_dbus_connect(void)
> +{
> + DBusError dbus_error;
> + DBusConnection *connection;
> + dbus_error_init(&dbus_error);
> +
> + connection = nih_dbus_connect(CGMANAGER_DBUS_SOCK, cgm_dbus_disconnected);
> + if (!connection) {
> + NihError *nerr;
> + nerr = nih_error_get();
> + DEBUG("Unable to open cgmanager connection at %s: %s", CGMANAGER_DBUS_SOCK,
> + nerr->message);
> + nih_free(nerr);
> + dbus_error_free(&dbus_error);
> + 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) {
> + NihError *nerr;
> + nerr = nih_error_get();
> + ERROR("Error opening cgmanager proxy: %s", nerr->message);
> + nih_free(nerr);
> + return false;
> + }
> +
> + // force fd passing negotiation
> + if (cgmanager_ping_sync(NULL, cgroup_manager, 0) != 0) {
> + NihError *nerr;
> + nerr = nih_error_get();
> + ERROR("Error pinging cgroup manager: %s", nerr->message);
> + nih_free(nerr);
> + }
> + return true;
> +}
> +
> +static void cgm_dbus_disconnect(void)
> +{
> + nih_free(cgroup_manager);
> + cgroup_manager = NULL;
> +}
> +
> +static void cgm_dbus_disconnected(DBusConnection *connection)
> {
> WARN("Cgroup manager connection was terminated");
> cgroup_manager = NULL;
> - cgmanager_initialized = false;
> - if (lxc_init_cgmanager()) {
> - cgmanager_initialized = true;
> + if (cgm_dbus_connect()) {
> INFO("New cgroup manager connection was opened");
> + } else {
> + WARN("Cgroup manager unable to re-open connection");
> }
> }
>
> @@ -115,47 +165,6 @@ static int send_creds(int sock, int rpid, int ruid, int rgid)
> return 0;
> }
>
> -#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) {
> - NihError *nerr;
> - nerr = nih_error_get();
> - ERROR("Error opening cgmanager connection at %s: %s", CGMANAGER_DBUS_SOCK,
> - nerr->message);
> - nih_free(nerr);
> - dbus_error_free(&dbus_error);
> - 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) {
> - NihError *nerr;
> - nerr = nih_error_get();
> - ERROR("Error opening cgmanager proxy: %s", nerr->message);
> - nih_free(nerr);
> - return false;
> - }
> - active_cg_ops = &cgmanager_ops;
> - // force fd passing negotiation
> - if (cgmanager_ping_sync(NULL, cgroup_manager, 0) != 0) {
> - NihError *nerr;
> - nerr = nih_error_get();
> - ERROR("Error pinging cgroup manager: %s", nerr->message);
> - nih_free(nerr);
> - }
> - return true;
> -}
> -
> static bool lxc_cgmanager_create(const char *controller, const char *cgroup_path, int32_t *existed)
> {
> if ( cgmanager_create_sync(NULL, cgroup_manager, controller,
> @@ -341,19 +350,49 @@ static void cgm_remove_cgroup(const char *controller, const char *path)
> INFO("cgroup removal attempt: %s:%s did not exist", controller, path);
> }
>
> -static void cgm_destroy(struct lxc_handler *handler)
> +static void *cgm_init(const char *name)
> {
> - char *cgroup_path = handler->cgroup_info->data;
> + struct cgm_data *d;
> +
> + d = malloc(sizeof(*d));
> + if (!d)
> + return NULL;
> +
> + memset(d, 0, sizeof(*d));
> + d->name = strdup(name);
> + if (!d->name)
> + goto err1;
> +
> + /* 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)
> + d->cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern");
> + if (!d->cgroup_pattern)
> + d->cgroup_pattern = "%n";
> + return d;
> +
> +err1:
> + free(d);
> + return NULL;
> +}
> +
> +static void cgm_destroy(void *hdata)
> +{
> + struct cgm_data *d = hdata;
> int i;
>
> - if (!cgroup_path)
> + if (!d)
> return;
> -
> for (i = 0; i < nr_subsystems; i++)
> - cgm_remove_cgroup(subsystems[i], cgroup_path);
> + cgm_remove_cgroup(subsystems[i], d->cgroup_path);
>
> - free(cgroup_path);
> - handler->cgroup_info->data = NULL;
> + free(d->name);
> + if (d->cgroup_path)
> + free(d->cgroup_path);
> + free(d);
> }
>
> /*
> @@ -366,19 +405,21 @@ static inline void cleanup_cgroups(char *path)
> cgm_remove_cgroup(subsystems[i], path);
> }
>
> -static inline bool cgm_create(struct lxc_handler *handler)
> +static inline bool cgm_create(void *hdata)
> {
> + struct cgm_data *d = hdata;
> int i, index=0, baselen, ret;
> int32_t existed;
> - char result[MAXPATHLEN], *tmp;
> - char *cgroup_path = handler->cgroup_info->data;
> + char result[MAXPATHLEN], *tmp, *cgroup_path;
>
> + if (!d)
> + return false;
> // 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);
> + tmp = lxc_string_replace("%n", d->name, d->cgroup_pattern);
> if (!tmp)
> return false;
> if (strlen(tmp) > MAXPATHLEN)
> @@ -415,7 +456,7 @@ again:
> cleanup_cgroups(tmp);
> return false;
> }
> - handler->cgroup_info->data = cgroup_path;
> + d->cgroup_path = cgroup_path;
> return true;
> next:
> cleanup_cgroups(tmp);
> @@ -454,19 +495,25 @@ static bool do_cgm_enter(pid_t pid, const char *cgroup_path)
> return true;
> }
>
> -static inline bool cgm_enter(struct lxc_handler *handler)
> +static inline bool cgm_enter(void *hdata, pid_t pid)
> {
> - char *cgroup_path = handler->cgroup_info->data;
> - return do_cgm_enter(handler->pid, cgroup_path);
> + struct cgm_data *d = hdata;
> +
> + if (!d || !d->cgroup_path)
> + return false;
> + return do_cgm_enter(pid, d->cgroup_path);
> }
>
> -static char *cgm_get_cgroup(struct lxc_handler *handler, const char *subsystem)
> +static const char *cgm_get_cgroup(void *hdata, const char *subsystem)
> {
> - char *cgroup_path = handler->cgroup_info->data;
> - return cgroup_path;
> + struct cgm_data *d = hdata;
> +
> + if (!d || !d->cgroup_path)
> + return NULL;
> + return d->cgroup_path;
> }
>
> -int cgm_get(const char *filename, char *value, size_t len, const char *name, const char *lxcpath)
> +static int cgm_get(const char *filename, char *value, size_t len, const char *name, const char *lxcpath)
> {
> char *result, *controller, *key, *cgroup;
> size_t newlen;
> @@ -531,7 +578,7 @@ static int cgm_do_set(const char *controller, const char *file,
> return ret;
> }
>
> -int cgm_set(const char *filename, const char *value, const char *name, const char *lxcpath)
> +static int cgm_set(const char *filename, const char *value, const char *name, const char *lxcpath)
> {
> char *controller, *key, *cgroup;
> int ret;
> @@ -555,10 +602,21 @@ int cgm_set(const char *filename, const char *value, const char *name, const cha
> return ret;
> }
>
> +static void free_subsystems(void)
> +{
> + int i;
> +
> + for (i = 0; i < nr_subsystems; i++)
> + free(subsystems[i]);
> + free(subsystems);
> + subsystems = NULL;
> + nr_subsystems = 0;
> +}
> +
> static bool collect_subsytems(void)
> {
> char *line = NULL, *tab1;
> - size_t sz = 0, i;
> + size_t sz = 0;
> FILE *f;
>
> if (subsystems) // already initialized
> @@ -598,51 +656,62 @@ static bool collect_subsytems(void)
>
> out_free:
> fclose(f);
> - for (i = 0; i < nr_subsystems; i++)
> - free(subsystems[i]);
> - free(subsystems);
> - subsystems = NULL;
> - nr_subsystems = 0;
> + free_subsystems();
> return false;
> }
>
> -static inline bool cgm_init(struct lxc_handler *handler)
> +struct cgroup_ops *cgm_ops_init(void)
> {
> if (!collect_subsytems())
> - return false;
> - if (geteuid())
> - return true;
> + return NULL;
> + if (!cgm_dbus_connect())
> + goto err1;
> +
> // root; try to escape to root cgroup
> - return lxc_cgmanager_escape();
> + if (geteuid() == 0 && !lxc_cgmanager_escape())
> + goto err2;
> +
> + return &cgmanager_ops;
> +
> +err2:
> + cgm_dbus_disconnect();
> +err1:
> + free_subsystems();
> + return NULL;
> }
>
> -static bool cgm_unfreeze_fromhandler(struct lxc_handler *handler)
> +static bool cgm_unfreeze(void *hdata)
> {
> - char *cgroup_path = handler->cgroup_info->data;
> + struct cgm_data *d = hdata;
>
> - if (cgmanager_set_value_sync(NULL, cgroup_manager, "freezer", cgroup_path,
> + if (!d || !d->cgroup_path)
> + return false;
> +
> + if (cgmanager_set_value_sync(NULL, cgroup_manager, "freezer", d->cgroup_path,
> "freezer.state", "THAWED") != 0) {
> NihError *nerr;
> nerr = nih_error_get();
> ERROR("call to cgmanager_set_value_sync failed: %s", nerr->message);
> nih_free(nerr);
> - ERROR("Error unfreezing %s", cgroup_path);
> + ERROR("Error unfreezing %s", d->cgroup_path);
> return false;
> }
> return true;
> }
>
> -static bool setup_limits(struct lxc_handler *h, bool do_devices)
> +static bool cgm_setup_limits(void *hdata, struct lxc_list *cgroup_settings, bool do_devices)
> {
> + struct cgm_data *d = hdata;
> struct lxc_list *iterator;
> struct lxc_cgroup *cg;
> bool ret = false;
> - struct lxc_list *cgroup_settings = &h->conf->cgroup;
> - char *cgroup_path = h->cgroup_info->data;
>
> if (lxc_list_empty(cgroup_settings))
> return true;
>
> + if (!d || !d->cgroup_path)
> + return false;
> +
> lxc_list_for_each(iterator, cgroup_settings) {
> char controller[100], *p;
> cg = iterator->elem;
> @@ -654,10 +723,10 @@ static bool setup_limits(struct lxc_handler *h, bool do_devices)
> p = strchr(controller, '.');
> if (p)
> *p = '\0';
> - if (cgm_do_set(controller, cg->subsystem, cgroup_path
> + if (cgm_do_set(controller, cg->subsystem, d->cgroup_path
> , cg->value) < 0) {
> ERROR("Error setting %s to %s for %s\n",
> - cg->subsystem, cg->value, h->name);
> + cg->subsystem, cg->value, d->name);
> goto out;
> }
>
> @@ -670,20 +739,17 @@ out:
> return ret;
> }
>
> -static bool cgm_setup_limits(struct lxc_handler *handler, bool with_devices)
> -{
> - return setup_limits(handler, with_devices);
> -}
> -
> -static bool cgm_chown(struct lxc_handler *handler)
> +static bool cgm_chown(void *hdata, struct lxc_conf *conf)
> {
> - char *cgroup_path = handler->cgroup_info->data;
> + struct cgm_data *d = hdata;
> int i;
>
> + if (!d || !d->cgroup_path)
> + return false;
> for (i = 0; i < nr_subsystems; i++) {
> - if (!chown_cgroup(subsystems[i], cgroup_path, handler->conf))
> + if (!chown_cgroup(subsystems[i], d->cgroup_path, conf))
> WARN("Failed to chown %s:%s to container root",
> - subsystems[i], cgroup_path);
> + subsystems[i], d->cgroup_path);
> }
> return true;
> }
> @@ -771,8 +837,7 @@ static bool cgm_bind_dir(const char *root, const char *dirname)
> */
> #define CGMANAGER_LOWER_SOCK "/sys/fs/cgroup/cgmanager.lower"
> #define CGMANAGER_UPPER_SOCK "/sys/fs/cgroup/cgmanager"
> -static bool cgm_mount_cgroup(const char *root,
> - struct lxc_cgroup_info *cgroup_info, int type)
> +static bool cgm_mount_cgroup(void *hdata, const char *root, int type)
> {
> if (dir_exists(CGMANAGER_LOWER_SOCK))
> return cgm_bind_dir(root, CGMANAGER_LOWER_SOCK);
> @@ -783,19 +848,20 @@ static bool cgm_mount_cgroup(const char *root,
> }
>
> static struct cgroup_ops cgmanager_ops = {
> - .destroy = cgm_destroy,
> .init = cgm_init,
> + .destroy = cgm_destroy,
> .create = cgm_create,
> .enter = cgm_enter,
> .create_legacy = NULL,
> .get_cgroup = cgm_get_cgroup,
> .get = cgm_get,
> .set = cgm_set,
> - .unfreeze_fromhandler = cgm_unfreeze_fromhandler,
> + .unfreeze = cgm_unfreeze,
> .setup_limits = cgm_setup_limits,
> .name = "cgmanager",
> .chown = cgm_chown,
> .attach = cgm_attach,
> .mount_cgroup = cgm_mount_cgroup,
> + .nrtasks = NULL,
> };
> #endif
> diff --git a/src/lxc/cgroup.c b/src/lxc/cgroup.c
> new file mode 100644
> index 0000000..b03f69d
> --- /dev/null
> +++ b/src/lxc/cgroup.c
> @@ -0,0 +1,169 @@
> +/*
> + * 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
> + */
> +
> +#include "cgroup.h"
> +#include "conf.h"
> +#include "log.h"
> +#include "start.h"
> +
> +lxc_log_define(lxc_cgroup, lxc);
> +
> +static struct cgroup_ops *ops = NULL;
> +
> +extern struct cgroup_ops *cgfs_ops_init(void);
> +extern struct cgroup_ops *cgm_ops_init(void);
> +
> +__attribute__((constructor))
> +void cgroup_ops_init(void)
> +{
> + if (ops) {
> + INFO("cgroup driver %s", ops->name);
> + return;
> + }
> +
> + DEBUG("cgroup_init");
> + #if HAVE_CGMANAGER
> + ops = cgm_ops_init();
> + #endif
> + if (!ops)
> + ops = cgfs_ops_init();
> + if (ops)
> + INFO("Initialized cgroup driver %s", ops->name);
> +}
> +
> +bool cgroup_init(struct lxc_handler *handler)
> +{
> + if (handler->cgroup_data) {
> + ERROR("cgroup_init called on already inited handler");
> + return true;
> + }
> +
> + if (ops) {
> + INFO("cgroup driver %s initing for %s", ops->name, handler->name);
> + handler->cgroup_data = ops->init(handler->name);
> + }
> + return handler->cgroup_data != NULL;
> +}
> +
> +void cgroup_destroy(struct lxc_handler *handler)
> +{
> + if (ops) {
> + ops->destroy(handler->cgroup_data);
> + handler->cgroup_data = NULL;
> + }
> +}
> +
> +/* Create the container cgroups for all requested controllers */
> +bool cgroup_create(struct lxc_handler *handler)
> +{
> + if (ops)
> + return ops->create(handler->cgroup_data);
> + return false;
> +}
> +
> +/*
> + * Enter the container init into its new cgroups for all
> + * requested controllers
> + */
> +bool cgroup_enter(struct lxc_handler *handler)
> +{
> + if (ops)
> + return ops->enter(handler->cgroup_data, handler->pid);
> + return false;
> +}
> +
> +bool cgroup_create_legacy(struct lxc_handler *handler)
> +{
> + if (ops && ops->create_legacy)
> + return ops->create_legacy(handler->cgroup_data, handler->pid);
> + return true;
> +}
> +
> +const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem)
> +{
> + if (ops)
> + return ops->get_cgroup(handler->cgroup_data, subsystem);
> + return NULL;
> +}
> +
> +bool cgroup_unfreeze(struct lxc_handler *handler)
> +{
> + if (ops)
> + return ops->unfreeze(handler->cgroup_data);
> + return false;
> +}
> +
> +bool cgroup_setup_limits(struct lxc_handler *handler, bool with_devices)
> +{
> + if (ops)
> + return ops->setup_limits(handler->cgroup_data,
> + &handler->conf->cgroup, with_devices);
> + return false;
> +}
> +
> +bool cgroup_chown(struct lxc_handler *handler)
> +{
> + if (ops && ops->chown)
> + return ops->chown(handler->cgroup_data, handler->conf);
> + return true;
> +}
> +
> +bool cgroup_mount(const char *root, struct lxc_handler *handler, int type)
> +{
> + if (ops) {
> + return ops->mount_cgroup(handler->cgroup_data, root, type);
> + }
> + return false;
> +}
> +
> +int cgroup_nrtasks(struct lxc_handler *handler)
> +{
> + if (ops) {
> + if (ops->nrtasks)
> + return ops->nrtasks(handler->cgroup_data);
> + else
> + WARN("CGROUP driver %s doesn't implement nrtasks", ops->name);
> + }
> + return -1;
> +}
> +
> +bool cgroup_attach(const char *name, const char *lxcpath, pid_t pid)
> +{
> + if (ops)
> + return ops->attach(name, lxcpath, pid);
> + return false;
> +}
> +
> +int lxc_cgroup_set(const char *filename, const char *value, const char *name, const char *lxcpath)
> +{
> + if (ops)
> + return ops->set(filename, value, name, lxcpath);
> + return -1;
> +}
> +
> +int lxc_cgroup_get(const char *filename, char *value, size_t len, const char *name, const char *lxcpath)
> +{
> + if (ops)
> + return ops->get(filename, value, len, name, lxcpath);
> + return -1;
> +}
> diff --git a/src/lxc/cgroup.h b/src/lxc/cgroup.h
> index da77473..6f9e5f6 100644
> --- a/src/lxc/cgroup.h
> +++ b/src/lxc/cgroup.h
> @@ -20,195 +20,39 @@
> * License along with this library; if not, write to the Free Software
> * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> */
> -#ifndef _ncgroup_h
> -#define _ncgroup_h
> -#include <stdbool.h>
> -#include <stdint.h>
> -#include <stddef.h>
> -
> -#include "state.h"
> -
> -struct cgroup_hierarchy;
> -struct cgroup_meta_data;
> -struct cgroup_mount_point;
> -
> -/*
> - * cgroup_meta_data: the metadata about the cgroup infrastructure on this
> - * host
> - */
> -struct cgroup_meta_data {
> - ptrdiff_t ref; /* simple refcount */
> - struct cgroup_hierarchy **hierarchies;
> - struct cgroup_mount_point **mount_points;
> - int maximum_hierarchy;
> -};
> -
> -/*
> - * cgroup_hierarchy: describes a single cgroup hierarchy
> - * (may have multiple mount points)
> - */
> -struct cgroup_hierarchy {
> - int index;
> - bool used; /* false if the hierarchy should be ignored by lxc */
> - char **subsystems;
> - struct cgroup_mount_point *rw_absolute_mount_point;
> - struct cgroup_mount_point *ro_absolute_mount_point;
> - struct cgroup_mount_point **all_mount_points;
> - size_t all_mount_point_capacity;
> -};
> -
> -/*
> - * cgroup_mount_point: a mount point to where a hierarchy
> - * is mounted to
> - */
> -struct cgroup_mount_point {
> - struct cgroup_hierarchy *hierarchy;
> - char *mount_point;
> - char *mount_prefix;
> - bool read_only;
> - bool need_cpuset_init;
> -};
> -
> -/*
> - * 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;
> - struct cgroup_meta_data *meta_ref;
> - struct cgroup_hierarchy *hierarchy;
> - char *cgroup_path;
> - char *cgroup_path_sub;
> - char **created_paths;
> - size_t created_paths_capacity;
> - size_t created_paths_count;
> - struct cgroup_mount_point *designated_mount_point;
> -};
> -
> -/* meta data management:
> - * lxc_cgroup_load_meta loads the meta data (using subsystem
> - * whitelist from main lxc configuration)
> - * lxc_cgroup_load_meta2 does the same, but allows one to specify
> - * a custom whitelist
> - * lxc_cgroup_get_meta increments the refcount of a meta data
> - * object
> - * lxc_cgroup_put_meta decrements the refcount of a meta data
> - * object, potentially destroying it
> - */
> -extern struct cgroup_meta_data *lxc_cgroup_load_meta();
> -extern struct cgroup_meta_data *lxc_cgroup_load_meta2(const char **subsystem_whitelist);
> -extern struct cgroup_meta_data *lxc_cgroup_get_meta(struct cgroup_meta_data *meta_data);
> -extern struct cgroup_meta_data *lxc_cgroup_put_meta(struct cgroup_meta_data *meta_data);
> -
> -/* find the hierarchy corresponding to a given subsystem */
> -extern struct cgroup_hierarchy *lxc_cgroup_find_hierarchy(struct cgroup_meta_data *meta_data, const char *subsystem);
> -
> -/* find a mount point for a given hierarchy that has access to the cgroup in 'cgroup' and (if wanted) is writable */
> -extern struct cgroup_mount_point *lxc_cgroup_find_mount_point(struct cgroup_hierarchy *hierarchy, const char *group, bool should_be_writable);
> -
> -/* all-in-one: find a mount point for a given hierarchy that has access to the cgroup and return the correct path within */
> -extern char *lxc_cgroup_find_abs_path(const char *subsystem, const char *group, bool should_be_writable, const char *suffix);
>
> -/* determine the cgroup membership of a given process */
> -extern struct cgroup_process_info *lxc_cgroup_process_info_get(pid_t pid, struct cgroup_meta_data *meta);
> -extern struct cgroup_process_info *lxc_cgroup_process_info_get_init(struct cgroup_meta_data *meta);
> -extern struct cgroup_process_info *lxc_cgroup_process_info_get_self(struct cgroup_meta_data *meta);
> +#ifndef __lxc_cgroup_h
> +#define __lxc_cgroup_h
>
> -/* 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);
> -extern int lxc_cgroup_create_legacy(struct cgroup_process_info *base_info, const char *name, pid_t pid);
> -
> -/* 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 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);
> +#include <stdbool.h>
> +#include <stddef.h>
> +#include <sys/types.h>
>
> struct lxc_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);
> -
> -/*
> - * lxc_cgroup_path_get: Get the absolute pathname for a cgroup
> - * file for a running container.
> - *
> - * @filename : the file of interest (e.g. "freezer.state") or
> - * the subsystem name (e.g. "freezer") in which case
> - * the directory where the cgroup may be modified
> - * will be returned
> - * @name : name of container to connect to
> - * @lxcpath : the lxcpath in which the container is running
> - *
> - * This is the exported function, which determines cgpath from the
> - * lxc-start of the @name container running in @lxcpath.
> - *
> - * Returns path on success, NULL on error. The caller must free()
> - * the returned path.
> - */
> -extern char *lxc_cgroup_path_get(const char *filename, const char *name,
> - const char *lxcpath);
> -
> +struct lxc_conf;
> 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_cgroup_nrtasks_handler(struct lxc_handler *handler);
>
> -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);
> -
> -/*
> - * 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;
> -};
> -
> -/* 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);
> + const char *name;
> +
> + void *(*init)(const char *name);
> + void (*destroy)(void *hdata);
> + bool (*create)(void *hdata);
> + bool (*enter)(void *hdata, pid_t pid);
> + bool (*create_legacy)(void *hdata, pid_t pid);
> + const char *(*get_cgroup)(void *hdata, 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);
> - bool (*unfreeze_fromhandler)(struct lxc_handler *handler);
> - bool (*setup_limits)(struct lxc_handler *handler, bool with_devices);
> - bool (*chown)(struct lxc_handler *handler);
> + bool (*unfreeze)(void *hdata);
> + bool (*setup_limits)(void *hdata, struct lxc_list *cgroup_conf, bool with_devices);
> + bool (*chown)(void *hdata, struct lxc_conf *conf);
> bool (*attach)(const char *name, const char *lxcpath, pid_t pid);
> - bool (*mount_cgroup)(const char *root, struct lxc_cgroup_info *info,
> - int type);
> - const char *name;
> -};
> -
> -struct cgfs_data {
> - struct cgroup_meta_data *meta;
> - struct cgroup_process_info *info;
> + bool (*mount_cgroup)(void *hdata, const char *root, int type);
> + int (*nrtasks)(void *hdata);
> };
>
> -/*
> - * backend-independent cgroup handlers
> - */
> +extern bool cgroup_attach(const char *name, const char *lxcpath, pid_t pid);
> +extern bool cgroup_mount(const char *root, struct lxc_handler *handler, int type);
> extern void cgroup_destroy(struct lxc_handler *handler);
> extern bool cgroup_init(struct lxc_handler *handler);
> extern bool cgroup_create(struct lxc_handler *handler);
> @@ -217,11 +61,8 @@ extern bool cgroup_chown(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 bool lxc_cgroup_attach(const char *name, const char *lxcpath, pid_t pid);
> -extern bool lxc_setup_mount_cgroup(const char *root, struct lxc_cgroup_info *cgroup_info, int type);
> -extern bool lxc_unfreeze_fromhandler(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);
> +extern int cgroup_nrtasks(struct lxc_handler *handler);
> +extern const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem);
> +extern bool cgroup_unfreeze(struct lxc_handler *handler);
>
> #endif
> diff --git a/src/lxc/commands.c b/src/lxc/commands.c
> index e9ab42f..6b46c2c 100644
> --- a/src/lxc/commands.c
> +++ b/src/lxc/commands.c
> @@ -430,7 +430,7 @@ static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
> struct lxc_handler *handler)
> {
> struct lxc_cmd_rsp rsp;
> - char *path;
> + const char *path;
>
> if (req->datalen < 1)
> return -1;
> @@ -439,7 +439,7 @@ static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
> if (!path)
> return -1;
> rsp.datalen = strlen(path) + 1,
> - rsp.data = path;
> + rsp.data = (char *)path;
> rsp.ret = 0;
>
> return lxc_cmd_rsp_send(fd, &rsp);
> @@ -590,7 +590,12 @@ 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) {
> - if (lxc_unfreeze_fromhandler(handler))
> + /* we can't just use lxc_unfreeze() since we are already in the
> + * context of handling the STOP cmd in lxc-start, and calling
> + * lxc_unfreeze() would do another cmd (GET_CGROUP) which would
> + * deadlock us
> + */
> + if (cgroup_unfreeze(handler))
> return 0;
> ERROR("Failed to unfreeze %s:%s", handler->lxcpath, handler->name);
> rsp.ret = -1;
> diff --git a/src/lxc/conf.c b/src/lxc/conf.c
> index fed5327..3a03db8 100644
> --- a/src/lxc/conf.c
> +++ b/src/lxc/conf.c
> @@ -63,7 +63,6 @@
> #include "utils.h"
> #include "conf.h"
> #include "log.h"
> -#include "lxc.h" /* for lxc_cgroup_set() */
> #include "caps.h" /* for lxc_caps_last_cap() */
> #include "bdev.h"
> #include "cgroup.h"
> @@ -670,7 +669,7 @@ int pin_rootfs(const char *rootfs)
> return fd;
> }
>
> -static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_cgroup_info *cgroup_info)
> +static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_handler *handler)
> {
> int r;
> size_t i;
> @@ -744,8 +743,8 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_cg
> }
>
> if (flags & LXC_AUTO_CGROUP_MASK) {
> - if (!lxc_setup_mount_cgroup(conf->rootfs.mount, cgroup_info,
> - flags & LXC_AUTO_CGROUP_MASK)) {
> + if (!cgroup_mount(conf->rootfs.mount, handler,
> + flags & LXC_AUTO_CGROUP_MASK)) {
> SYSERROR("error mounting /sys/fs/cgroup");
> return -1;
> }
> @@ -3497,7 +3496,6 @@ int lxc_setup(struct lxc_handler *handler)
> 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)) {
> @@ -3535,7 +3533,7 @@ int lxc_setup(struct lxc_handler *handler)
> /* do automatic mounts (mainly /proc and /sys), but exclude
> * those that need to wait until other stuff has finished
> */
> - if (lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & ~LXC_AUTO_CGROUP_MASK, cgroup_info) < 0) {
> + if (lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & ~LXC_AUTO_CGROUP_MASK, handler) < 0) {
> ERROR("failed to setup the automatic mounts for '%s'", name);
> return -1;
> }
> @@ -3554,7 +3552,7 @@ int lxc_setup(struct lxc_handler *handler)
> * before, /sys could not have been mounted
> * (is either mounted automatically or via fstab entries)
> */
> - if (lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & LXC_AUTO_CGROUP_MASK, cgroup_info) < 0) {
> + if (lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & LXC_AUTO_CGROUP_MASK, handler) < 0) {
> ERROR("failed to setup the automatic mounts for '%s'", name);
> return -1;
> }
> diff --git a/src/lxc/freezer.c b/src/lxc/freezer.c
> index 89c7fab..c79f139 100644
> --- a/src/lxc/freezer.c
> +++ b/src/lxc/freezer.c
> @@ -35,18 +35,53 @@
> #include "state.h"
> #include "monitor.h"
> #include "log.h"
> -#include "cgroup.h"
> +#include "lxc.h"
>
> lxc_log_define(lxc_freezer, lxc);
>
> +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)
> + return -1;
> +
> + if (v[strlen(v)-1] == '\n')
> + v[strlen(v)-1] = '\0';
> + return lxc_str2state(v);
> +}
> +
> +static int do_freeze_thaw(int freeze, const char *name, const char *lxcpath)
> +{
> + char v[100];
> + const char *state = freeze ? "FROZEN" : "THAWED";
> +
> + if (lxc_cgroup_set("freezer.state", state, name, lxcpath) < 0) {
> + ERROR("Failed to freeze %s:%s", lxcpath, name);
> + 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);
> + }
> +}
>
> int lxc_freeze(const char *name, const char *lxcpath)
> {
> lxc_monitor_send_state(name, FREEZING, lxcpath);
> - return freeze_unfreeze(name, 1, lxcpath);
> + return do_freeze_thaw(1, name, lxcpath);
> }
>
> int lxc_unfreeze(const char *name, const char *lxcpath)
> {
> - return freeze_unfreeze(name, 0, lxcpath);
> + return do_freeze_thaw(0, name, lxcpath);
> }
> diff --git a/src/lxc/lxc.h b/src/lxc/lxc.h
> index 56f9fe2..8775640 100644
> --- a/src/lxc/lxc.h
> +++ b/src/lxc/lxc.h
> @@ -129,17 +129,6 @@ extern int lxc_unfreeze(const char *name, const char *lxcpath);
> */
> extern lxc_state_t lxc_state(const char *name, const char *lxcpath);
>
> -struct lxc_handler;
> -/*
> - * Set a specified value for a specified subsystem. The specified
> - * subsystem must be fully specified, eg. "cpu.shares"
> - * @filename : the cgroup attribute filename
> - * @value : the value to be set
> - * @handler : the lxc_handler structure of the container
> - * Returns 0 on success, < 0 otherwise
> - */
> -extern int lxc_cgroup_set_handler(const char *filename, const char *value, struct lxc_handler *handler);
> -
> /*
> * Set a specified value for a specified subsystem. The specified
> * subsystem must be fully specified, eg. "cpu.shares"
> diff --git a/src/lxc/lxcutmp.c b/src/lxc/lxcutmp.c
> index 15dd71c..24cfa75 100644
> --- a/src/lxc/lxcutmp.c
> +++ b/src/lxc/lxcutmp.c
> @@ -291,7 +291,7 @@ static int utmp_get_ntasks(struct lxc_handler *handler)
> {
> int ntasks;
>
> - ntasks = lxc_cgroup_nrtasks_handler(handler);
> + ntasks = cgroup_nrtasks(handler);
>
> if (ntasks < 0) {
> ERROR("failed to get the number of tasks");
> diff --git a/src/lxc/start.h b/src/lxc/start.h
> index c30c661..63fa8b4 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 lxc_cgroup_info *cgroup_info;
> + void *cgroup_data;
> };
>
> extern struct lxc_handler *lxc_init(const char *name, struct lxc_conf *, const char *);
> diff --git a/src/lxc/state.c b/src/lxc/state.c
> index 81648e0..db833b0 100644
> --- a/src/lxc/state.c
> +++ b/src/lxc/state.c
> @@ -69,6 +69,8 @@ lxc_state_t lxc_str2state(const char *state)
>
> lxc_state_t lxc_getstate(const char *name, const char *lxcpath)
> {
> + extern lxc_state_t freezer_state(const char *name, const char *lxcpath);
> +
> lxc_state_t state = freezer_state(name, lxcpath);
> if (state != FROZEN && state != FREEZING)
> state = lxc_cmd_get_state(name, lxcpath);
> diff --git a/src/tests/cgpath.c b/src/tests/cgpath.c
> index f0e2de8..c8a09e8 100644
> --- a/src/tests/cgpath.c
> +++ b/src/tests/cgpath.c
> @@ -50,9 +50,7 @@ static int test_running_container(const char *lxcpath,
> int ret = -1;
> struct lxc_container *c = NULL;
> char *cgrelpath;
> - char *cgabspath;
> char relpath[PATH_MAX+1];
> - char abspath[PATH_MAX+1];
> char value[NAME_MAX], value_save[NAME_MAX];
>
> sprintf(relpath, "%s/%s", group ? group : "lxc", name);
> @@ -109,32 +107,8 @@ static int test_running_container(const char *lxcpath,
> goto err3;
> }
>
> - cgabspath = lxc_cgroup_path_get("freezer", c->name, c->config_path);
> - if (!cgabspath) {
> - TSTERR("lxc_cgroup_path_get returned NULL");
> - goto err3;
> - }
> - sprintf(abspath, "%s/%s/%s", "freezer", group ? group : "lxc", c->name);
> - if (!strstr(cgabspath, abspath)) {
> - TSTERR("lxc_cgroup_path_get %s not in %s", abspath, cgabspath);
> - goto err4;
> - }
> -
> - free(cgabspath);
> - cgabspath = lxc_cgroup_path_get("freezer.state", c->name, c->config_path);
> - if (!cgabspath) {
> - TSTERR("lxc_cgroup_path_get returned NULL");
> - goto err3;
> - }
> - sprintf(abspath, "%s/%s/%s", "freezer", group ? group : "lxc", c->name);
> - if (!strstr(cgabspath, abspath)) {
> - TSTERR("lxc_cgroup_path_get %s not in %s", abspath, cgabspath);
> - goto err4;
> - }
> -
> ret = 0;
> -err4:
> - free(cgabspath);
> +
> err3:
> free(cgrelpath);
> err2:
> --
> 1.8.5.3
>
> _______________________________________________
> lxc-devel mailing list
> lxc-devel at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/lxc-devel
More information about the lxc-devel
mailing list