Commit 47ee660e by Stéphane Graber

Merge pull request #875 from hallyn/cgfsng

cgfsng: next generation filesystem-backed cgroup implementation
parents 554cd166 43647298
...@@ -89,6 +89,7 @@ liblxc_so_SOURCES = \ ...@@ -89,6 +89,7 @@ liblxc_so_SOURCES = \
error.h error.c \ error.h error.c \
parse.c parse.h \ parse.c parse.h \
cgfs.c \ cgfs.c \
cgfsng.c \
cgroup.c cgroup.h \ cgroup.c cgroup.h \
lxc.h \ lxc.h \
initutils.c initutils.h \ initutils.c initutils.h \
......
...@@ -141,7 +141,6 @@ static int do_cgroup_set(const char *cgroup_path, const char *sub_filename, cons ...@@ -141,7 +141,6 @@ static int do_cgroup_set(const char *cgroup_path, const char *sub_filename, cons
static bool cgroup_devices_has_allow_or_deny(struct cgfs_data *d, char *v, bool for_allow); 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 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 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 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 bool init_cpuset_if_needed(struct cgroup_mount_point *mp, const char *path);
...@@ -2116,7 +2115,7 @@ static int cgroup_recursive_task_count(const char *cgroup_path) ...@@ -2116,7 +2115,7 @@ static int cgroup_recursive_task_count(const char *cgroup_path)
if (r >= 0) if (r >= 0)
n += r; n += r;
} else if (!strcmp(dent->d_name, "tasks")) { } else if (!strcmp(dent->d_name, "tasks")) {
r = count_lines(sub_path); r = lxc_count_file_lines(sub_path);
if (r >= 0) if (r >= 0)
n += r; n += r;
} }
...@@ -2128,25 +2127,6 @@ static int cgroup_recursive_task_count(const char *cgroup_path) ...@@ -2128,25 +2127,6 @@ static int cgroup_recursive_task_count(const char *cgroup_path)
return n; return n;
} }
static int count_lines(const char *fn)
{
FILE *f;
char *line = NULL;
size_t sz = 0;
int n = 0;
f = fopen_cloexec(fn, "r");
if (!f)
return -1;
while (getline(&line, &sz, f) != -1) {
n++;
}
free(line);
fclose(f);
return n;
}
static int handle_cgroup_settings(struct cgroup_mount_point *mp, static int handle_cgroup_settings(struct cgroup_mount_point *mp,
char *cgroup_path) char *cgroup_path)
{ {
...@@ -2420,7 +2400,7 @@ static const char *cgfs_canonical_path(void *hdata) ...@@ -2420,7 +2400,7 @@ static const char *cgfs_canonical_path(void *hdata)
return path; return path;
} }
static bool cgfs_escape(void) static bool cgfs_escape(void *hdata)
{ {
struct cgroup_meta_data *md; struct cgroup_meta_data *md;
int i; int i;
......
...@@ -299,7 +299,7 @@ static bool lxc_cgmanager_create(const char *controller, const char *cgroup_path ...@@ -299,7 +299,7 @@ static bool lxc_cgmanager_create(const char *controller, const char *cgroup_path
* be in "/lxc/c1" rather than "/user/..../c1" * be in "/lxc/c1" rather than "/user/..../c1"
* called internally with connection already open * called internally with connection already open
*/ */
static bool cgm_escape(void) static bool cgm_escape(void *hdata)
{ {
bool ret = true, cgm_needs_disconnect = false; bool ret = true, cgm_needs_disconnect = false;
pid_t me = getpid(); pid_t me = getpid();
...@@ -1436,7 +1436,7 @@ struct cgroup_ops *cgm_ops_init(void) ...@@ -1436,7 +1436,7 @@ struct cgroup_ops *cgm_ops_init(void)
cgm_all_controllers_same = false; cgm_all_controllers_same = false;
// if root, try to escape to root cgroup // if root, try to escape to root cgroup
if (geteuid() == 0 && !cgm_escape()) { if (geteuid() == 0 && !cgm_escape(NULL)) {
free_subsystems(); free_subsystems();
return NULL; return NULL;
} }
......
...@@ -34,6 +34,7 @@ lxc_log_define(lxc_cgroup, lxc); ...@@ -34,6 +34,7 @@ lxc_log_define(lxc_cgroup, lxc);
static struct cgroup_ops *ops = NULL; static struct cgroup_ops *ops = NULL;
extern struct cgroup_ops *cgfs_ops_init(void); extern struct cgroup_ops *cgfs_ops_init(void);
extern struct cgroup_ops *cgfsng_ops_init(void);
extern struct cgroup_ops *cgm_ops_init(void); extern struct cgroup_ops *cgm_ops_init(void);
__attribute__((constructor)) __attribute__((constructor))
...@@ -45,8 +46,10 @@ void cgroup_ops_init(void) ...@@ -45,8 +46,10 @@ void cgroup_ops_init(void)
} }
DEBUG("cgroup_init"); DEBUG("cgroup_init");
ops = cgfsng_ops_init();
#if HAVE_CGMANAGER #if HAVE_CGMANAGER
ops = cgm_ops_init(); if (!ops)
ops = cgm_ops_init();
#endif #endif
if (!ops) if (!ops)
ops = cgfs_ops_init(); ops = cgfs_ops_init();
...@@ -109,10 +112,10 @@ const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem ...@@ -109,10 +112,10 @@ const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem
return NULL; return NULL;
} }
bool cgroup_escape(void) bool cgroup_escape(struct lxc_handler *handler)
{ {
if (ops) if (ops)
return ops->escape(); return ops->escape(handler->cgroup_data);
return false; return false;
} }
......
...@@ -35,6 +35,7 @@ struct lxc_list; ...@@ -35,6 +35,7 @@ struct lxc_list;
typedef enum { typedef enum {
CGFS, CGFS,
CGMANAGER, CGMANAGER,
CGFSNG,
} cgroup_driver_t; } cgroup_driver_t;
struct cgroup_ops { struct cgroup_ops {
...@@ -47,7 +48,7 @@ struct cgroup_ops { ...@@ -47,7 +48,7 @@ struct cgroup_ops {
bool (*create_legacy)(void *hdata, pid_t pid); bool (*create_legacy)(void *hdata, pid_t pid);
const char *(*get_cgroup)(void *hdata, const char *subsystem); const char *(*get_cgroup)(void *hdata, const char *subsystem);
const char *(*canonical_path)(void *hdata); const char *(*canonical_path)(void *hdata);
bool (*escape)(void); bool (*escape)(void *hdata);
int (*set)(const char *filename, const char *value, const char *name, const char *lxcpath); 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); int (*get)(const char *filename, char *value, size_t len, const char *name, const char *lxcpath);
bool (*unfreeze)(void *hdata); bool (*unfreeze)(void *hdata);
...@@ -72,7 +73,7 @@ extern void cgroup_cleanup(struct lxc_handler *handler); ...@@ -72,7 +73,7 @@ extern void cgroup_cleanup(struct lxc_handler *handler);
extern bool cgroup_create_legacy(struct lxc_handler *handler); extern bool cgroup_create_legacy(struct lxc_handler *handler);
extern int cgroup_nrtasks(struct lxc_handler *handler); extern int cgroup_nrtasks(struct lxc_handler *handler);
extern const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem); extern const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem);
extern bool cgroup_escape(void); extern bool cgroup_escape(struct lxc_handler *handler);
/* /*
* Currently, this call only makes sense for privileged containers. * Currently, this call only makes sense for privileged containers.
......
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
lxc_log_define(lxc_criu, lxc); lxc_log_define(lxc_criu, lxc);
void exec_criu(struct criu_opts *opts) void exec_criu(struct lxc_handler *handler, struct criu_opts *opts)
{ {
char **argv, log[PATH_MAX]; char **argv, log[PATH_MAX];
int static_args = 22, argc = 0, i, ret; int static_args = 22, argc = 0, i, ret;
...@@ -63,7 +63,7 @@ void exec_criu(struct criu_opts *opts) ...@@ -63,7 +63,7 @@ void exec_criu(struct criu_opts *opts)
* /actual/ root cgroup so that lxcfs thinks criu has enough rights to * /actual/ root cgroup so that lxcfs thinks criu has enough rights to
* see all cgroups. * see all cgroups.
*/ */
if (!cgroup_escape()) { if (!cgroup_escape(handler)) {
ERROR("failed to escape cgroups"); ERROR("failed to escape cgroups");
return; return;
} }
...@@ -517,7 +517,7 @@ void do_restore(struct lxc_container *c, int pipe, char *directory, bool verbose ...@@ -517,7 +517,7 @@ void do_restore(struct lxc_container *c, int pipe, char *directory, bool verbose
os.cgroup_path = cgroup_canonical_path(handler); os.cgroup_path = cgroup_canonical_path(handler);
/* exec_criu() returning is an error */ /* exec_criu() returning is an error */
exec_criu(&os); exec_criu(handler, &os);
umount(rootfs->mount); umount(rootfs->mount);
rmdir(rootfs->mount); rmdir(rootfs->mount);
goto out_fini_handler; goto out_fini_handler;
...@@ -624,6 +624,16 @@ static bool do_dump(struct lxc_container *c, char *mode, char *directory, ...@@ -624,6 +624,16 @@ static bool do_dump(struct lxc_container *c, char *mode, char *directory,
if (pid == 0) { if (pid == 0) {
struct criu_opts os; struct criu_opts os;
struct lxc_handler *handler;
handler = lxc_init(c->name, c->lxc_conf, c->config_path);
if (!handler)
exit(1);
if (!cgroup_init(handler)) {
ERROR("failed initing cgroups");
exit(1);
}
os.action = mode; os.action = mode;
os.directory = directory; os.directory = directory;
...@@ -633,7 +643,7 @@ static bool do_dump(struct lxc_container *c, char *mode, char *directory, ...@@ -633,7 +643,7 @@ static bool do_dump(struct lxc_container *c, char *mode, char *directory,
os.predump_dir = predump_dir; os.predump_dir = predump_dir;
/* exec_criu() returning is an error */ /* exec_criu() returning is an error */
exec_criu(&os); exec_criu(handler, &os);
exit(1); exit(1);
} else { } else {
int status; int status;
......
...@@ -58,7 +58,7 @@ struct criu_opts { ...@@ -58,7 +58,7 @@ struct criu_opts {
const char *cgroup_path; const char *cgroup_path;
}; };
void exec_criu(struct criu_opts *opts); void exec_criu(struct lxc_handler *handler, struct criu_opts *opts);
/* Check and make sure the container has a configuration that we know CRIU can /* Check and make sure the container has a configuration that we know CRIU can
* dump. */ * dump. */
......
...@@ -1771,3 +1771,25 @@ err: ...@@ -1771,3 +1771,25 @@ err:
close(fd); close(fd);
return ret; return ret;
} }
/*
* Return the number of lines in file @fn, or -1 on error
*/
int lxc_count_file_lines(const char *fn)
{
FILE *f;
char *line = NULL;
size_t sz = 0;
int n = 0;
f = fopen_cloexec(fn, "r");
if (!f)
return -1;
while (getline(&line, &sz, f) != -1) {
n++;
}
free(line);
fclose(f);
return n;
}
...@@ -284,4 +284,5 @@ int safe_mount(const char *src, const char *dest, const char *fstype, ...@@ -284,4 +284,5 @@ int safe_mount(const char *src, const char *dest, const char *fstype,
unsigned long flags, const void *data, const char *rootfs); unsigned long flags, const void *data, const char *rootfs);
int mount_proc_if_needed(const char *rootfs); int mount_proc_if_needed(const char *rootfs);
int null_stdfds(void); int null_stdfds(void);
int lxc_count_file_lines(const char *fn);
#endif /* __LXC_UTILS_H */ #endif /* __LXC_UTILS_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment