]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
split cgroup handling into discrete backends
authorDwight Engen <dwight.engen@oracle.com>
Wed, 5 Feb 2014 21:59:26 +0000 (16:59 -0500)
committerSerge Hallyn <serge.hallyn@ubuntu.com>
Thu, 6 Feb 2014 16:46:19 +0000 (10:46 -0600)
- 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@oracle.com>
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
14 files changed:
src/lxc/Makefile.am
src/lxc/attach.c
src/lxc/cgfs.c
src/lxc/cgmanager.c
src/lxc/cgroup.c [new file with mode: 0644]
src/lxc/cgroup.h
src/lxc/commands.c
src/lxc/conf.c
src/lxc/freezer.c
src/lxc/lxc.h
src/lxc/lxcutmp.c
src/lxc/start.h
src/lxc/state.c
src/tests/cgpath.c

index b4aa924fdc3ebc86c86ee0c5059180ec29b552dd..19511a4ec714b99e02b849bc00e773365ab8c8cc 100644 (file)
@@ -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 \
index 5c4adcddc0740bcb3a366e4252130e42089396a0..87826522d5ee0a27d74242a71a54560435e10683 100644 (file)
@@ -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;
                }
 
index c23b784faef028ad1fd4cabf7d2860a9fd8291ed..f576ba1517bc6cb062dcec00adadaf84ad4571c0 100644 (file)
 #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);
-}
index a3faac1e841f1a7d7698425d9debe33c66e8edd1..6798b6b84261491b00b9bcfac62ba00aefbce4e5 100644 (file)
@@ -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 (file)
index 0000000..b03f69d
--- /dev/null
@@ -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;
+}
index da77473cb0719c38de8d138b2aca2874931aac86..6f9e5f64508b1782f146dbfa5e7b75f524f12a51 100644 (file)
  * 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
index e9ab42f4a82200369968d4b1f2c7b8b625cb6709..6b46c2ca74ec70be0c84033b5476b28d87408fb6 100644 (file)
@@ -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;
index 3e16cc8226e6eb41985af76f86e01fedc99e8fea..81dcb42013435d9175971ae0baa45f6ff6cea02b 100644 (file)
@@ -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;
                }
@@ -3500,7 +3499,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)) {
@@ -3538,7 +3536,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;
        }
@@ -3557,7 +3555,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;
        }
index 89c7fab4ea3a3669077bba79bd63a298c555cea9..c79f13951180a88a0e6e02626e1e6bf162f6a152 100644 (file)
 #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);
 }
index 56f9fe25175f1701ce065aebf77f2db0b4e94cd8..8775640535e7cf71b22d2f2c66b9a75e14969f4b 100644 (file)
@@ -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"
index 15dd71cccbbad93044ae19ae28edc971b93a6497..24cfa7589e3a78026edd94af533f3edf8342b4c4 100644 (file)
@@ -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");
index c30c661707794af2e1dfc1a3bc25bbf3d2fa6e3f..63fa8b45b28f6b356068742543661e27790f3403 100644 (file)
@@ -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 *);
index 81648e034c46fa843c0098f035a8c0b6110ef92b..db833b0742a15a27fe72b4f80d0f9115b594268a 100644 (file)
@@ -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);
index f0e2de84cef4b44e1298a9774e72c46b53d7d4a3..c8a09e84a934d5ce887e4447bd59761881ce6161 100644 (file)
@@ -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: