[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