On Tue, Apr 21, 2015 at 08:09:12PM +0000, Serge Hallyn wrote: > The logging code uses a global log_fd and log_level to direct > logging (ERROR(), etc). While the container configuration file allows > for lxc.loglevel and lxc.logfile, those are only used at configuration > file read time to set the global variables. This works ok in the > lxc front-end programs, but becomes a problem with threaded API users. > > The simplest solution would be to not allow per-container configuration > files, but it'd be nice to avoid that. > > Passing a logfd or lxc_conf into every ERROR/INFO/etc call is "possible", > but would be a huge complication as there are many functions, including > struct member functions and callbacks, which don't have that info and > would need to get it from somewhere. > > So the approach I'm taking here is to say that all real container work > is done inside api calls, and therefore the API calls themselves can > set a thread-local variable indicating which log info to use. If > unset, then use the global values. The lxc-* programs, when called > with a '-o logfile' argument, set a global variable to indicate that > the user-specified value should be used. > > In this patch: > > If the lxc container configuration specifies a loglevel/logfile, only > set the lxc_config's logfd and loglevel according to those, not the > global values. > > Each API call is wrapped to set/unset the current_config. (The few > exceptions are calls which do not result in any log actions) > > Update logfile appender to use the logfile specified in lxc_conf if (a) > current_config is set and (b) the lxc-* command did not override it. > > Changelog (2015-04-21): > . always re-set current_config to NULL at end of an API > call, rather than storing the previous value. We don't > nest API calls. > . remove the log_lock stuff which wasn't used > . lxc_conf_free: if the config is current_config, set > current_config to NULL. (It can't be another thread's > current_config, or we wouldn't be freeing it) > . lxc_check_inherited: don't close fd if it is the > current_config->logfd. Note this is only called when > starting a container, so we have no other threads at > this point. >
Let's try that again :) Acked-by: Stéphane Graber <[email protected]> > Signed-off-by: Serge Hallyn <[email protected]> > --- > src/lxc/Makefile.am | 1 + > src/lxc/conf.c | 16 +++ > src/lxc/conf.h | 7 + > src/lxc/confile.c | 12 +- > src/lxc/log.c | 83 ++++++----- > src/lxc/log.h | 23 ++- > src/lxc/lxccontainer.c | 373 > ++++++++++++++++++++++++++++++++++++------------- > src/lxc/start.c | 3 + > 8 files changed, 373 insertions(+), 145 deletions(-) > > diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am > index b1e56b9..8b79c40 100644 > --- a/src/lxc/Makefile.am > +++ b/src/lxc/Makefile.am > @@ -248,6 +248,7 @@ endif > > init_lxc_static_LDFLAGS = -static > init_lxc_static_LDADD = @CAP_LIBS@ > +init_lxc_static_CFLAGS = $(AM_CFLAGS) -DNO_LXC_CONF > endif > > install-exec-local: install-soPROGRAMS > diff --git a/src/lxc/conf.c b/src/lxc/conf.c > index d4855fd..3a7a52a 100644 > --- a/src/lxc/conf.c > +++ b/src/lxc/conf.c > @@ -178,6 +178,17 @@ struct caps_opt { > int value; > }; > > +/* > + * The lxc_conf of the container currently being worked on in an > + * API call > + * This is used in the error calls > + */ > +#ifdef HAVE_TLS > +__thread struct lxc_conf *current_config; > +#else > +struct lxc_conf *current_config; > +#endif > + > /* Declare this here, since we don't want to reshuffle the whole file. */ > static int in_caplist(int cap, struct lxc_list *caps); > > @@ -2573,6 +2584,7 @@ struct lxc_conf *lxc_conf_init(void) > return NULL; > } > new->kmsg = 0; > + new->logfd = -1; > lxc_list_init(&new->cgroup); > lxc_list_init(&new->network); > lxc_list_init(&new->mount_list); > @@ -4239,6 +4251,8 @@ void lxc_conf_free(struct lxc_conf *conf) > { > if (!conf) > return; > + if (current_config == conf) > + current_config = NULL; > free(conf->console.log_path); > free(conf->console.path); > free(conf->rootfs.mount); > @@ -4246,6 +4260,8 @@ void lxc_conf_free(struct lxc_conf *conf) > free(conf->rootfs.path); > free(conf->rootfs.pivot); > free(conf->logfile); > + if (conf->logfd != -1) > + close(conf->logfd); > free(conf->utsname); > free(conf->ttydir); > free(conf->fstab); > diff --git a/src/lxc/conf.h b/src/lxc/conf.h > index 4b66045..0c0475e 100644 > --- a/src/lxc/conf.h > +++ b/src/lxc/conf.h > @@ -336,6 +336,7 @@ struct lxc_conf { > // store the config file specified values here. > char *logfile; // the logfile as specifed in config > int loglevel; // loglevel as specifed in config (if any) > + int logfd; > > int inherit_ns_fd[LXC_NS_MAX]; > > @@ -365,6 +366,12 @@ struct lxc_conf { > char *init_cmd; > }; > > +#ifdef HAVE_TLS > +extern __thread struct lxc_conf *current_config; > +#else > +extern struct lxc_conf *current_config; > +#endif > + > int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf, > const char *lxcpath, char *argv[]); > > diff --git a/src/lxc/confile.c b/src/lxc/confile.c > index e3be6a6..7e8b6a2 100644 > --- a/src/lxc/confile.c > +++ b/src/lxc/confile.c > @@ -1171,15 +1171,15 @@ static int config_lsm_se_context(const char *key, > const char *value, > } > > static int config_logfile(const char *key, const char *value, > - struct lxc_conf *lxc_conf) > + struct lxc_conf *c) > { > int ret; > > // store these values in the lxc_conf, and then try to set for > // actual current logging. > - ret = config_path_item(&lxc_conf->logfile, value); > + ret = config_path_item(&c->logfile, value); > if (ret == 0) > - ret = lxc_log_set_file(lxc_conf->logfile); > + ret = lxc_log_set_file(&c->logfd, c->logfile); > return ret; > } > > @@ -1198,7 +1198,7 @@ static int config_loglevel(const char *key, const char > *value, > // store these values in the lxc_conf, and then try to set for > // actual current logging. > lxc_conf->loglevel = newlevel; > - return lxc_log_set_level(newlevel); > + return lxc_log_set_level(&lxc_conf->loglevel, newlevel); > } > > static int config_autodev(const char *key, const char *value, > @@ -2381,9 +2381,9 @@ int lxc_get_config_item(struct lxc_conf *c, const char > *key, char *retv, > else if (strcmp(key, "lxc.se_context") == 0) > v = c->lsm_se_context; > else if (strcmp(key, "lxc.logfile") == 0) > - v = lxc_log_get_file(); > + v = c->logfile; > else if (strcmp(key, "lxc.loglevel") == 0) > - v = lxc_log_priority_to_string(lxc_log_get_level()); > + v = lxc_log_priority_to_string(c->loglevel); > else if (strcmp(key, "lxc.cgroup") == 0) // all cgroup info > return lxc_get_cgroup_entry(c, retv, inlen, "all"); > else if (strncmp(key, "lxc.cgroup.", 11) == 0) // specific cgroup info > diff --git a/src/lxc/log.c b/src/lxc/log.c > index 6633e62..a257f67 100644 > --- a/src/lxc/log.c > +++ b/src/lxc/log.c > @@ -27,6 +27,7 @@ > #include <sys/types.h> > #include <sys/stat.h> > #include <string.h> > +#include <pthread.h> > > #define __USE_GNU /* for *_CLOEXEC */ > > @@ -40,27 +41,13 @@ > #define LXC_LOG_PREFIX_SIZE 32 > #define LXC_LOG_BUFFER_SIZE 512 > > -#ifdef HAVE_TLS > -__thread int lxc_log_fd = -1; > -static __thread char log_prefix[LXC_LOG_PREFIX_SIZE] = "lxc"; > -static __thread char *log_fname = NULL; > -/* command line values for logfile or logpriority should always override > - * values from the configuration file or defaults > - */ > -static __thread int lxc_logfile_specified = 0; > -static __thread int lxc_loglevel_specified = 0; > -static __thread int lxc_quiet_specified = 0; > -#else > int lxc_log_fd = -1; > +int lxc_quiet_specified; > +int lxc_log_use_global_fd; > +static int lxc_loglevel_specified; > + > static char log_prefix[LXC_LOG_PREFIX_SIZE] = "lxc"; > static char *log_fname = NULL; > -static int lxc_quiet_specified = 0; > -/* command line values for logfile or logpriority should always override > - * values from the configuration file or defaults > - */ > -static int lxc_logfile_specified = 0; > -static int lxc_loglevel_specified = 0; > -#endif > > lxc_log_define(lxc_log, lxc); > > @@ -85,8 +72,17 @@ static int log_append_logfile(const struct > lxc_log_appender *appender, > char buffer[LXC_LOG_BUFFER_SIZE]; > int n; > int ms; > + int fd_to_use = -1; > > - if (lxc_log_fd == -1) > +#ifndef NO_LXC_CONF > + if (!lxc_log_use_global_fd && current_config) > + fd_to_use = current_config->logfd; > +#endif > + > + if (fd_to_use == -1) > + fd_to_use = lxc_log_fd; > + > + if (fd_to_use == -1) > return 0; > > ms = event->timestamp.tv_usec / 1000; > @@ -111,7 +107,7 @@ static int log_append_logfile(const struct > lxc_log_appender *appender, > > buffer[n] = '\n'; > > - return write(lxc_log_fd, buffer, n + 1); > + return write(fd_to_use, buffer, n + 1); > } > > static struct lxc_log_appender log_appender_stderr = { > @@ -136,7 +132,7 @@ static struct lxc_log_category log_root = { > struct lxc_log_category lxc_log_category_lxc = { > .name = "lxc", > .priority = LXC_LOG_PRIORITY_ERROR, > - .appender = &log_appender_stderr, > + .appender = &log_appender_logfile, > .parent = &log_root > }; > > @@ -305,6 +301,11 @@ static int _lxc_log_set_file(const char *name, const > char *lxcpath, int create_d > return ret; > } > > +/* > + * lxc_log_init: > + * Called from lxc front-end programs (like lxc-create, lxc-start) to > + * initalize the log defaults. > + */ > extern int lxc_log_init(const char *name, const char *file, > const char *priority, const char *prefix, int quiet, > const char *lxcpath) > @@ -320,10 +321,12 @@ extern int lxc_log_init(const char *name, const char > *file, > if (priority) > lxc_priority = lxc_log_priority_to_int(priority); > > - lxc_log_category_lxc.priority = lxc_priority; > + if (!lxc_loglevel_specified) { > + lxc_log_category_lxc.priority = lxc_priority; > + lxc_loglevel_specified = 1; > + } > > if (!lxc_quiet_specified) { > - lxc_log_category_lxc.appender = &log_appender_logfile; > if (!quiet) > lxc_log_category_lxc.appender->next = > &log_appender_stderr; > } > @@ -335,6 +338,7 @@ extern int lxc_log_init(const char *name, const char > *file, > if (strcmp(file, "none") == 0) > return 0; > ret = __lxc_log_set_file(file, 1); > + lxc_log_use_global_fd = 1; > } else { > /* if no name was specified, there nothing to do */ > if (!name) > @@ -385,15 +389,13 @@ extern void lxc_log_close(void) > * happens after processing command line arguments, which override the .conf > * settings. So only set the level if previously unset. > */ > -extern int lxc_log_set_level(int level) > +extern int lxc_log_set_level(int *dest, int level) > { > - if (lxc_loglevel_specified) > - return 0; > if (level < 0 || level >= LXC_LOG_PRIORITY_NOTSET) { > ERROR("invalid log priority %d", level); > return -1; > } > - lxc_log_category_lxc.priority = level; > + *dest = level; > return 0; > } > > @@ -415,11 +417,23 @@ extern bool lxc_log_has_valid_level(void) > * happens after processing command line arguments, which override the .conf > * settings. So only set the file if previously unset. > */ > -extern int lxc_log_set_file(const char *fname) > +extern int lxc_log_set_file(int *fd, const char *fname) > { > - if (lxc_logfile_specified) > - return 0; > - return __lxc_log_set_file(fname, 0); > + if (*fd != -1) { > + close(*fd); > + *fd = -1; > + } > + > + if (build_dir(fname)) { > + ERROR("failed to create dir for log file \"%s\" : %s", fname, > + strerror(errno)); > + return -1; > + } > + > + *fd = log_open(fname); > + if (*fd == -1) > + return -errno; > + return 0; > } > > extern const char *lxc_log_get_file(void) > @@ -440,11 +454,6 @@ extern const char *lxc_log_get_prefix(void) > > extern void lxc_log_options_no_override() > { > - if (lxc_log_get_file()) > - lxc_logfile_specified = 1; > - > - if (lxc_log_get_level() != LXC_LOG_PRIORITY_NOTSET) > - lxc_loglevel_specified = 1; > - > lxc_quiet_specified = 1; > + lxc_loglevel_specified = 1; > } > diff --git a/src/lxc/log.h b/src/lxc/log.h > index b47f120..76bd4df 100644 > --- a/src/lxc/log.h > +++ b/src/lxc/log.h > @@ -33,6 +33,8 @@ > #include <strings.h> > #include <stdbool.h> > > +#include "conf.h" > + > #ifndef O_CLOEXEC > #define O_CLOEXEC 02000000 > #endif > @@ -104,6 +106,10 @@ struct lxc_log_category { > const struct lxc_log_category *parent; > }; > > +#ifndef NO_LXC_CONF > +extern int lxc_log_use_global_fd; > +#endif > + > /* > * Returns true if the chained priority is equal to or higher than > * given priority. > @@ -116,7 +122,14 @@ lxc_log_priority_is_enabled(const struct > lxc_log_category* category, > category->parent) > category = category->parent; > > - return priority >= category->priority; > + int cmp_prio = category->priority; > +#ifndef NO_LXC_CONF > + if (!lxc_log_use_global_fd && current_config && > + current_config->loglevel != LXC_LOG_PRIORITY_NOTSET) > + cmp_prio = current_config->loglevel; > +#endif > + > + return priority >= cmp_prio; > } > > /* > @@ -294,18 +307,14 @@ ATTR_UNUSED static inline void LXC_##PRIORITY(struct > lxc_log_locinfo* locinfo, \ > ERROR("%s - " format, strerror(errno), ##__VA_ARGS__); \ > } while (0) > > -#ifdef HAVE_TLS > -extern __thread int lxc_log_fd; > -#else > extern int lxc_log_fd; > -#endif > > extern int lxc_log_init(const char *name, const char *file, > const char *priority, const char *prefix, int quiet, > const char *lxcpath); > > -extern int lxc_log_set_file(const char *fname); > -extern int lxc_log_set_level(int level); > +extern int lxc_log_set_file(int *fd, const char *fname); > +extern int lxc_log_set_level(int *dest, int level); > extern void lxc_log_set_prefix(const char *prefix); > extern const char *lxc_log_get_file(void); > extern int lxc_log_get_level(void); > diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c > index e2586de..1fae6d9 100644 > --- a/src/lxc/lxccontainer.c > +++ b/src/lxc/lxccontainer.c > @@ -91,6 +91,15 @@ return -1; > > lxc_log_define(lxc_container, lxc); > > +static bool do_lxcapi_destroy(struct lxc_container *c); > +static const char *lxcapi_get_config_path(struct lxc_container *c); > +#define do_lxcapi_get_config_path(c) lxcapi_get_config_path(c) > +static bool do_lxcapi_set_config_item(struct lxc_container *c, const char > *key, const char *v); > +static bool container_destroy(struct lxc_container *c); > +static bool get_snappath_dir(struct lxc_container *c, char *snappath); > +static bool lxcapi_snapshot_destroy_all(struct lxc_container *c); > +static bool do_lxcapi_save_config(struct lxc_container *c, const char > *alt_file); > + > static bool config_file_exists(const char *lxcpath, const char *cname) > { > /* $lxcpath + '/' + $cname + '/config' + \0 */ > @@ -307,7 +316,7 @@ int lxc_container_put(struct lxc_container *c) > return 0; > } > > -static bool lxcapi_is_defined(struct lxc_container *c) > +static bool do_lxcapi_is_defined(struct lxc_container *c) > { > struct stat statbuf; > bool ret = false; > @@ -330,7 +339,49 @@ out: > return ret; > } > > -static const char *lxcapi_state(struct lxc_container *c) > +#define WRAP_API(rettype, fnname) \ > +static rettype fnname(struct lxc_container *c) > \ > +{ \ > + rettype ret; \ > + current_config = c ? c->lxc_conf : NULL; \ > + ret = do_##fnname(c); \ > + current_config = NULL; \ > + return ret; \ > +} > + > +#define WRAP_API_1(rettype, fnname, t1) > \ > +static rettype fnname(struct lxc_container *c, t1 a1) > \ > +{ \ > + rettype ret; \ > + current_config = c ? c->lxc_conf : NULL; \ > + ret = do_##fnname(c, a1); \ > + current_config = NULL; \ > + return ret; \ > +} > + > +#define WRAP_API_2(rettype, fnname, t1, t2) \ > +static rettype fnname(struct lxc_container *c, t1 a1, t2 a2) \ > +{ \ > + rettype ret; \ > + current_config = c ? c->lxc_conf : NULL; \ > + ret = do_##fnname(c, a1, a2); \ > + current_config = NULL; \ > + return ret; \ > +} > + > +#define WRAP_API_3(rettype, fnname, t1, t2, t3) > \ > +static rettype fnname(struct lxc_container *c, t1 a1, t2 a2, t3 a3) \ > +{ \ > + rettype ret; \ > + current_config = c ? c->lxc_conf : NULL; \ > + ret = do_##fnname(c, a1, a2, a3); \ > + current_config = NULL; \ > + return ret; \ > +} > + > +WRAP_API(bool, lxcapi_is_defined) > + > +static const char *do_lxcapi_state(struct lxc_container *c) > { > lxc_state_t s; > > @@ -340,6 +391,8 @@ static const char *lxcapi_state(struct lxc_container *c) > return lxc_state2str(s); > } > > +WRAP_API(const char *, lxcapi_state) > + > static bool is_stopped(struct lxc_container *c) > { > lxc_state_t s; > @@ -347,19 +400,21 @@ static bool is_stopped(struct lxc_container *c) > return (s == STOPPED); > } > > -static bool lxcapi_is_running(struct lxc_container *c) > +static bool do_lxcapi_is_running(struct lxc_container *c) > { > const char *s; > > if (!c) > return false; > - s = lxcapi_state(c); > + s = do_lxcapi_state(c); > if (!s || strcmp(s, "STOPPED") == 0) > return false; > return true; > } > > -static bool lxcapi_freeze(struct lxc_container *c) > +WRAP_API(bool, lxcapi_is_running) > + > +static bool do_lxcapi_freeze(struct lxc_container *c) > { > int ret; > if (!c) > @@ -371,7 +426,9 @@ static bool lxcapi_freeze(struct lxc_container *c) > return true; > } > > -static bool lxcapi_unfreeze(struct lxc_container *c) > +WRAP_API(bool, lxcapi_freeze) > + > +static bool do_lxcapi_unfreeze(struct lxc_container *c) > { > int ret; > if (!c) > @@ -383,7 +440,9 @@ static bool lxcapi_unfreeze(struct lxc_container *c) > return true; > } > > -static int lxcapi_console_getfd(struct lxc_container *c, int *ttynum, int > *masterfd) > +WRAP_API(bool, lxcapi_unfreeze) > + > +static int do_lxcapi_console_getfd(struct lxc_container *c, int *ttynum, int > *masterfd) > { > int ttyfd; > if (!c) > @@ -393,13 +452,23 @@ static int lxcapi_console_getfd(struct lxc_container > *c, int *ttynum, int *maste > return ttyfd; > } > > +WRAP_API_2(int, lxcapi_console_getfd, int *, int *) > + > static int lxcapi_console(struct lxc_container *c, int ttynum, int stdinfd, > int stdoutfd, int stderrfd, int escape) > { > - return lxc_console(c, ttynum, stdinfd, stdoutfd, stderrfd, escape); > + int ret; > + > + if (!c) > + return -1; > + > + current_config = c->lxc_conf; > + ret = lxc_console(c, ttynum, stdinfd, stdoutfd, stderrfd, escape); > + current_config = NULL; > + return ret; > } > > -static pid_t lxcapi_init_pid(struct lxc_container *c) > +static pid_t do_lxcapi_init_pid(struct lxc_container *c) > { > if (!c) > return -1; > @@ -407,6 +476,8 @@ static pid_t lxcapi_init_pid(struct lxc_container *c) > return lxc_cmd_get_init_pid(c->name, c->config_path); > } > > +WRAP_API(pid_t, lxcapi_init_pid) > + > static bool load_config_locked(struct lxc_container *c, const char *fname) > { > if (!c->lxc_conf) > @@ -418,7 +489,7 @@ static bool load_config_locked(struct lxc_container *c, > const char *fname) > return true; > } > > -static bool lxcapi_load_config(struct lxc_container *c, const char *alt_file) > +static bool do_lxcapi_load_config(struct lxc_container *c, const char > *alt_file) > { > bool ret = false, need_disklock = false; > int lret; > @@ -455,7 +526,9 @@ static bool lxcapi_load_config(struct lxc_container *c, > const char *alt_file) > return ret; > } > > -static bool lxcapi_want_daemonize(struct lxc_container *c, bool state) > +WRAP_API_1(bool, lxcapi_load_config, const char *) > + > +static bool do_lxcapi_want_daemonize(struct lxc_container *c, bool state) > { > if (!c || !c->lxc_conf) > return false; > @@ -468,7 +541,9 @@ static bool lxcapi_want_daemonize(struct lxc_container > *c, bool state) > return true; > } > > -static bool lxcapi_want_close_all_fds(struct lxc_container *c, bool state) > +WRAP_API_1(bool, lxcapi_want_daemonize, bool) > + > +static bool do_lxcapi_want_close_all_fds(struct lxc_container *c, bool state) > { > if (!c || !c->lxc_conf) > return false; > @@ -481,7 +556,9 @@ static bool lxcapi_want_close_all_fds(struct > lxc_container *c, bool state) > return true; > } > > -static bool lxcapi_wait(struct lxc_container *c, const char *state, int > timeout) > +WRAP_API_1(bool, lxcapi_want_close_all_fds, bool) > + > +static bool do_lxcapi_wait(struct lxc_container *c, const char *state, int > timeout) > { > int ret; > > @@ -492,8 +569,9 @@ static bool lxcapi_wait(struct lxc_container *c, const > char *state, int timeout) > return ret == 0; > } > > +WRAP_API_2(bool, lxcapi_wait, const char *, int) > > -static bool wait_on_daemonized_start(struct lxc_container *c, int pid) > +static bool do_wait_on_daemonized_start(struct lxc_container *c, int pid) > { > /* we'll probably want to make this timeout configurable? */ > int timeout = 5, ret, status; > @@ -505,9 +583,11 @@ static bool wait_on_daemonized_start(struct > lxc_container *c, int pid) > ret = waitpid(pid, &status, 0); > if (ret == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) > DEBUG("failed waiting for first dual-fork child"); > - return lxcapi_wait(c, "RUNNING", timeout); > + return do_lxcapi_wait(c, "RUNNING", timeout); > } > > +WRAP_API_1(bool, wait_on_daemonized_start, int) > + > static bool am_single_threaded(void) > { > struct dirent dirent, *direntp; > @@ -540,7 +620,7 @@ static bool am_single_threaded(void) > * I can't decide if it'd be more convenient for callers if we accept '...', > * or a null-terminated array (i.e. execl vs execv) > */ > -static bool lxcapi_start(struct lxc_container *c, int useinit, char * const > argv[]) > +static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * > const argv[]) > { > int ret; > struct lxc_conf *conf; > @@ -565,7 +645,7 @@ static bool lxcapi_start(struct lxc_container *c, int > useinit, char * const argv > } > if (ret == 2) { > ERROR("Error: %s creation was not completed", c->name); > - c->destroy(c); > + do_lxcapi_destroy(c); > return false; > } else if (ret == 1) { > ERROR("Error: creation of %s is ongoing", c->name); > @@ -708,6 +788,15 @@ out: > return (ret == 0 ? true : false); > } > > +static bool lxcapi_start(struct lxc_container *c, int useinit, char * const > argv[]) > +{ > + bool ret; > + current_config = c ? c->lxc_conf : NULL; > + ret = do_lxcapi_start(c, useinit, argv); > + current_config = NULL; > + return ret; > +} > + > /* > * note there MUST be an ending NULL > */ > @@ -721,6 +810,8 @@ static bool lxcapi_startl(struct lxc_container *c, int > useinit, ...) > if (!c) > return false; > > + current_config = c->lxc_conf; > + > va_start(ap, useinit); > inargs = lxc_va_arg_list_to_argv(ap, 0, 1); > va_end(ap); > @@ -731,7 +822,7 @@ static bool lxcapi_startl(struct lxc_container *c, int > useinit, ...) > } > > /* pass NULL if no arguments were supplied */ > - bret = lxcapi_start(c, useinit, *inargs ? inargs : NULL); > + bret = do_lxcapi_start(c, useinit, *inargs ? inargs : NULL); > > out: > if (inargs) { > @@ -741,10 +832,11 @@ out: > free(inargs); > } > > + current_config = NULL; > return bret; > } > > -static bool lxcapi_stop(struct lxc_container *c) > +static bool do_lxcapi_stop(struct lxc_container *c) > { > int ret; > > @@ -756,6 +848,8 @@ static bool lxcapi_stop(struct lxc_container *c) > return ret == 0; > } > > +WRAP_API(bool, lxcapi_stop) > + > static int do_create_container_dir(const char *path, struct lxc_conf *conf) > { > int ret = -1, lasterr; > @@ -803,9 +897,6 @@ static bool create_container_dir(struct lxc_container *c) > return ret == 0; > } > > -static const char *lxcapi_get_config_path(struct lxc_container *c); > -static bool lxcapi_set_config_item(struct lxc_container *c, const char *key, > const char *v); > - > /* > * do_bdev_create: thin wrapper around bdev_create(). Like bdev_create(), > * it returns a mounted bdev on success, NULL on error. > @@ -825,7 +916,7 @@ static struct bdev *do_bdev_create(struct lxc_container > *c, const char *type, > dest = alloca(len); > ret = snprintf(dest, len, "%s", rpath); > } else { > - const char *lxcpath = lxcapi_get_config_path(c); > + const char *lxcpath = do_lxcapi_get_config_path(c); > len = strlen(c->name) + strlen(lxcpath) + 9; > dest = alloca(len); > ret = snprintf(dest, len, "%s/%s/rootfs", lxcpath, c->name); > @@ -839,7 +930,7 @@ static struct bdev *do_bdev_create(struct lxc_container > *c, const char *type, > return NULL; > } > > - lxcapi_set_config_item(c, "lxc.rootfs", bdev->src); > + do_lxcapi_set_config_item(c, "lxc.rootfs", bdev->src); > > /* if we are not root, chown the rootfs dir to root in the > * target uidmap */ > @@ -1216,9 +1307,8 @@ static void lxcapi_clear_config(struct lxc_container *c) > } > } > > -static bool lxcapi_destroy(struct lxc_container *c); > -static bool container_destroy(struct lxc_container *c); > -static bool get_snappath_dir(struct lxc_container *c, char *snappath); > +#define do_lxcapi_clear_config(c) lxcapi_clear_config(c) > + > /* > * lxcapi_create: > * create a container with the given parameters. > @@ -1233,7 +1323,7 @@ static bool get_snappath_dir(struct lxc_container *c, > char *snappath); > * @argv: the arguments to pass to the template, terminated by NULL. If no > * arguments, you can just pass NULL. > */ > -static bool lxcapi_create(struct lxc_container *c, const char *t, > +static bool do_lxcapi_create(struct lxc_container *c, const char *t, > const char *bdevtype, struct bdev_specs *specs, int flags, > char *const argv[]) > { > @@ -1259,14 +1349,14 @@ static bool lxcapi_create(struct lxc_container *c, > const char *t, > * an existing container. Return an error, but do NOT delete the > * container. > */ > - if (lxcapi_is_defined(c) && c->lxc_conf && c->lxc_conf->rootfs.path && > + if (do_lxcapi_is_defined(c) && c->lxc_conf && c->lxc_conf->rootfs.path > && > access(c->lxc_conf->rootfs.path, F_OK) == 0 && tpath) { > ERROR("Container %s:%s already exists", c->config_path, > c->name); > goto free_tpath; > } > > if (!c->lxc_conf) { > - if (!c->load_config(c, > lxc_global_config_value("lxc.default_config"))) { > + if (!do_lxcapi_load_config(c, > lxc_global_config_value("lxc.default_config"))) { > ERROR("Error loading default configuration file %s", > lxc_global_config_value("lxc.default_config")); > goto free_tpath; > } > @@ -1286,7 +1376,7 @@ static bool lxcapi_create(struct lxc_container *c, > const char *t, > if (c->lxc_conf->rootfs.path && access(c->lxc_conf->rootfs.path, F_OK) > != 0) > /* rootfs passed into configuration, but does not exist: error > */ > goto out; > - if (lxcapi_is_defined(c) && c->lxc_conf->rootfs.path && !tpath) { > + if (do_lxcapi_is_defined(c) && c->lxc_conf->rootfs.path && !tpath) { > /* Rootfs already existed, user just wanted to save the > * loaded configuration */ > ret = true; > @@ -1322,7 +1412,7 @@ static bool lxcapi_create(struct lxc_container *c, > const char *t, > } > > /* save config file again to store the new rootfs location */ > - if (!c->save_config(c, NULL)) { > + if (!do_lxcapi_save_config(c, NULL)) { > ERROR("failed to save starting configuration for %s", > c->name); > // parent task won't see bdev in config so we delete it > bdev->ops->umount(bdev); > @@ -1345,7 +1435,7 @@ static bool lxcapi_create(struct lxc_container *c, > const char *t, > > // now clear out the lxc_conf we have, reload from the created > // container > - lxcapi_clear_config(c); > + do_lxcapi_clear_config(c); > > if (t) { > if (!prepend_lxc_header(c->configfile, tpath, argv)) { > @@ -1366,16 +1456,27 @@ free_tpath: > return ret; > } > > -static bool lxcapi_reboot(struct lxc_container *c) > +static bool lxcapi_create(struct lxc_container *c, const char *t, > + const char *bdevtype, struct bdev_specs *specs, int flags, > + char *const argv[]) > +{ > + bool ret; > + current_config = c ? c->lxc_conf : NULL; > + ret = do_lxcapi_create(c, t, bdevtype, specs, flags, argv); > + current_config = NULL; > + return ret; > +} > + > +static bool do_lxcapi_reboot(struct lxc_container *c) > { > pid_t pid; > int rebootsignal = SIGINT; > > if (!c) > return false; > - if (!c->is_running(c)) > + if (!do_lxcapi_is_running(c)) > return false; > - pid = c->init_pid(c); > + pid = do_lxcapi_init_pid(c); > if (pid <= 0) > return false; > if (c->lxc_conf && c->lxc_conf->rebootsignal) > @@ -1386,7 +1487,9 @@ static bool lxcapi_reboot(struct lxc_container *c) > > } > > -static bool lxcapi_shutdown(struct lxc_container *c, int timeout) > +WRAP_API(bool, lxcapi_reboot) > + > +static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout) > { > bool retv; > pid_t pid; > @@ -1395,18 +1498,20 @@ static bool lxcapi_shutdown(struct lxc_container *c, > int timeout) > if (!c) > return false; > > - if (!c->is_running(c)) > + if (!do_lxcapi_is_running(c)) > return true; > - pid = c->init_pid(c); > + pid = do_lxcapi_init_pid(c); > if (pid <= 0) > return true; > if (c->lxc_conf && c->lxc_conf->haltsignal) > haltsignal = c->lxc_conf->haltsignal; > kill(pid, haltsignal); > - retv = c->wait(c, "STOPPED", timeout); > + retv = do_lxcapi_wait(c, "STOPPED", timeout); > return retv; > } > > +WRAP_API_1(bool, lxcapi_shutdown, int) > + > static bool lxcapi_createl(struct lxc_container *c, const char *t, > const char *bdevtype, struct bdev_specs *specs, int flags, ...) > { > @@ -1417,6 +1522,8 @@ static bool lxcapi_createl(struct lxc_container *c, > const char *t, > if (!c) > return false; > > + current_config = c->lxc_conf; > + > /* > * since we're going to wait for create to finish, I don't think we > * need to get a copy of the arguments. > @@ -1429,10 +1536,11 @@ static bool lxcapi_createl(struct lxc_container *c, > const char *t, > goto out; > } > > - bret = c->create(c, t, bdevtype, specs, flags, args); > + bret = do_lxcapi_create(c, t, bdevtype, specs, flags, args); > > out: > free(args); > + current_config = NULL; > return bret; > } > > @@ -1450,7 +1558,7 @@ static void do_clear_unexp_config_line(struct lxc_conf > *conf, const char *key) > WARN("Error clearing configuration for %s", key); > } > > -static bool lxcapi_clear_config_item(struct lxc_container *c, const char > *key) > +static bool do_lxcapi_clear_config_item(struct lxc_container *c, const char > *key) > { > int ret; > > @@ -1465,9 +1573,11 @@ static bool lxcapi_clear_config_item(struct > lxc_container *c, const char *key) > return ret == 0; > } > > +WRAP_API_1(bool, lxcapi_clear_config_item, const char *) > + > static inline bool enter_net_ns(struct lxc_container *c) > { > - pid_t pid = c->init_pid(c); > + pid_t pid = do_lxcapi_init_pid(c); > > if ((geteuid() != 0 || (c->lxc_conf && > !lxc_list_empty(&c->lxc_conf->id_map))) && access("/proc/self/ns/user", F_OK) > == 0) { > if (!switch_to_ns(pid, "user")) > @@ -1547,7 +1657,7 @@ static bool remove_from_array(char ***names, char > *cname, int size) > return false; > } > > -static char** lxcapi_get_interfaces(struct lxc_container *c) > +static char ** do_lxcapi_get_interfaces(struct lxc_container *c) > { > pid_t pid; > int i, count = 0, pipefd[2]; > @@ -1634,7 +1744,9 @@ static char** lxcapi_get_interfaces(struct > lxc_container *c) > return interfaces; > } > > -static char** lxcapi_get_ips(struct lxc_container *c, const char* interface, > const char* family, int scope) > +WRAP_API(char **, lxcapi_get_interfaces) > + > +static char** do_lxcapi_get_ips(struct lxc_container *c, const char* > interface, const char* family, int scope) > { > pid_t pid; > int i, count = 0, pipefd[2]; > @@ -1751,7 +1863,9 @@ static char** lxcapi_get_ips(struct lxc_container *c, > const char* interface, con > return addresses; > } > > -static int lxcapi_get_config_item(struct lxc_container *c, const char *key, > char *retv, int inlen) > +WRAP_API_3(char **, lxcapi_get_ips, const char *, const char *, int) > + > +static int do_lxcapi_get_config_item(struct lxc_container *c, const char > *key, char *retv, int inlen) > { > int ret; > > @@ -1764,7 +1878,9 @@ static int lxcapi_get_config_item(struct lxc_container > *c, const char *key, char > return ret; > } > > -static char* lxcapi_get_running_config_item(struct lxc_container *c, const > char *key) > +WRAP_API_3(int, lxcapi_get_config_item, const char *, char *, int) > + > +static char* do_lxcapi_get_running_config_item(struct lxc_container *c, > const char *key) > { > char *ret; > > @@ -1772,12 +1888,14 @@ static char* lxcapi_get_running_config_item(struct > lxc_container *c, const char > return NULL; > if (container_mem_lock(c)) > return NULL; > - ret = lxc_cmd_get_config_item(c->name, key, c->get_config_path(c)); > + ret = lxc_cmd_get_config_item(c->name, key, > do_lxcapi_get_config_path(c)); > container_mem_unlock(c); > return ret; > } > > -static int lxcapi_get_keys(struct lxc_container *c, const char *key, char > *retv, int inlen) > +WRAP_API_1(char *, lxcapi_get_running_config_item, const char *) > + > +static int do_lxcapi_get_keys(struct lxc_container *c, const char *key, char > *retv, int inlen) > { > if (!key) > return lxc_listconfigs(retv, inlen); > @@ -1797,7 +1915,9 @@ static int lxcapi_get_keys(struct lxc_container *c, > const char *key, char *retv, > return ret; > } > > -static bool lxcapi_save_config(struct lxc_container *c, const char *alt_file) > +WRAP_API_3(int, lxcapi_get_keys, const char *, char *, int) > + > +static bool do_lxcapi_save_config(struct lxc_container *c, const char > *alt_file) > { > FILE *fout; > bool ret = false, need_disklock = false; > @@ -1810,7 +1930,7 @@ static bool lxcapi_save_config(struct lxc_container *c, > const char *alt_file) > > // If we haven't yet loaded a config, load the stock config > if (!c->lxc_conf) { > - if (!c->load_config(c, > lxc_global_config_value("lxc.default_config"))) { > + if (!do_lxcapi_load_config(c, > lxc_global_config_value("lxc.default_config"))) { > ERROR("Error loading default configuration file %s > while saving %s", lxc_global_config_value("lxc.default_config"), c->name); > return false; > } > @@ -1850,6 +1970,8 @@ out: > return ret; > } > > +WRAP_API_1(bool, lxcapi_save_config, const char *) > + > static bool mod_rdep(struct lxc_container *c, bool inc) > { > char path[MAXPATHLEN]; > @@ -2038,7 +2160,7 @@ static bool container_destroy(struct lxc_container *c) > bool bret = false; > int ret; > > - if (!c || !lxcapi_is_defined(c)) > + if (!c || !do_lxcapi_is_defined(c)) > return false; > > if (container_disk_lock(c)) > @@ -2063,7 +2185,7 @@ static bool container_destroy(struct lxc_container *c) > > mod_all_rdeps(c, false); > > - const char *p1 = lxcapi_get_config_path(c); > + const char *p1 = do_lxcapi_get_config_path(c); > char *path = alloca(strlen(p1) + strlen(c->name) + 2); > sprintf(path, "%s/%s", p1, c->name); > if (am_unpriv()) > @@ -2081,7 +2203,7 @@ out: > return bret; > } > > -static bool lxcapi_destroy(struct lxc_container *c) > +static bool do_lxcapi_destroy(struct lxc_container *c) > { > if (!c || !lxcapi_is_defined(c)) > return false; > @@ -2098,9 +2220,9 @@ static bool lxcapi_destroy(struct lxc_container *c) > return container_destroy(c); > } > > -static bool lxcapi_snapshot_destroy_all(struct lxc_container *c); > +WRAP_API(bool, lxcapi_destroy) > > -static bool lxcapi_destroy_with_snapshots(struct lxc_container *c) > +static bool do_lxcapi_destroy_with_snapshots(struct lxc_container *c) > { > if (!c || !lxcapi_is_defined(c)) > return false; > @@ -2111,6 +2233,8 @@ static bool lxcapi_destroy_with_snapshots(struct > lxc_container *c) > return lxcapi_destroy(c); > } > > +WRAP_API(bool, lxcapi_destroy_with_snapshots) > + > static bool set_config_item_locked(struct lxc_container *c, const char *key, > const char *v) > { > struct lxc_config_t *config; > @@ -2127,7 +2251,7 @@ static bool set_config_item_locked(struct lxc_container > *c, const char *key, con > return do_append_unexp_config_line(c->lxc_conf, key, v); > } > > -static bool lxcapi_set_config_item(struct lxc_container *c, const char *key, > const char *v) > +static bool do_lxcapi_set_config_item(struct lxc_container *c, const char > *key, const char *v) > { > bool b = false; > > @@ -2143,6 +2267,8 @@ static bool lxcapi_set_config_item(struct lxc_container > *c, const char *key, con > return b; > } > > +WRAP_API_2(bool, lxcapi_set_config_item, const char *, const char *) > + > static char *lxcapi_config_file_name(struct lxc_container *c) > { > if (!c || !c->configfile) > @@ -2190,7 +2316,7 @@ static bool set_config_filename(struct lxc_container *c) > return true; > } > > -static bool lxcapi_set_config_path(struct lxc_container *c, const char *path) > +static bool do_lxcapi_set_config_path(struct lxc_container *c, const char > *path) > { > char *p; > bool b = false; > @@ -2228,8 +2354,9 @@ err: > return b; > } > > +WRAP_API_1(bool, lxcapi_set_config_path, const char *) > > -static bool lxcapi_set_cgroup_item(struct lxc_container *c, const char > *subsys, const char *value) > +static bool do_lxcapi_set_cgroup_item(struct lxc_container *c, const char > *subsys, const char *value) > { > int ret; > > @@ -2248,7 +2375,9 @@ static bool lxcapi_set_cgroup_item(struct lxc_container > *c, const char *subsys, > return ret == 0; > } > > -static int lxcapi_get_cgroup_item(struct lxc_container *c, const char > *subsys, char *retv, int inlen) > +WRAP_API_2(bool, lxcapi_set_cgroup_item, const char *, const char *) > + > +static int do_lxcapi_get_cgroup_item(struct lxc_container *c, const char > *subsys, char *retv, int inlen) > { > int ret; > > @@ -2267,6 +2396,8 @@ static int lxcapi_get_cgroup_item(struct lxc_container > *c, const char *subsys, c > return ret; > } > > +WRAP_API_3(int, lxcapi_get_cgroup_item, const char *, char *, int) > + > const char *lxc_get_global_config_item(const char *key) > { > return lxc_global_config_value(key); > @@ -2383,7 +2514,7 @@ static int copyhooks(struct lxc_container *oldc, struct > lxc_container *c) > ERROR("Error saving new hooks in clone"); > return -1; > } > - c->save_config(c, NULL); > + do_lxcapi_save_config(c, NULL); > return 0; > } > > @@ -2655,7 +2786,7 @@ static int create_file_dirname(char *path, struct > lxc_conf *conf) > return ret; > } > > -static struct lxc_container *lxcapi_clone(struct lxc_container *c, const > char *newname, > +static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const > char *newname, > const char *lxcpath, int flags, > const char *bdevtype, const char *bdevdata, uint64_t newsize, > char **hookargs) > @@ -2668,7 +2799,7 @@ static struct lxc_container *lxcapi_clone(struct > lxc_container *c, const char *n > FILE *fout; > pid_t pid; > > - if (!c || !c->is_defined(c)) > + if (!c || !do_lxcapi_is_defined(c)) > return NULL; > > if (container_mem_lock(c)) > @@ -2683,7 +2814,7 @@ static struct lxc_container *lxcapi_clone(struct > lxc_container *c, const char *n > if (!newname) > newname = c->name; > if (!lxcpath) > - lxcpath = c->get_config_path(c); > + lxcpath = do_lxcapi_get_config_path(c); > ret = snprintf(newpath, MAXPATHLEN, "%s/%s/config", lxcpath, newname); > if (ret < 0 || ret >= MAXPATHLEN) { > SYSERROR("clone: failed making config pathname"); > @@ -2812,7 +2943,19 @@ out: > return NULL; > } > > -static bool lxcapi_rename(struct lxc_container *c, const char *newname) > +static struct lxc_container *lxcapi_clone(struct lxc_container *c, const > char *newname, > + const char *lxcpath, int flags, > + const char *bdevtype, const char *bdevdata, uint64_t newsize, > + char **hookargs) > +{ > + struct lxc_container * ret; > + current_config = c ? c->lxc_conf : NULL; > + ret = do_lxcapi_clone(c, newname, lxcpath, flags, bdevtype, bdevdata, > newsize, hookargs); > + current_config = NULL; > + return ret; > +} > + > +static bool do_lxcapi_rename(struct lxc_container *c, const char *newname) > { > struct bdev *bdev; > struct lxc_container *newc; > @@ -2847,15 +2990,23 @@ static bool lxcapi_rename(struct lxc_container *c, > const char *newname) > return true; > } > > +WRAP_API_1(bool, lxcapi_rename, const char *) > + > static int lxcapi_attach(struct lxc_container *c, lxc_attach_exec_t > exec_function, void *exec_payload, lxc_attach_options_t *options, pid_t > *attached_process) > { > + int ret; > + > if (!c) > return -1; > > - return lxc_attach(c->name, c->config_path, exec_function, exec_payload, > options, attached_process); > + current_config = c->lxc_conf; > + > + ret = lxc_attach(c->name, c->config_path, exec_function, exec_payload, > options, attached_process); > + current_config = NULL; > + return ret; > } > > -static int lxcapi_attach_run_wait(struct lxc_container *c, > lxc_attach_options_t *options, const char *program, const char * const argv[]) > +static int do_lxcapi_attach_run_wait(struct lxc_container *c, > lxc_attach_options_t *options, const char *program, const char * const argv[]) > { > lxc_attach_command_t command; > pid_t pid; > @@ -2874,6 +3025,15 @@ static int lxcapi_attach_run_wait(struct lxc_container > *c, lxc_attach_options_t > return lxc_wait_for_pid_status(pid); > } > > +static int lxcapi_attach_run_wait(struct lxc_container *c, > lxc_attach_options_t *options, const char *program, const char * const argv[]) > +{ > + int ret; > + current_config = c ? c->lxc_conf : NULL; > + ret = do_lxcapi_attach_run_wait(c, options, program, argv); > + current_config = NULL; > + return ret; > +} > + > static int get_next_index(const char *lxcpath, char *cname) > { > char *fname; > @@ -2917,7 +3077,7 @@ static bool get_snappath_dir(struct lxc_container *c, > char *snappath) > return true; > } > > -static int lxcapi_snapshot(struct lxc_container *c, const char *commentfile) > +static int do_lxcapi_snapshot(struct lxc_container *c, const char > *commentfile) > { > int i, flags, ret; > struct lxc_container *c2; > @@ -2959,7 +3119,7 @@ static int lxcapi_snapshot(struct lxc_container *c, > const char *commentfile) > ERROR("and keep the original container pristine."); > flags &= ~LXC_CLONE_SNAPSHOT | LXC_CLONE_MAYBE_SNAPSHOT; > } > - c2 = c->clone(c, newname, snappath, flags, NULL, NULL, 0, NULL); > + c2 = do_lxcapi_clone(c, newname, snappath, flags, NULL, NULL, 0, NULL); > if (!c2) { > ERROR("clone of %s:%s failed", c->config_path, c->name); > return -1; > @@ -3007,6 +3167,8 @@ static int lxcapi_snapshot(struct lxc_container *c, > const char *commentfile) > return i; > } > > +WRAP_API_1(int, lxcapi_snapshot, const char *) > + > static void lxcsnap_free(struct lxc_snapshot *s) > { > free(s->name); > @@ -3061,7 +3223,7 @@ static char *get_timestamp(char* snappath, char *name) > return s; > } > > -static int lxcapi_snapshot_list(struct lxc_container *c, struct lxc_snapshot > **ret_snaps) > +static int do_lxcapi_snapshot_list(struct lxc_container *c, struct > lxc_snapshot **ret_snaps) > { > char snappath[MAXPATHLEN], path2[MAXPATHLEN]; > int count = 0, ret; > @@ -3137,7 +3299,9 @@ out_free: > return -1; > } > > -static bool lxcapi_snapshot_restore(struct lxc_container *c, const char > *snapname, const char *newname) > +WRAP_API_1(int, lxcapi_snapshot_list, struct lxc_snapshot **) > + > +static bool do_lxcapi_snapshot_restore(struct lxc_container *c, const char > *snapname, const char *newname) > { > char clonelxcpath[MAXPATHLEN]; > int flags = 0; > @@ -3198,6 +3362,8 @@ static bool lxcapi_snapshot_restore(struct > lxc_container *c, const char *snapnam > return b; > } > > +WRAP_API_2(bool, lxcapi_snapshot_restore, const char *, const char *) > + > static bool do_snapshot_destroy(const char *snapname, const char > *clonelxcpath) > { > struct lxc_container *snap = NULL; > @@ -3209,7 +3375,7 @@ static bool do_snapshot_destroy(const char *snapname, > const char *clonelxcpath) > goto err; > } > > - if (!lxcapi_destroy(snap)) { > + if (!do_lxcapi_destroy(snap)) { > ERROR("Could not destroy snapshot %s", snapname); > goto err; > } > @@ -3253,7 +3419,7 @@ static bool remove_all_snapshots(const char *path) > return bret; > } > > -static bool lxcapi_snapshot_destroy(struct lxc_container *c, const char > *snapname) > +static bool do_lxcapi_snapshot_destroy(struct lxc_container *c, const char > *snapname) > { > char clonelxcpath[MAXPATHLEN]; > > @@ -3266,7 +3432,9 @@ static bool lxcapi_snapshot_destroy(struct > lxc_container *c, const char *snapnam > return do_snapshot_destroy(snapname, clonelxcpath); > } > > -static bool lxcapi_snapshot_destroy_all(struct lxc_container *c) > +WRAP_API_1(bool, lxcapi_snapshot_destroy, const char *) > + > +static bool do_lxcapi_snapshot_destroy_all(struct lxc_container *c) > { > char clonelxcpath[MAXPATHLEN]; > > @@ -3279,11 +3447,15 @@ static bool lxcapi_snapshot_destroy_all(struct > lxc_container *c) > return remove_all_snapshots(clonelxcpath); > } > > -static bool lxcapi_may_control(struct lxc_container *c) > +WRAP_API(bool, lxcapi_snapshot_destroy_all) > + > +static bool do_lxcapi_may_control(struct lxc_container *c) > { > return lxc_try_cmd(c->name, c->config_path) == 0; > } > > +WRAP_API(bool, lxcapi_may_control) > + > static bool do_add_remove_node(pid_t init_pid, const char *path, bool add, > struct stat *st) > { > @@ -3347,7 +3519,7 @@ static bool add_remove_device_node(struct lxc_container > *c, const char *src_path > const char *p; > > /* make sure container is running */ > - if (!c->is_running(c)) { > + if (!do_lxcapi_is_running(c)) { > ERROR("container is not running"); > return false; > } > @@ -3371,17 +3543,17 @@ static bool add_remove_device_node(struct > lxc_container *c, const char *src_path > if (ret < 0 || ret >= MAX_BUFFER) > return false; > > - if (!do_add_remove_node(c->init_pid(c), p, add, &st)) > + if (!do_add_remove_node(do_lxcapi_init_pid(c), p, add, &st)) > return false; > > /* add or remove device to/from cgroup access list */ > if (add) { > - if (!c->set_cgroup_item(c, "devices.allow", value)) { > + if (!do_lxcapi_set_cgroup_item(c, "devices.allow", value)) { > ERROR("set_cgroup_item failed while adding the device > node"); > return false; > } > } else { > - if (!c->set_cgroup_item(c, "devices.deny", value)) { > + if (!do_lxcapi_set_cgroup_item(c, "devices.deny", value)) { > ERROR("set_cgroup_item failed while removing the device > node"); > return false; > } > @@ -3390,7 +3562,7 @@ static bool add_remove_device_node(struct lxc_container > *c, const char *src_path > return true; > } > > -static bool lxcapi_add_device_node(struct lxc_container *c, const char > *src_path, const char *dest_path) > +static bool do_lxcapi_add_device_node(struct lxc_container *c, const char > *src_path, const char *dest_path) > { > if (am_unpriv()) { > ERROR(NOT_SUPPORTED_ERROR, __FUNCTION__); > @@ -3399,7 +3571,9 @@ static bool lxcapi_add_device_node(struct lxc_container > *c, const char *src_path > return add_remove_device_node(c, src_path, dest_path, true); > } > > -static bool lxcapi_remove_device_node(struct lxc_container *c, const char > *src_path, const char *dest_path) > +WRAP_API_2(bool, lxcapi_add_device_node, const char *, const char *) > + > +static bool do_lxcapi_remove_device_node(struct lxc_container *c, const char > *src_path, const char *dest_path) > { > if (am_unpriv()) { > ERROR(NOT_SUPPORTED_ERROR, __FUNCTION__); > @@ -3408,7 +3582,9 @@ static bool lxcapi_remove_device_node(struct > lxc_container *c, const char *src_p > return add_remove_device_node(c, src_path, dest_path, false); > } > > -static bool lxcapi_attach_interface(struct lxc_container *c, const char > *ifname, > +WRAP_API_2(bool, lxcapi_remove_device_node, const char *, const char *) > + > +static bool do_lxcapi_attach_interface(struct lxc_container *c, const char > *ifname, > const char *dst_ifname) > { > int ret = 0; > @@ -3431,7 +3607,7 @@ static bool lxcapi_attach_interface(struct > lxc_container *c, const char *ifname, > goto err; > } > > - ret = lxc_netdev_move_by_name(ifname, c->init_pid(c), dst_ifname); > + ret = lxc_netdev_move_by_name(ifname, do_lxcapi_init_pid(c), > dst_ifname); > if (ret) > goto err; > > @@ -3441,7 +3617,9 @@ err: > return false; > } > > -static bool lxcapi_detach_interface(struct lxc_container *c, const char > *ifname, > +WRAP_API_2(bool, lxcapi_attach_interface, const char *, const char *) > + > +static bool do_lxcapi_detach_interface(struct lxc_container *c, const char > *ifname, > const char *dst_ifname) > { > pid_t pid, pid_outside; > @@ -3496,6 +3674,8 @@ static bool lxcapi_detach_interface(struct > lxc_container *c, const char *ifname, > return true; > } > > +WRAP_API_2(bool, lxcapi_detach_interface, const char *, const char *) > + > struct criu_opts { > /* The type of criu invocation, one of "dump" or "restore" */ > char *action; > @@ -3857,7 +4037,7 @@ out: > return true; > } > > -static bool lxcapi_checkpoint(struct lxc_container *c, char *directory, bool > stop, bool verbose) > +static bool do_lxcapi_checkpoint(struct lxc_container *c, char *directory, > bool stop, bool verbose) > { > pid_t pid; > int status; > @@ -3902,6 +4082,8 @@ static bool lxcapi_checkpoint(struct lxc_container *c, > char *directory, bool sto > } > } > > +WRAP_API_3(bool, lxcapi_checkpoint, char *, bool, bool) > + > static bool restore_net_info(struct lxc_container *c) > { > struct lxc_list *it; > @@ -4080,7 +4262,7 @@ out: > exit(1); > } > > -static bool lxcapi_restore(struct lxc_container *c, char *directory, bool > verbose) > +static bool do_lxcapi_restore(struct lxc_container *c, char *directory, bool > verbose) > { > pid_t pid; > int status, nread; > @@ -4134,6 +4316,8 @@ err_wait: > return false; > } > > +WRAP_API_2(bool, lxcapi_restore, char *, bool) > + > static int lxcapi_attach_run_waitl(struct lxc_container *c, > lxc_attach_options_t *options, const char *program, const char *arg, ...) > { > va_list ap; > @@ -4143,18 +4327,23 @@ static int lxcapi_attach_run_waitl(struct > lxc_container *c, lxc_attach_options_t > if (!c) > return -1; > > + current_config = c->lxc_conf; > + > va_start(ap, arg); > argv = lxc_va_arg_list_to_argv_const(ap, 1); > va_end(ap); > > if (!argv) { > ERROR("Memory allocation error."); > - return -1; > + ret = -1; > + goto out; > } > argv[0] = arg; > > - ret = lxcapi_attach_run_wait(c, options, program, (const char * const > *)argv); > + ret = do_lxcapi_attach_run_wait(c, options, program, (const char * > const *)argv); > free((void*)argv); > +out: > + current_config = NULL; > return ret; > } > > @@ -4271,12 +4460,6 @@ struct lxc_container *lxc_container_new(const char > *name, const char *configpath > c->checkpoint = lxcapi_checkpoint; > c->restore = lxcapi_restore; > > - /* we'll allow the caller to update these later */ > - if (lxc_log_init(NULL, "none", NULL, "lxc_container", 0, > c->config_path)) { > - fprintf(stderr, "failed to open log\n"); > - goto err; > - } > - > return c; > > err: > @@ -4350,7 +4533,7 @@ int list_defined_containers(const char *lxcpath, char > ***names, struct lxc_conta > goto free_bad; > continue; > } > - if (!lxcapi_is_defined(c)) { > + if (!do_lxcapi_is_defined(c)) { > INFO("Container %s:%s has a config but is not defined", > lxcpath, direntp->d_name); > if (names) > diff --git a/src/lxc/start.c b/src/lxc/start.c > index d615375..0f70591 100644 > --- a/src/lxc/start.c > +++ b/src/lxc/start.c > @@ -212,6 +212,9 @@ restart: > if (fd == fddir || fd == lxc_log_fd || fd == fd_to_ignore) > continue; > > + if (current_config && fd == current_config->logfd) > + continue; > + > if (match_fd(fd)) > continue; > > -- > 1.9.1 > > _______________________________________________ > lxc-devel mailing list > [email protected] > http://lists.linuxcontainers.org/listinfo/lxc-devel -- Stéphane Graber Ubuntu developer http://www.ubuntu.com
signature.asc
Description: Digital signature
_______________________________________________ lxc-devel mailing list [email protected] http://lists.linuxcontainers.org/listinfo/lxc-devel
