[lxc-devel] [PATCH RFC] Allow a few basic limits to be set at creation / runtime

Serge Hallyn serge.hallyn at ubuntu.com
Wed May 28 15:58:07 UTC 2014


Quoting Dwight Engen (dwight.engen at oracle.com):
> On Wed, 28 May 2014 14:51:55 +0000
> Serge Hallyn <serge.hallyn at ubuntu.com> wrote:
> 
> > Quoting Dwight Engen (dwight.engen at oracle.com):
> > > Currently, a user has to read kernel/Documentation/cgroups/* to
> > > know what is available and then apply these using lxc-cgroups to
> > > set runtime limits, or hand edit the configuration file after
> > > creating a container to set them permanently.
> > > 
> > > This change covers the most common use cases (cpu, memory) by
> > > allowing the user to specify them to lxc-create, and introduces a
> > > new command lxc-ctl which allows setting the limits at run-time
> > > and/or saving them to the containers' config file with the --save
> > > option. This functionality is analogous to that found in vzctl, or
> > > Solaris zonecfg.
> > > 
> > > Introduce config_cgroup_find to find an already set cgroup item, and
> > > use it in config_cgroup() to replace a value instead of appending
> > > another entry. This means that (in for example lxc-clone) only the
> > > last duplicate entry will now be written out.
> > > 
> > > Signed-off-by: Dwight Engen <dwight.engen at oracle.com>
> > 
> > would lxc-cgctl or lxc-limit be a better name, or do you intend to
> > generalize it to other container controls later?
> 
> I'm open to whatever name we feel is appropriate. I called it lxc-ctl
> to leave it open in case we wanted to extend it in the future and also
> since it might be more discoverable to users of vzctl.
> 
> Since you acked it below, I'll take it that we're okay with the idea in

Yup, and I'm also ok with the name.  Not sure whether Stéphane will
have objections, but I think it's true that most people are currently
not using cgroups with containers much for lack of something like
this.

> general, and I'll write up a man page for the new command once we
> settle on a name.
> 
> > Acked-by: Serge E. Hallyn <serge.hallyn at ubuntu.com>
> > 
> > > ---
> > >  .gitignore           |   1 +
> > >  src/lxc/Makefile.am  |   2 +
> > >  src/lxc/arguments.h  |  10 ++-
> > >  src/lxc/confile.c    | 175
> > > ++++++++++++++++++++++++++++++++++++++++++---------
> > > src/lxc/confile.h    |  18 ++++++ src/lxc/lxc_create.c |  19 +++++-
> > >  src/lxc/lxc_ctl.c    | 133 +++++++++++++++++++++++++++++++++++++++
> > >  7 files changed, 326 insertions(+), 32 deletions(-)
> > >  create mode 100644 src/lxc/lxc_ctl.c
> > > 
> > > diff --git a/.gitignore b/.gitignore
> > > index 8145f81..b90a0e2 100644
> > > --- a/.gitignore
> > > +++ b/.gitignore
> > > @@ -52,6 +52,7 @@ src/lxc/lxc-clone
> > >  src/lxc/lxc-console
> > >  src/lxc/lxc-config
> > >  src/lxc/lxc-create
> > > +src/lxc/lxc-ctl
> > >  src/lxc/lxc-destroy
> > >  src/lxc/lxc-execute
> > >  src/lxc/lxc-freeze
> > > diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
> > > index ab8a46e..d48ebf6 100644
> > > --- a/src/lxc/Makefile.am
> > > +++ b/src/lxc/Makefile.am
> > > @@ -186,6 +186,7 @@ bin_PROGRAMS = \
> > >  	lxc-config \
> > >  	lxc-console \
> > >  	lxc-create \
> > > +	lxc-ctl \
> > >  	lxc-destroy \
> > >  	lxc-execute \
> > >  	lxc-freeze \
> > > @@ -229,6 +230,7 @@ lxc_unfreeze_SOURCES = lxc_unfreeze.c
> > >  lxc_unshare_SOURCES = lxc_unshare.c
> > >  lxc_wait_SOURCES = lxc_wait.c
> > >  lxc_create_SOURCES = lxc_create.c
> > > +lxc_ctl_SOURCES = lxc_ctl.c
> > >  lxc_snapshot_SOURCES = lxc_snapshot.c
> > >  lxc_usernsexec_SOURCES = lxc_usernsexec.c
> > >  lxc_user_nic_SOURCES = lxc_user_nic.c network.c network.h
> > > diff --git a/src/lxc/arguments.h b/src/lxc/arguments.h
> > > index cc85f86..0e963dd 100644
> > > --- a/src/lxc/arguments.h
> > > +++ b/src/lxc/arguments.h
> > > @@ -88,6 +88,9 @@ struct lxc_arguments {
> > >  	char *lvname, *vgname, *thinpool;
> > >  	char *zfsroot, *lowerdir, *dir;
> > >  
> > > +	/* lxc-create/lxc-ctl */
> > > +	char *mem, *cpulimit, *cpuset;
> > > +
> > >  	/* auto-start */
> > >  	int all;
> > >  	int ignore_auto;
> > > @@ -114,8 +117,11 @@ struct lxc_arguments {
> > >  	{0, 0, 0, 0}
> > >  
> > >  /* option keys for long only options */
> > > -#define	OPT_USAGE 0x1000
> > > -#define	OPT_VERSION OPT_USAGE-1
> > > +#define	OPT_USAGE	0x1000
> > > +#define	OPT_VERSION	OPT_USAGE-1
> > > +#define OPT_MEM		OPT_USAGE-2
> > > +#define OPT_CPULIMIT	OPT_USAGE-3
> > > +#define OPT_CPUSET	OPT_USAGE-4
> > >  
> > >  extern int lxc_arguments_parse(struct lxc_arguments *args,
> > >  			       int argc, char *const argv[]);
> > > diff --git a/src/lxc/confile.c b/src/lxc/confile.c
> > > index ac05b75..d65789e 100644
> > > --- a/src/lxc/confile.c
> > > +++ b/src/lxc/confile.c
> > > @@ -37,6 +37,7 @@
> > >  #include <netinet/in.h>
> > >  #include <net/if.h>
> > >  
> > > +#include "arguments.h"
> > >  #include "parse.h"
> > >  #include "config.h"
> > >  #include "confile.h"
> > > @@ -45,6 +46,7 @@
> > >  #include "conf.h"
> > >  #include "network.h"
> > >  #include "lxcseccomp.h"
> > > +#include "lxccontainer.h"
> > >  
> > >  #if HAVE_SYS_PERSONALITY_H
> > >  #include <sys/personality.h>
> > > @@ -1212,13 +1214,27 @@ static int config_stopsignal(const char
> > > *key, const char *value, return 0;
> > >  }
> > >  
> > > +static struct lxc_list *config_cgroup_find(struct lxc_conf
> > > *lxc_conf,
> > > +					   const char *subkey)
> > > +{
> > > +	struct lxc_list *it;
> > > +
> > > +	lxc_list_for_each(it, &lxc_conf->cgroup) {
> > > +		struct lxc_cgroup *cg = it->elem;
> > > +		if (strcmp(cg->subsystem, subkey) == 0)
> > > +			return it;
> > > +	}
> > > +	return NULL;
> > > +}
> > > +
> > >  static int config_cgroup(const char *key, const char *value,
> > >  			 struct lxc_conf *lxc_conf)
> > >  {
> > >  	char *token = "lxc.cgroup.";
> > > -	char *subkey;
> > > +	char *subkey, *subsystem, *val;
> > >  	struct lxc_list *cglist = NULL;
> > >  	struct lxc_cgroup *cgelem = NULL;
> > > +	bool add = false;
> > >  
> > >  	if (!value || strlen(value) == 0)
> > >  		return lxc_clear_cgroups(lxc_conf, key);
> > > @@ -1236,41 +1252,44 @@ static int config_cgroup(const char *key,
> > > const char *value, 
> > >  	subkey += strlen(token);
> > >  
> > > -	cglist = malloc(sizeof(*cglist));
> > > -	if (!cglist)
> > > -		goto out;
> > > -
> > > -	cgelem = malloc(sizeof(*cgelem));
> > > -	if (!cgelem)
> > > -		goto out;
> > > -	memset(cgelem, 0, sizeof(*cgelem));
> > > +	subsystem = strdup(subkey);
> > > +	if (!subsystem)
> > > +		return -1;
> > > +	val = strdup(value);
> > > +	if (!val)
> > > +		goto err1;
> > >  
> > > -	cgelem->subsystem = strdup(subkey);
> > > -	cgelem->value = strdup(value);
> > > +	cglist = config_cgroup_find(lxc_conf, subkey);
> > > +	if (cglist) {
> > > +		cgelem = cglist->elem;
> > > +		free(cgelem->subsystem);
> > > +		free(cgelem->value);
> > > +	} else {
> > > +		cglist = malloc(sizeof(*cglist));
> > > +		if (!cglist)
> > > +			goto err2;
> > >  
> > > -	if (!cgelem->subsystem || !cgelem->value)
> > > -		goto out;
> > > +		cgelem = malloc(sizeof(*cgelem));
> > > +		if (!cgelem)
> > > +			goto err3;
> > > +		memset(cgelem, 0, sizeof(*cgelem));
> > > +		add = true;
> > > +	}
> > >  
> > > +	cgelem->subsystem = subsystem;
> > > +	cgelem->value = val;
> > >  	cglist->elem = cgelem;
> > >  
> > > -	lxc_list_add_tail(&lxc_conf->cgroup, cglist);
> > > -
> > > +	if (add)
> > > +		lxc_list_add_tail(&lxc_conf->cgroup, cglist);
> > >  	return 0;
> > >  
> > > -out:
> > > -	if (cglist)
> > > -		free(cglist);
> > > -
> > > -	if (cgelem) {
> > > -		if (cgelem->subsystem)
> > > -			free(cgelem->subsystem);
> > > -
> > > -		if (cgelem->value)
> > > -			free(cgelem->value);
> > > -
> > > -		free(cgelem);
> > > -	}
> > > -
> > > +err3:
> > > +	free(cglist);
> > > +err2:
> > > +	free(val);
> > > +err1:
> > > +	free(subsystem);
> > >  	return -1;
> > >  }
> > >  
> > > @@ -2402,3 +2421,101 @@ void write_config(FILE *fout, struct
> > > lxc_conf *c) lxc_list_for_each(it, &c->groups)
> > >  		fprintf(fout, "lxc.group = %s\n", (char
> > > *)it->elem); }
> > > +
> > > +static const struct lxc_ctl lxc_ctl_init[] = {
> > > +	{false, "mem",       "memory.limit_in_bytes", NULL},
> > > +	{false, "cpulimit",  "cpu.shares", NULL},
> > > +	{false, "cpuset",    "cpuset.cpus", NULL}
> > > +};
> > > +
> > > +#define LXC_CTL_CNT (sizeof(lxc_ctl_init)/sizeof(lxc_ctl_init[0]))
> > > +
> > > +struct lxc_ctl *lxc_ctl_new(struct lxc_arguments *args)
> > > +{
> > > +	struct lxc_ctl *ctl;
> > > +	ctl = malloc(sizeof(lxc_ctl_init));
> > > +	if (ctl)
> > > +		memcpy(ctl, lxc_ctl_init, sizeof(lxc_ctl_init));
> > > +	if (args->mem)
> > > +		lxc_ctl_set_value(ctl, "mem", args->mem);
> > > +	if (args->cpuset)
> > > +		lxc_ctl_set_value(ctl, "cpuset", args->cpuset);
> > > +	if (args->cpulimit) {
> > > +		char buf[11];
> > > +		sprintf(buf, "%d", atoi(args->cpulimit) * 1024 /
> > > 100);
> > > +		lxc_ctl_set_value(ctl, "cpulimit", buf);
> > > +	}
> > > +
> > > +	return ctl;
> > > +};
> > > +
> > > +void lxc_ctl_free(struct lxc_ctl *lxc_ctl)
> > > +{
> > > +	int i;
> > > +
> > > +	for (i = 0; i < LXC_CTL_CNT; i++) {
> > > +		if (lxc_ctl[i].value)
> > > +			free(lxc_ctl[i].value);
> > > +	}
> > > +	free(lxc_ctl);
> > > +}
> > > +
> > > +void lxc_ctl_set_value(struct lxc_ctl *lxc_ctl, const char *ctl,
> > > +		       const char *value)
> > > +{
> > > +	int i;
> > > +
> > > +	for (i = 0; i < LXC_CTL_CNT; i++) {
> > > +		if (strcmp(lxc_ctl[i].ctl, ctl))
> > > +			continue;
> > > +		lxc_ctl[i].set = 1;
> > > +		if (lxc_ctl[i].value)
> > > +			free(lxc_ctl[i].value);
> > > +		lxc_ctl[i].value = strdup(value);
> > > +		break;
> > > +	}
> > > +}
> > > +
> > > +bool lxc_ctl_set_running(struct lxc_ctl *lxc_ctl, struct
> > > lxc_container *c) +{
> > > +	int i;
> > > +
> > > +	for (i = 0; i < LXC_CTL_CNT; i++) {
> > > +		if (!lxc_ctl[i].set)
> > > +			continue;
> > > +
> > > +		if (!c->set_cgroup_item(c, lxc_ctl[i].cgitem,
> > > lxc_ctl[i].value)) {
> > > +			ERROR("failed setting %s to %s",
> > > +			      lxc_ctl[i].cgitem, lxc_ctl[i].value);
> > > +			return false;
> > > +		}
> > > +	}
> > > +	return true;
> > > +}
> > > +
> > > +bool lxc_ctl_set_config(struct lxc_ctl *lxc_ctl, struct
> > > lxc_container *c) +{
> > > +	char *key;
> > > +	int i, rc;
> > > +	bool did_set = false;
> > > +
> > > +	for (i = 0; i < LXC_CTL_CNT; i++) {
> > > +		if (!lxc_ctl[i].set)
> > > +			continue;
> > > +
> > > +		rc = asprintf(&key, "lxc.cgroup.%s",
> > > lxc_ctl[i].cgitem);
> > > +		if (rc < 0)
> > > +			return false;
> > > +		if (config_cgroup(key, lxc_ctl[i].value,
> > > c->lxc_conf) != 0) {
> > > +			ERROR("failed setting cfg %s to %s",
> > > +			      lxc_ctl[i].cgitem, lxc_ctl[i].value);
> > > +			return false;
> > > +		}
> > > +		free(key);
> > > +		did_set = true;
> > > +	}
> > > +
> > > +	if (did_set && !c->save_config(c, NULL))
> > > +		return false;
> > > +	return true;
> > > +}
> > > diff --git a/src/lxc/confile.h b/src/lxc/confile.h
> > > index 171614a..4e32ede 100644
> > > --- a/src/lxc/confile.h
> > > +++ b/src/lxc/confile.h
> > > @@ -25,10 +25,13 @@
> > >  #define __LXC_CONFILE_H
> > >  
> > >  #include <stdio.h>
> > > +#include <stdbool.h>
> > >  #include <lxc/attach_options.h>
> > >  
> > >  struct lxc_conf;
> > >  struct lxc_list;
> > > +struct lxc_container;
> > > +struct lxc_arguments;
> > >  
> > >  typedef int (*config_cb)(const char *, const char *, struct
> > > lxc_conf *); struct lxc_config_t {
> > > @@ -52,4 +55,19 @@ extern int lxc_fill_elevated_privileges(char
> > > *flaglist, int *flags); extern int lxc_get_config_item(struct
> > > lxc_conf *c, const char *key, char *retv, int inlen); extern int
> > > lxc_clear_config_item(struct lxc_conf *c, const char *key); extern
> > > void write_config(FILE *fout, struct lxc_conf *c); +
> > > +struct lxc_ctl
> > > +{
> > > +	bool set;
> > > +	const char *ctl;
> > > +	const char *cgitem;
> > > +	char *value;
> > > +};
> > > +
> > > +extern struct lxc_ctl *lxc_ctl_new(struct lxc_arguments *args);
> > > +extern void lxc_ctl_free(struct lxc_ctl *lxc_ctl);
> > > +extern void lxc_ctl_set_value(struct lxc_ctl *lxc_ctl, const char
> > > *ctl, const char *value); +extern bool lxc_ctl_set_running(struct
> > > lxc_ctl *lxc_ctl, struct lxc_container *c); +extern bool
> > > lxc_ctl_set_config(struct lxc_ctl *lxc_ctl, struct lxc_container
> > > *c); + #endif
> > > diff --git a/src/lxc/lxc_create.c b/src/lxc/lxc_create.c
> > > index 2cc866a..b8bf312 100644
> > > --- a/src/lxc/lxc_create.c
> > > +++ b/src/lxc/lxc_create.c
> > > @@ -32,6 +32,7 @@
> > >  #include "bdev.h"
> > >  #include "arguments.h"
> > >  #include "utils.h"
> > > +#include "confile.h"
> > >  
> > >  lxc_log_define(lxc_create_ui, lxc);
> > >  
> > > @@ -81,6 +82,9 @@ static int my_parser(struct lxc_arguments* args,
> > > int c, char* arg) case '4': args->fssize = get_fssize(arg); break;
> > >  	case '5': args->zfsroot = arg; break;
> > >  	case '6': args->dir = arg; break;
> > > +	case OPT_CPULIMIT: args->cpulimit = arg; break;
> > > +	case OPT_CPUSET: args->cpuset = arg; break;
> > > +	case OPT_MEM: args->mem = arg; break;
> > >  	}
> > >  	return 0;
> > >  }
> > > @@ -96,6 +100,9 @@ static const struct option my_longopts[] = {
> > >  	{"fssize", required_argument, 0, '4'},
> > >  	{"zfsroot", required_argument, 0, '5'},
> > >  	{"dir", required_argument, 0, '6'},
> > > +	{"cpulimit", required_argument, 0, OPT_CPULIMIT},
> > > +	{"cpuset", required_argument, 0, OPT_CPUSET},
> > > +	{"mem", required_argument, 0, OPT_MEM},
> > >  	LXC_COMMON_OPTIONS
> > >  };
> > >  
> > > @@ -154,7 +161,10 @@ Options :\n\
> > >                       (Default: 1G, default unit: M)\n\
> > >    --dir=DIR          Place rootfs directory under DIR\n\
> > >    --zfsroot=PATH     Create zfs under given zfsroot\n\
> > > -                     (Default: tank/lxc)\n",
> > > +                     (Default: tank/lxc)\n\
> > > +  --cpulimit=NUM     Percentage of cpu allowed\n\
> > > +  --cpuset=NUM,NUM   Which cpus to run on\n\
> > > +  --mem=BYTES        Amount of memory (may be suffixed with
> > > K,M,G)\n", .options  = my_longopts,
> > >  	.parser   = my_parser,
> > >  	.checker  = NULL,
> > > @@ -190,6 +200,7 @@ int main(int argc, char *argv[])
> > >  {
> > >  	struct lxc_container *c;
> > >  	struct bdev_specs spec;
> > > +	struct lxc_ctl *ctl;
> > >  	int flags = 0;
> > >  
> > >  	if (lxc_arguments_parse(&my_args, argc, argv))
> > > @@ -221,6 +232,10 @@ int main(int argc, char *argv[])
> > >  	if (strcmp(my_args.bdevtype, "none") == 0)
> > >  		my_args.bdevtype = "dir";
> > >  
> > > +	ctl = lxc_ctl_new(&my_args);
> > > +	if (!ctl)
> > > +		exit(1);
> > > +
> > >  	if (geteuid()) {
> > >  		if (mkdir_p(my_args.lxcpath[0], 0755)) {
> > >  			exit(1);
> > > @@ -276,6 +291,8 @@ int main(int argc, char *argv[])
> > >  		my_args.bdevtype = NULL;
> > >  	if (my_args.quiet)
> > >  		flags = LXC_CREATE_QUIET;
> > > +
> > > +	lxc_ctl_set_config(ctl, c);
> > >  	if (!c->create(c, my_args.template, my_args.bdevtype,
> > > &spec, flags, &argv[optind])) { ERROR("Error creating container
> > > %s", c->name); lxc_container_put(c);
> > > diff --git a/src/lxc/lxc_ctl.c b/src/lxc/lxc_ctl.c
> > > new file mode 100644
> > > index 0000000..efe82f9
> > > --- /dev/null
> > > +++ b/src/lxc/lxc_ctl.c
> > > @@ -0,0 +1,133 @@
> > > +/*
> > > + * lxc: linux Container library
> > > + *
> > > + * Authors:
> > > + * Copyright © 2014 Oracle
> > > + * Dwight Engen <dwight.engen at oracle.com>
> > > + *
> > > + * 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
> > > + */
> > > +
> > > +#define _GNU_SOURCE
> > > +#include <stdio.h>
> > > +#include <stdbool.h>
> > > +#include <sys/types.h>
> > > +
> > > +#include <lxc/lxccontainer.h>
> > > +
> > > +#include "lxc.h"
> > > +#include "log.h"
> > > +#include "utils.h"
> > > +#include "arguments.h"
> > > +#include "confile.h"
> > > +
> > > +lxc_log_define(lxc_ctl_ui, lxc);
> > > +
> > > +static bool save = false;
> > > +
> > > +#define OPT_SAVE	OPT_USAGE+1
> > > +
> > > +static int my_parser(struct lxc_arguments *args, int c, char *arg)
> > > +{
> > > +	switch (c) {
> > > +	case OPT_SAVE: save = 1; break;
> > > +	case OPT_CPULIMIT: args->cpulimit = arg; break;
> > > +	case OPT_CPUSET: args->cpuset = arg; break;
> > > +	case OPT_MEM: args->mem = arg; break;
> > > +	}
> > > +	return 0;
> > > +}
> > > +
> > > +static const struct option my_longopts[] = {
> > > +	{"save", no_argument, 0, OPT_SAVE},
> > > +	{"cpulimit", required_argument, 0, OPT_CPULIMIT},
> > > +	{"cpuset", required_argument, 0, OPT_CPUSET},
> > > +	{"mem", required_argument, 0, OPT_MEM},
> > > +	LXC_COMMON_OPTIONS,
> > > +};
> > > +
> > > +static struct lxc_arguments my_args = {
> > > +	.progname = "lxc-ctl",
> > > +	.help     = "\
> > > +--name=NAME\n\
> > > +\n\
> > > +lxc-ctl set basic container limits\n\
> > > +\n\
> > > +Options :\n\
> > > +  -n, --name=NAME       NAME for name of the container\n\
> > > +      --save            Save to config file\n\
> > > +      --cpulimit=NUM    Set percentage of cpu allowed\n\
> > > +      --cpuset=NUM,NUM  Set which cpus to run on\n\
> > > +      --mem=BYTES       Set amount of memory (may be suffixed with
> > > K,M,G)",
> > > +	.name     = NULL,
> > > +	.options  = my_longopts,
> > > +	.parser   = my_parser,
> > > +	.checker  = NULL,
> > > +};
> > > +
> > > +int main(int argc, char *argv[])
> > > +{
> > > +	struct lxc_container *c;
> > > +	struct lxc_ctl *ctl;
> > > +	int ret = EXIT_FAILURE;
> > > +
> > > +	if (lxc_arguments_parse(&my_args, argc, argv))
> > > +		goto err1;
> > > +
> > > +	if (!my_args.log_file)
> > > +		my_args.log_file = "none";
> > > +
> > > +	if (lxc_log_init(my_args.name, my_args.log_file,
> > > my_args.log_priority,
> > > +			 my_args.progname, my_args.quiet,
> > > my_args.lxcpath[0]))
> > > +		goto err1;
> > > +	lxc_log_options_no_override();
> > > +
> > > +	c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
> > > +	if (!c)
> > > +		goto err1;
> > > +
> > > +	if (!c->may_control(c)) {
> > > +		ERROR("Insufficent privileges to control %s:%s",
> > > my_args.lxcpath[0], my_args.name);
> > > +		goto err2;
> > > +	}
> > > +
> > > +	ctl = lxc_ctl_new(&my_args);
> > > +	if (!ctl)
> > > +		goto err2;
> > > +
> > > +	if (save && !lxc_ctl_set_config(ctl, c)) {
> > > +		ERROR("failed to save config %s:%s",
> > > my_args.lxcpath[0], my_args.name);
> > > +		goto err3;
> > > +	}
> > > +
> > > +	if (c->is_running(c)) {
> > > +		if (!lxc_ctl_set_running(ctl, c))
> > > +			goto err3;
> > > +	} else {
> > > +		if (!save) {
> > > +			ERROR("%s:%s is not running",
> > > my_args.lxcpath[0], my_args.name);
> > > +			goto err3;
> > > +		}
> > > +	}
> > > +
> > > +	ret = EXIT_SUCCESS;
> > > +
> > > +err3:
> > > +	lxc_ctl_free(ctl);
> > > +err2:
> > > +	lxc_container_put(c);
> > > +err1:
> > > +	return ret;
> > > +}
> > > -- 
> > > 1.9.0
> > > 
> > > _______________________________________________
> > > lxc-devel mailing list
> > > lxc-devel at lists.linuxcontainers.org
> > > http://lists.linuxcontainers.org/listinfo/lxc-devel
> > _______________________________________________
> > lxc-devel mailing list
> > lxc-devel at lists.linuxcontainers.org
> > http://lists.linuxcontainers.org/listinfo/lxc-devel
> 
> _______________________________________________
> lxc-devel mailing list
> lxc-devel at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/lxc-devel


More information about the lxc-devel mailing list