Commit 2ba7a429 by Tycho Andersen Committed by Serge Hallyn

restore: create cgroups for criu

Previously, we let criu create the cgroups for a container as it was restoring things. In some cases (i.e. migration across hosts), if the container being migrated was in /lxc/u1-3, it would be migrated to the target host in /lxc/u1-3, even if there was no /lxc/u1-2 (or worse, if there was already an alive container in u1-3). Instead, we use lxc's cgroup_create, and then tell criu where to restore to. Signed-off-by: 's avatarTycho Andersen <tycho.andersen@canonical.com> Acked-by: 's avatarSerge E. Hallyn <serge.hallyn@ubuntu.com>
parent dbb51a43
...@@ -2319,6 +2319,28 @@ static const char *cgfs_get_cgroup(void *hdata, const char *subsystem) ...@@ -2319,6 +2319,28 @@ static const char *cgfs_get_cgroup(void *hdata, const char *subsystem)
return lxc_cgroup_get_hierarchy_path_data(subsystem, d); return lxc_cgroup_get_hierarchy_path_data(subsystem, d);
} }
static const char *cgfs_canonical_path(void *hdata)
{
struct cgfs_data *d = hdata;
struct cgroup_process_info *info_ptr;
char *path = NULL;
if (!d)
return NULL;
for (info_ptr = d->info; info_ptr; info_ptr = info_ptr->next) {
if (!path)
path = info_ptr->cgroup_path;
else if (strcmp(path, info_ptr->cgroup_path) != 0) {
ERROR("not all paths match %s, %s has path %s", path,
info_ptr->hierarchy->subsystems[0], info_ptr->cgroup_path);
return NULL;
}
}
return path;
}
static bool cgfs_unfreeze(void *hdata) static bool cgfs_unfreeze(void *hdata)
{ {
struct cgfs_data *d = hdata; struct cgfs_data *d = hdata;
...@@ -2376,18 +2398,6 @@ static bool lxc_cgroupfs_attach(const char *name, const char *lxcpath, pid_t pid ...@@ -2376,18 +2398,6 @@ static bool lxc_cgroupfs_attach(const char *name, const char *lxcpath, pid_t pid
return true; return true;
} }
static bool cgfs_parse_existing_cgroups(void *hdata, pid_t init)
{
struct cgfs_data *d = hdata;
if (!d)
return false;
d->info = lxc_cgroup_process_info_get(init, d->meta);
return !!(d->info);
}
static struct cgroup_ops cgfs_ops = { static struct cgroup_ops cgfs_ops = {
.init = cgfs_init, .init = cgfs_init,
.destroy = cgfs_destroy, .destroy = cgfs_destroy,
...@@ -2395,6 +2405,7 @@ static struct cgroup_ops cgfs_ops = { ...@@ -2395,6 +2405,7 @@ static struct cgroup_ops cgfs_ops = {
.enter = cgfs_enter, .enter = cgfs_enter,
.create_legacy = cgfs_create_legacy, .create_legacy = cgfs_create_legacy,
.get_cgroup = cgfs_get_cgroup, .get_cgroup = cgfs_get_cgroup,
.canonical_path = cgfs_canonical_path,
.get = lxc_cgroupfs_get, .get = lxc_cgroupfs_get,
.set = lxc_cgroupfs_set, .set = lxc_cgroupfs_set,
.unfreeze = cgfs_unfreeze, .unfreeze = cgfs_unfreeze,
...@@ -2402,7 +2413,6 @@ static struct cgroup_ops cgfs_ops = { ...@@ -2402,7 +2413,6 @@ static struct cgroup_ops cgfs_ops = {
.name = "cgroupfs", .name = "cgroupfs",
.attach = lxc_cgroupfs_attach, .attach = lxc_cgroupfs_attach,
.chown = NULL, .chown = NULL,
.parse_existing_cgroups = cgfs_parse_existing_cgroups,
.mount_cgroup = cgroupfs_mount_cgroup, .mount_cgroup = cgroupfs_mount_cgroup,
.nrtasks = cgfs_nrtasks, .nrtasks = cgfs_nrtasks,
}; };
...@@ -727,6 +727,15 @@ static const char *cgm_get_cgroup(void *hdata, const char *subsystem) ...@@ -727,6 +727,15 @@ static const char *cgm_get_cgroup(void *hdata, const char *subsystem)
return d->cgroup_path; return d->cgroup_path;
} }
static const char *cgm_canonical_path(void *hdata)
{
struct cgm_data *d = hdata;
if (!d || !d->cgroup_path)
return NULL;
return d->cgroup_path;
}
#if HAVE_CGMANAGER_GET_PID_CGROUP_ABS_SYNC #if HAVE_CGMANAGER_GET_PID_CGROUP_ABS_SYNC
static inline bool abs_cgroup_supported(void) { static inline bool abs_cgroup_supported(void) {
return api_version >= CGM_SUPPORTS_GET_ABS; return api_version >= CGM_SUPPORTS_GET_ABS;
...@@ -1366,13 +1375,13 @@ static struct cgroup_ops cgmanager_ops = { ...@@ -1366,13 +1375,13 @@ static struct cgroup_ops cgmanager_ops = {
.enter = cgm_enter, .enter = cgm_enter,
.create_legacy = NULL, .create_legacy = NULL,
.get_cgroup = cgm_get_cgroup, .get_cgroup = cgm_get_cgroup,
.canonical_path = cgm_canonical_path,
.get = cgm_get, .get = cgm_get,
.set = cgm_set, .set = cgm_set,
.unfreeze = cgm_unfreeze, .unfreeze = cgm_unfreeze,
.setup_limits = cgm_setup_limits, .setup_limits = cgm_setup_limits,
.name = "cgmanager", .name = "cgmanager",
.chown = cgm_chown, .chown = cgm_chown,
.parse_existing_cgroups = NULL,
.attach = cgm_attach, .attach = cgm_attach,
.mount_cgroup = cgm_mount_cgroup, .mount_cgroup = cgm_mount_cgroup,
.nrtasks = cgm_get_nrtasks, .nrtasks = cgm_get_nrtasks,
......
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include <unistd.h>
#include <sys/types.h>
#include "cgroup.h" #include "cgroup.h"
#include "conf.h" #include "conf.h"
#include "log.h" #include "log.h"
...@@ -106,6 +109,19 @@ const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem ...@@ -106,6 +109,19 @@ const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem
return NULL; return NULL;
} }
const char *cgroup_canonical_path(struct lxc_handler *handler)
{
if (geteuid()) {
WARN("cgroup_canonical_path only makes sense for privileged containers.\n");
return NULL;
}
if (ops)
return ops->canonical_path(handler->cgroup_data);
return NULL;
}
bool cgroup_unfreeze(struct lxc_handler *handler) bool cgroup_unfreeze(struct lxc_handler *handler)
{ {
if (ops) if (ops)
...@@ -128,15 +144,6 @@ bool cgroup_chown(struct lxc_handler *handler) ...@@ -128,15 +144,6 @@ bool cgroup_chown(struct lxc_handler *handler)
return true; return true;
} }
bool cgroup_parse_existing_cgroups(struct lxc_handler *handler)
{
if (ops && ops->parse_existing_cgroups)
return ops->parse_existing_cgroups(handler->cgroup_data, handler->pid);
/* cgmanager does this automatically */
return true;
}
bool cgroup_mount(const char *root, struct lxc_handler *handler, int type) bool cgroup_mount(const char *root, struct lxc_handler *handler, int type)
{ {
if (ops) { if (ops) {
......
...@@ -41,12 +41,12 @@ struct cgroup_ops { ...@@ -41,12 +41,12 @@ struct cgroup_ops {
bool (*enter)(void *hdata, pid_t pid); bool (*enter)(void *hdata, pid_t pid);
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);
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);
bool (*setup_limits)(void *hdata, struct lxc_list *cgroup_conf, bool with_devices); bool (*setup_limits)(void *hdata, struct lxc_list *cgroup_conf, bool with_devices);
bool (*chown)(void *hdata, struct lxc_conf *conf); bool (*chown)(void *hdata, struct lxc_conf *conf);
bool (*parse_existing_cgroups)(void *hdata, pid_t pid);
bool (*attach)(const char *name, const char *lxcpath, pid_t pid); bool (*attach)(const char *name, const char *lxcpath, pid_t pid);
bool (*mount_cgroup)(void *hdata, const char *root, int type); bool (*mount_cgroup)(void *hdata, const char *root, int type);
int (*nrtasks)(void *hdata); int (*nrtasks)(void *hdata);
...@@ -60,12 +60,16 @@ extern bool cgroup_init(struct lxc_handler *handler); ...@@ -60,12 +60,16 @@ extern bool cgroup_init(struct lxc_handler *handler);
extern bool cgroup_create(struct lxc_handler *handler); extern bool cgroup_create(struct lxc_handler *handler);
extern bool cgroup_setup_limits(struct lxc_handler *handler, bool with_devices); extern bool cgroup_setup_limits(struct lxc_handler *handler, bool with_devices);
extern bool cgroup_chown(struct lxc_handler *handler); extern bool cgroup_chown(struct lxc_handler *handler);
extern bool cgroup_parse_existing_cgroups(struct lxc_handler *handler);
extern bool cgroup_enter(struct lxc_handler *handler); extern bool cgroup_enter(struct lxc_handler *handler);
extern void cgroup_cleanup(struct lxc_handler *handler); 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);
/*
* Currently, this call only makes sense for privileged containers.
*/
extern const char *cgroup_canonical_path(struct lxc_handler *handler);
extern bool cgroup_unfreeze(struct lxc_handler *handler); extern bool cgroup_unfreeze(struct lxc_handler *handler);
extern void cgroup_disconnect(void); extern void cgroup_disconnect(void);
......
...@@ -3485,6 +3485,7 @@ struct criu_opts { ...@@ -3485,6 +3485,7 @@ struct criu_opts {
/* restore: the file to write the init process' pid into */ /* restore: the file to write the init process' pid into */
char *pidfile; char *pidfile;
const char *cgroup_path;
}; };
/* /*
...@@ -3533,8 +3534,9 @@ static void exec_criu(struct criu_opts *opts) ...@@ -3533,8 +3534,9 @@ static void exec_criu(struct criu_opts *opts)
if (!opts->stop) if (!opts->stop)
static_args++; static_args++;
} else if (strcmp(opts->action, "restore") == 0) { } else if (strcmp(opts->action, "restore") == 0) {
/* --root $(lxc_mount_point) --restore-detached --restore-sibling --pidfile $foo */ /* --root $(lxc_mount_point) --restore-detached
static_args += 6; * --restore-sibling --pidfile $foo --cgroup-root $foo */
static_args += 8;
} else { } else {
return; return;
} }
...@@ -3607,6 +3609,8 @@ static void exec_criu(struct criu_opts *opts) ...@@ -3607,6 +3609,8 @@ static void exec_criu(struct criu_opts *opts)
DECLARE_ARG("--restore-sibling"); DECLARE_ARG("--restore-sibling");
DECLARE_ARG("--pidfile"); DECLARE_ARG("--pidfile");
DECLARE_ARG(opts->pidfile); DECLARE_ARG(opts->pidfile);
DECLARE_ARG("--cgroup-root");
DECLARE_ARG(opts->cgroup_path);
lxc_list_for_each(it, &opts->c->lxc_conf->network) { lxc_list_for_each(it, &opts->c->lxc_conf->network) {
char eth[128], veth[128], buf[257]; char eth[128], veth[128], buf[257];
...@@ -3832,6 +3836,11 @@ static bool lxcapi_restore(struct lxc_container *c, char *directory, bool verbos ...@@ -3832,6 +3836,11 @@ static bool lxcapi_restore(struct lxc_container *c, char *directory, bool verbos
goto out_fini_handler; goto out_fini_handler;
} }
if (!cgroup_create(handler)) {
ERROR("failed creating groups");
goto out_fini_handler;
}
pid = fork(); pid = fork();
if (pid < 0) if (pid < 0)
goto out_fini_handler; goto out_fini_handler;
...@@ -3865,6 +3874,7 @@ static bool lxcapi_restore(struct lxc_container *c, char *directory, bool verbos ...@@ -3865,6 +3874,7 @@ static bool lxcapi_restore(struct lxc_container *c, char *directory, bool verbos
os.c = c; os.c = c;
os.pidfile = pidfile; os.pidfile = pidfile;
os.verbose = verbose; os.verbose = verbose;
os.cgroup_path = cgroup_canonical_path(handler);
/* exec_criu() returning is an error */ /* exec_criu() returning is an error */
exec_criu(&os); exec_criu(&os);
...@@ -3901,11 +3911,6 @@ static bool lxcapi_restore(struct lxc_container *c, char *directory, bool verbos ...@@ -3901,11 +3911,6 @@ static bool lxcapi_restore(struct lxc_container *c, char *directory, bool verbos
goto out_fini_handler; goto out_fini_handler;
} }
if (!cgroup_parse_existing_cgroups(handler)) {
ERROR("failed creating cgroups");
goto out_fini_handler;
}
if (container_mem_lock(c)) if (container_mem_lock(c))
goto out_fini_handler; goto out_fini_handler;
......
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