From aa460476ad3a2e06747da3bfe2c7eb24ea084512 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Wed, 7 Jun 2017 22:23:56 +0200 Subject: [PATCH] start: add lxc_init_handler() Signed-off-by: Christian Brauner --- src/lxc/criu.c | 5 ++- src/lxc/execute.c | 15 ++++----- src/lxc/lxc.h | 8 +++-- src/lxc/lxccontainer.c | 36 +++++++++++++++------ src/lxc/start.c | 64 ++++++++++++++++++++++++------------- src/lxc/start.h | 9 ++++-- src/lxc/state.c | 22 ++++++------- src/lxc/tools/lxc_execute.c | 62 +++++++++++++++-------------------- 8 files changed, 125 insertions(+), 96 deletions(-) diff --git a/src/lxc/criu.c b/src/lxc/criu.c index 9b0ccacb6..6fa42b246 100644 --- a/src/lxc/criu.c +++ b/src/lxc/criu.c @@ -797,10 +797,13 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_ close(fd); } - handler = lxc_init(c->name, c->lxc_conf, c->config_path); + handler = lxc_init_handler(c->name, c->lxc_conf, c->config_path); if (!handler) goto out; + if (lxc_init(c->name, handler) < 0) + goto out; + if (!cgroup_init(handler)) { ERROR("failed initing cgroups"); goto out_fini_handler; diff --git a/src/lxc/execute.c b/src/lxc/execute.c index cfc81a761..40fd2241e 100644 --- a/src/lxc/execute.c +++ b/src/lxc/execute.c @@ -111,16 +111,15 @@ static struct lxc_operations execute_start_ops = { }; int lxc_execute(const char *name, char *const argv[], int quiet, - struct lxc_conf *conf, const char *lxcpath, bool backgrounded) + struct lxc_handler *handler, const char *lxcpath, + bool backgrounded) { - struct execute_args args = { - .argv = argv, - .quiet = quiet - }; + struct execute_args args = {.argv = argv, .quiet = quiet}; - if (lxc_check_inherited(conf, false, -1)) + if (lxc_check_inherited(handler->conf, false, handler->conf->maincmd_fd)) return -1; - conf->is_execute = 1; - return __lxc_start(name, conf, &execute_start_ops, &args, lxcpath, backgrounded); + handler->conf->is_execute = 1; + return __lxc_start(name, handler, &execute_start_ops, &args, lxcpath, + backgrounded); } diff --git a/src/lxc/lxc.h b/src/lxc/lxc.h index c6182d4e6..c3c55828a 100644 --- a/src/lxc/lxc.h +++ b/src/lxc/lxc.h @@ -36,6 +36,7 @@ extern "C" { struct lxc_msg; struct lxc_conf; struct lxc_arguments; +struct lxc_handler; /** Following code is for liblxc. @@ -51,8 +52,9 @@ struct lxc_arguments; * @backgrounded : whether or not the container is daemonized * Returns 0 on success, < 0 otherwise */ -extern int lxc_start(const char *name, char *const argv[], struct lxc_conf *conf, - const char *lxcpath, bool backgrounded); +extern int lxc_start(const char *name, char *const argv[], + struct lxc_handler *handler, const char *lxcpath, + bool backgrounded); /* * Start the specified command inside an application container @@ -64,7 +66,7 @@ extern int lxc_start(const char *name, char *const argv[], struct lxc_conf *conf * Returns 0 on success, < 0 otherwise */ extern int lxc_execute(const char *name, char *const argv[], int quiet, - struct lxc_conf *conf, const char *lxcpath, + struct lxc_handler *handler, const char *lxcpath, bool backgrounded); /* diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c index ebed82bc1..d4f5e0781 100644 --- a/src/lxc/lxccontainer.c +++ b/src/lxc/lxccontainer.c @@ -57,6 +57,7 @@ #include "namespace.h" #include "network.h" #include "sync.h" +#include "start.h" #include "state.h" #include "utils.h" #include "version.h" @@ -715,6 +716,7 @@ static void free_init_cmd(char **argv) static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const argv[]) { int ret; + struct lxc_handler *handler; struct lxc_conf *conf; bool daemonize = false; FILE *pid_fp = NULL; @@ -731,7 +733,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a /* If anything fails before we set error_num, we want an error in there */ c->error_num = 1; - /* container has been setup */ + /* container has not been setup */ if (!c->lxc_conf) return false; @@ -758,8 +760,16 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a daemonize = c->daemonize; container_mem_unlock(c); + /* initialize handler */ + handler = lxc_init_handler(c->name, conf, c->config_path); + if (!handler) + return false; + if (useinit) { - ret = lxc_execute(c->name, argv, 1, conf, c->config_path, daemonize); + TRACE("calling \"lxc_execute\""); + ret = lxc_execute(c->name, argv, 1, handler, c->config_path, + daemonize); + c->error_num = ret; return ret == 0 ? true : false; } @@ -791,6 +801,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a * the PID file, child will do the free and unlink. */ c->pidfile = NULL; + close(c->lxc_conf->maincmd_fd); return wait_on_daemonized_start(c, pid); } @@ -815,7 +826,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a SYSERROR("Error chdir()ing to /."); exit(1); } - lxc_check_inherited(conf, true, -1); + lxc_check_inherited(conf, true, handler->conf->maincmd_fd); if (null_stdfds() < 0) { ERROR("failed to close fds"); exit(1); @@ -828,7 +839,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a } } - /* We need to write PID file after daeminize, so we always + /* We need to write PID file after daemonize, so we always * write the right PID. */ if (c->pidfile) { @@ -869,13 +880,20 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a } reboot: - if (lxc_check_inherited(conf, daemonize, -1)) { + if (conf->reboot == 2) { + /* initialize handler */ + handler = lxc_init_handler(c->name, conf, c->config_path); + if (!handler) + goto out; + } + + if (lxc_check_inherited(conf, daemonize, handler->conf->maincmd_fd)) { ERROR("Inherited fds found"); ret = 1; goto out; } - ret = lxc_start(c->name, argv, conf, c->config_path, daemonize); + ret = lxc_start(c->name, argv, handler, c->config_path, daemonize); c->error_num = ret; if (conf->reboot == 1) { @@ -890,13 +908,11 @@ out: free(c->pidfile); c->pidfile = NULL; } - free_init_cmd(init_cmd); if (daemonize) - exit (ret == 0 ? true : false); - else - return (ret == 0 ? true : false); + exit(ret == 0 ? true : false); + return (ret == 0 ? true : false); } static bool lxcapi_start(struct lxc_container *c, int useinit, char * const argv[]) diff --git a/src/lxc/start.c b/src/lxc/start.c index bd1c62697..fbc196692 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -396,14 +396,17 @@ out_sigfd: return -1; } -struct lxc_handler *lxc_init(const char *name, struct lxc_conf *conf, const char *lxcpath) +struct lxc_handler *lxc_init_handler(const char *name, struct lxc_conf *conf, + const char *lxcpath) { int i; struct lxc_handler *handler; handler = malloc(sizeof(*handler)); - if (!handler) + if (!handler) { + ERROR("failed to allocate memory"); return NULL; + } memset(handler, 0, sizeof(*handler)); @@ -415,16 +418,37 @@ struct lxc_handler *lxc_init(const char *name, struct lxc_conf *conf, const char for (i = 0; i < LXC_NS_MAX; i++) handler->nsfd[i] = -1; - lsm_init(); - handler->name = strdup(name); if (!handler->name) { - ERROR("Failed to allocate memory."); - goto out_free; + ERROR("failed to allocate memory"); + goto do_partial_cleanup; } - if (lxc_cmd_init(name, handler, lxcpath)) - goto out_free_name; + if (lxc_cmd_init(name, handler, lxcpath)) { + ERROR("failed to set up command socket"); + goto do_full_cleanup; + } + + TRACE("unix domain socket %d for command server is ready", + handler->conf->maincmd_fd); + + return handler; + +do_full_cleanup: + free(handler->name); + +do_partial_cleanup: + free(handler); + + return NULL; +} + +int lxc_init(const char *name, struct lxc_handler *handler) +{ + struct lxc_conf *conf = handler->conf; + + lsm_init(); + TRACE("initialized LSM"); if (lxc_read_seccomp_config(conf) != 0) { ERROR("Failed loading seccomp policy."); @@ -487,7 +511,7 @@ struct lxc_handler *lxc_init(const char *name, struct lxc_conf *conf, const char } INFO("Container \"%s\" is initialized.", name); - return handler; + return 0; out_restore_sigmask: sigprocmask(SIG_SETMASK, &handler->oldmask, NULL); @@ -498,12 +522,7 @@ out_aborting: out_close_maincmd_fd: close(conf->maincmd_fd); conf->maincmd_fd = -1; -out_free_name: - free(handler->name); - handler->name = NULL; -out_free: - free(handler); - return NULL; + return -1; } void lxc_fini(const char *name, struct lxc_handler *handler) @@ -1337,17 +1356,16 @@ out_abort: return -1; } -int __lxc_start(const char *name, struct lxc_conf *conf, +int __lxc_start(const char *name, struct lxc_handler *handler, struct lxc_operations* ops, void *data, const char *lxcpath, bool backgrounded) { - struct lxc_handler *handler; - int err = -1; int status; + int err = -1; bool removed_all_netdevs = true; + struct lxc_conf *conf = handler->conf; - handler = lxc_init(name, conf, lxcpath); - if (!handler) { + if (lxc_init(name, handler) < 0) { ERROR("Failed to initialize container \"%s\".", name); return -1; } @@ -1494,15 +1512,15 @@ static struct lxc_operations start_ops = { .post_start = post_start }; -int lxc_start(const char *name, char *const argv[], struct lxc_conf *conf, +int lxc_start(const char *name, char *const argv[], struct lxc_handler *handler, const char *lxcpath, bool backgrounded) { struct start_args start_arg = { .argv = argv, }; - conf->need_utmp_watch = 1; - return __lxc_start(name, conf, &start_ops, &start_arg, lxcpath, backgrounded); + handler->conf->need_utmp_watch = 1; + return __lxc_start(name, handler, &start_ops, &start_arg, lxcpath, backgrounded); } static void lxc_destroy_container_on_signal(struct lxc_handler *handler, diff --git a/src/lxc/start.h b/src/lxc/start.h index 3bae8788c..7b8ebcf92 100644 --- a/src/lxc/start.h +++ b/src/lxc/start.h @@ -27,11 +27,11 @@ #include #include +#include "conf.h" #include "config.h" #include "state.h" #include "namespace.h" -struct lxc_conf; struct lxc_handler; @@ -66,11 +66,14 @@ struct lxc_handler { extern int lxc_poll(const char *name, struct lxc_handler *handler); extern int lxc_set_state(const char *name, struct lxc_handler *handler, lxc_state_t state); extern void lxc_abort(const char *name, struct lxc_handler *handler); -extern struct lxc_handler *lxc_init(const char *name, struct lxc_conf *, const char *); +extern struct lxc_handler *lxc_init_handler(const char *name, + struct lxc_conf *conf, + const char *lxcpath); +extern int lxc_init(const char *name, struct lxc_handler *handler); extern void lxc_fini(const char *name, struct lxc_handler *handler); extern int lxc_check_inherited(struct lxc_conf *conf, bool closeall, int fd_to_ignore); -int __lxc_start(const char *, struct lxc_conf *, struct lxc_operations *, +int __lxc_start(const char *, struct lxc_handler *, struct lxc_operations *, void *, const char *, bool); extern void resolve_clone_flags(struct lxc_handler *handler); diff --git a/src/lxc/state.c b/src/lxc/state.c index 7c1835b19..a5f6df8b0 100644 --- a/src/lxc/state.c +++ b/src/lxc/state.c @@ -109,24 +109,16 @@ extern int lxc_wait(const char *lxcname, const char *states, int timeout, const char *lxcpath) { struct lxc_msg msg; - int state, ret; - int s[MAX_STATE] = {0}, fd; + int state; + int s[MAX_STATE] = {0}, fd = -1, ret = -1; if (fillwaitedstates(states, s)) return -1; - if (lxc_monitord_spawn(lxcpath)) - return -1; - - fd = lxc_monitor_open(lxcpath); - if (fd < 0) - return -1; - /* * if container present, * then check if already in requested state */ - ret = -1; state = lxc_getstate(lxcname, lxcpath); if (state < 0) { goto out_close; @@ -135,6 +127,13 @@ extern int lxc_wait(const char *lxcname, const char *states, int timeout, goto out_close; } + if (lxc_monitord_spawn(lxcpath)) + return -1; + + fd = lxc_monitor_open(lxcpath); + if (fd < 0) + return -1; + for (;;) { int64_t elapsed_time, curtime = 0; struct timespec tspec; @@ -192,6 +191,7 @@ extern int lxc_wait(const char *lxcname, const char *states, int timeout, } out_close: - lxc_monitor_close(fd); + if (fd >= 0) + lxc_monitor_close(fd); return ret; } diff --git a/src/lxc/tools/lxc_execute.c b/src/lxc/tools/lxc_execute.c index 5eeee0333..3e3407e30 100644 --- a/src/lxc/tools/lxc_execute.c +++ b/src/lxc/tools/lxc_execute.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -40,7 +41,6 @@ #include "config.h" #include "start.h" #include "utils.h" -#include "lxccontainer.h" lxc_log_define(lxc_execute_ui, lxc); @@ -105,10 +105,10 @@ Options :\n\ int main(int argc, char *argv[]) { - char *rcfile; - struct lxc_conf *conf; + struct lxc_container *c; struct lxc_log log; int ret; + bool bret; lxc_list_init(&defines); @@ -129,50 +129,38 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); lxc_log_options_no_override(); - /* rcfile is specified in the cli option */ - if (my_args.rcfile) - rcfile = (char *)my_args.rcfile; - else { - int rc; + c = lxc_container_new(my_args.name, my_args.lxcpath[0]); + if (!c) { + ERROR("Failed to create lxc_container"); + exit(EXIT_FAILURE); + } - rc = asprintf(&rcfile, "%s/%s/config", my_args.lxcpath[0], my_args.name); - if (rc == -1) { - SYSERROR("failed to allocate memory"); + if (my_args.rcfile) { + c->clear_config(c); + if (!c->load_config(c, my_args.rcfile)) { + ERROR("Failed to load rcfile"); + lxc_container_put(c); exit(EXIT_FAILURE); } - - /* container configuration does not exist */ - if (access(rcfile, F_OK)) { - free(rcfile); - rcfile = NULL; + c->configfile = strdup(my_args.rcfile); + if (!c->configfile) { + ERROR("Out of memory setting new config filename"); + lxc_container_put(c); + exit(EXIT_FAILURE); } } - conf = lxc_conf_init(); - if (!conf) { - ERROR("failed to initialize configuration"); - exit(EXIT_FAILURE); - } - - if (rcfile && lxc_config_read(rcfile, conf, NULL)) { - ERROR("failed to read configuration file"); - exit(EXIT_FAILURE); - } - - if (lxc_config_define_load(&defines, conf)) - exit(EXIT_FAILURE); - if (my_args.uid) - conf->init_uid = my_args.uid; + c->lxc_conf->init_uid = my_args.uid; if (my_args.gid) - conf->init_gid = my_args.gid; + c->lxc_conf->init_gid = my_args.gid; - ret = lxc_execute(my_args.name, my_args.argv, my_args.quiet, conf, my_args.lxcpath[0], false); - - lxc_conf_free(conf); - - if (ret < 0) + c->daemonize = false; + bret = c->start(c, 1, my_args.argv); + ret = c->error_num; + lxc_container_put(c); + if (!bret) exit(EXIT_FAILURE); exit(ret); }