[lxc-devel] [PATCH 1/1] api: add set_cgroup_item and get_cgroup_item (to c api)

Stéphane Graber stgraber at ubuntu.com
Fri Dec 7 17:34:33 UTC 2012


On 12/06/2012 07:41 PM, Serge Hallyn wrote:
> set_cgroup_item takes a pointer to a running container, a cgroup subsystem
> name, and a char *value and it mimicks
> 	'lxc-cgroup -n containername subsys value'
> get_cgroup_item takes a pointer to a running container, a a cgroup
> subsystem name, a destination value * and the length of the value being
> sent in, and returns the length of what was read from the cgroup file.
> If a 0 len is passed in, then the length of the file is returned.  So
> you can do
> 
> 	len = c->get_cgroup_item(c, "devices.list", NULL, 0);
> 	v = malloc(len+1);
> 	ret = c->get_cgroup_item(c, "devices.list", v, len);
> 
> to read the whole file.
> 
> This patch also disables the lxc-init part of the startone test, which
> was failing because lxc-init has been moved due to multiarch issues.
> The test is salvagable, but saving it was beyond this effort.
> 
> Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>

Looks good. I'll apply it now and test it thoroughly when updating the
python binding later today.

Acked-by: Stéphane Graber <stgraber at ubuntu.com>

> ---
>  src/lxc/cgroup.c       |   20 ++++++++++++++++++-
>  src/lxc/lxccontainer.c |   52 ++++++++++++++++++++++++++++++++++++++++++++++++
>  src/lxc/lxccontainer.h |    9 +++++++++
>  src/tests/startone.c   |   47 +++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 127 insertions(+), 1 deletion(-)
> 
> diff --git a/src/lxc/cgroup.c b/src/lxc/cgroup.c
> index 532d638..b6c948b 100644
> --- a/src/lxc/cgroup.c
> +++ b/src/lxc/cgroup.c
> @@ -789,6 +789,13 @@ out:
>  	return ret;
>  }
>  
> +/*
> + * If you pass in NULL value or 0 len, then you are asking for the size
> + * of the file.  Note that we can't get the file size quickly through stat
> + * or lseek.  Therefore if you pass in len > 0 but less than the file size,
> + * your only indication will be that the return value will be equal to the
> + * passed-in ret.  We will not return the actual full file size.
> + */
>  int lxc_cgroup_get(const char *name, const char *filename,
>  		   char *value, size_t len)
>  {
> @@ -813,7 +820,18 @@ int lxc_cgroup_get(const char *name, const char *filename,
>  		return -1;
>  	}
>  
> -	ret = read(fd, value, len);
> +    if (!len || !value) {
> +        char buf[100];
> +        int count = 0;
> +        while ((ret = read(fd, buf, 100)) > 0)
> +            count += ret;
> +        if (ret >= 0)
> +            ret = count;
> +    } else {
> +        memset(value, 0, len);
> +        ret = read(fd, value, len);
> +    }
> +
>  	if (ret < 0)
>  		ERROR("read %s : %s", path, strerror(errno));
>  
> diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
> index d25b848..1345ab5 100644
> --- a/src/lxc/lxccontainer.c
> +++ b/src/lxc/lxccontainer.c
> @@ -163,6 +163,13 @@ static const char *lxcapi_state(struct lxc_container *c)
>  	return ret;
>  }
>  
> +static bool is_stopped_nolock(struct lxc_container *c)
> +{
> +	lxc_state_t s;
> +	s = lxc_getstate(c->name);
> +	return (s == STOPPED);
> +}
> +
>  static bool lxcapi_is_running(struct lxc_container *c)
>  {
>  	const char *s;
> @@ -850,6 +857,49 @@ static char *lxcapi_config_file_name(struct lxc_container *c)
>  	return strdup(c->configfile);
>  }
>  
> +static bool lxcapi_set_cgroup_item(struct lxc_container *c, const char *subsys, const char *value)
> +{
> +	int ret;
> +	bool b = false;
> +
> +	if (!c)
> +		return false;
> +
> +	if (lxclock(c->privlock, 0))
> +		return false;
> +
> +	if (is_stopped_nolock(c))
> +		goto err;
> +
> +	ret = lxc_cgroup_set(c->name, subsys, value);
> +	if (!ret)
> +		b = true;
> +err:
> +	lxcunlock(c->privlock);
> +	return b;
> +}
> +
> +static int lxcapi_get_cgroup_item(struct lxc_container *c, const char *subsys, char *retv, int inlen)
> +{
> +	int ret = -1;
> +
> +	if (!c || !c->lxc_conf)
> +		return -1;
> +
> +	if (lxclock(c->privlock, 0))
> +		return -1;
> +
> +	if (is_stopped_nolock(c))
> +		goto out;
> +
> +	ret = lxc_cgroup_get(c->name, subsys, retv, inlen);
> +
> +out:
> +	lxcunlock(c->privlock);
> +	return ret;
> +}
> +
> +
>  struct lxc_container *lxc_container_new(const char *name)
>  {
>  	struct lxc_container *c;
> @@ -920,6 +970,8 @@ struct lxc_container *lxc_container_new(const char *name)
>  	c->shutdown = lxcapi_shutdown;
>  	c->clear_config_item = lxcapi_clear_config_item;
>  	c->get_config_item = lxcapi_get_config_item;
> +	c->get_cgroup_item = lxcapi_get_cgroup_item;
> +	c->set_cgroup_item = lxcapi_set_cgroup_item;
>  
>  	/* we'll allow the caller to update these later */
>  	if (lxc_log_init(NULL, NULL, "lxc_container", 0)) {
> diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
> index 9c9296c..a6fdb2b 100644
> --- a/src/lxc/lxccontainer.h
> +++ b/src/lxc/lxccontainer.h
> @@ -48,6 +48,15 @@ struct lxc_container {
>  	 * the length which was our would be printed. */
>  	int (*get_config_item)(struct lxc_container *c, const char *key, char *retv, int inlen);
>  	int (*get_keys)(struct lxc_container *c, const char *key, char *retv, int inlen);
> +	/*
> +	 * get_cgroup_item returns the number of bytes read, or an error (<0).
> +	 * If retv NULL or inlen 0 is passed in, then the length of the cgroup
> +	 * file will be returned.  *   Otherwise it will return the # of bytes read.
> +	 * If inlen is less than the number of bytes available, then the returned
> +	 * value will be inlen, not the full available size of the file.
> +	 */
> +	int (*get_cgroup_item)(struct lxc_container *c, const char *subsys, char *retv, int inlen);
> +	bool (*set_cgroup_item)(struct lxc_container *c, const char *subsys, const char *value);
>  
>  #if 0
>  	bool (*commit_cgroups)(struct lxc_container *c);
> diff --git a/src/tests/startone.c b/src/tests/startone.c
> index 81a6bfb..325942e 100644
> --- a/src/tests/startone.c
> +++ b/src/tests/startone.c
> @@ -98,6 +98,8 @@ int main(int argc, char *argv[])
>  	int ret = 0;
>  	const char *s;
>  	bool b;
> +	char buf[201];
> +	int len;
>  
>  	ret = 1;
>  	/* test a real container */
> @@ -125,6 +127,19 @@ int main(int argc, char *argv[])
>  		goto out;
>  	}
>  
> +	len = c->get_cgroup_item(c, "cpuset.cpus", buf, 200);
> +	if (len >= 0) {
> +		fprintf(stderr, "%d: %s not running but had cgroup settings\n", __LINE__, MYNAME);
> +		goto out;
> +	}
> +
> +	sprintf(buf, "0");
> +	b = c->set_cgroup_item(c, "cpuset.cpus", buf);
> +	if (b) {
> +		fprintf(stderr, "%d: %s not running but coudl set cgroup settings\n", __LINE__, MYNAME);
> +		goto out;
> +	}
> +
>  	s = c->state(c);
>  	if (!s || strcmp(s, "STOPPED")) {
>  		fprintf(stderr, "%d: %s is in state %s, not in STOPPED.\n", __LINE__, c->name, s ? s : "undefined");
> @@ -172,12 +187,43 @@ int main(int argc, char *argv[])
>  		goto out;
>  	}
>  
> +	len = c->get_cgroup_item(c, "cpuset.cpus", buf, 0);
> +	if (len <= 0) {
> +		fprintf(stderr, "%d: not able to get length of cpuset.cpus (ret %d)\n", __LINE__, len);
> +		goto out;
> +	}
> +
> +	len = c->get_cgroup_item(c, "cpuset.cpus", buf, 200);
> +	if (len <= 0 || strcmp(buf, "0\n")) {
> +		fprintf(stderr, "%d: not able to get cpuset.cpus (len %d buf %s)\n", __LINE__, len, buf);
> +		goto out;
> +	}
> +
> +	sprintf(buf, "FROZEN");
> +	b = c->set_cgroup_item(c, "freezer.state", buf);
> +	if (!b) {
> +		fprintf(stderr, "%d: not able to set freezer.state.\n", __LINE__);
> +		goto out;
> +	}
> +
> +    sprintf(buf, "XXX");
> +	len = c->get_cgroup_item(c, "freezer.state", buf, 200);
> +	if (len <= 0 || (strcmp(buf, "FREEZING\n") && strcmp(buf, "FROZEN\n"))) {
> +		fprintf(stderr, "%d: not able to get freezer.state (len %d buf %s)\n", __LINE__, len, buf);
> +		goto out;
> +	}
> +
> +	c->set_cgroup_item(c, "freezer.state", "THAWED");
> +
>  	printf("hit return to finish");
>  	ret = scanf("%c", &mychar);
>  	if (ret < 0)
>  		goto out;
>  	c->stop(c);
>  
> +    /* feh - multilib has moved the lxc-init crap */
> +    goto ok;
> +
>  	ret = system("mkdir -p " LXCPATH "/lxctest1/rootfs//usr/local/libexec/lxc");
>  	if (!ret)
>  		ret = system("mkdir -p " LXCPATH "/lxctest1/rootfs/usr/lib/lxc/");
> @@ -204,6 +250,7 @@ int main(int argc, char *argv[])
>  	}
>  	//  auto-check result?  ('bobo' is printed on stdout)
>  
> +ok:
>  	fprintf(stderr, "all lxc_container tests passed for %s\n", c->name);
>  	ret = 0;
>  
> 


-- 
Stéphane Graber
Ubuntu developer
http://www.ubuntu.com

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 899 bytes
Desc: OpenPGP digital signature
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20121207/d68259a8/attachment.pgp>


More information about the lxc-devel mailing list