[lxc-devel] [PATCH 2/2] split cgroup handling into discrete backends
Dwight Engen
dwight.engen at oracle.com
Wed Feb 5 21:59:26 UTC 2014
- 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
Signed-off-by: Dwight Engen <dwight.engen at oracle.com>
---
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
More information about the lxc-devel
mailing list