[lxc-devel] [patch 1/1] overwrite /proc/meminfo informations with a fuse

Krzysztof Taraszka krzysztof.taraszka at gnuhosting.net
Wed Sep 2 09:49:28 UTC 2009


2009/9/1 Daniel Lezcano <daniel.lezcano at free.fr>

> This patch allows to display information related to the cgroup
> in /proc/meminfo.
>
> It is a first try, there is certainly a clever way to do that but
> it is just to play with it.
>
> Compile with:
>
>        make lxcfs CFLAGS="-D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=27"
> LDFLAGS="-lfuse"
>
> Launch a container as root with:
>
>        lxc-execute -n foo /bin/bash
>
> Set 256MB of memory:
>
>        echo 268435456 > /cgroup/foo/memory.limit_in_bytes
>
> And finally mount /proc/meminfo:
>
>        ./lxcfs -odirect_io /proc/meminfo
>
> And the results are:
>
> cat /proc/meminfo:
> ==================
>
> MemTotal:      262144 kB
> MemFree:       255991 kB
>
> top:
> ====
>
> top - 23:52:17 up  2:43,  2 users,  load average: 0.00, 0.00, 0.00
> Tasks:   6 total,   1 running,   5 sleeping,   0 stopped,   0 zombie
> Cpu(s):  0.0%us,  0.3%sy,  0.0%ni, 99.0%id,  0.0%wa,  0.0%hi,  0.7%si,  0.0
> Mem:    262144k total,     6153k used,   255991k free,        0k buffers
> Swap:        0k total,        0k used,        0k free,        0k cached
>
>  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
>    1 dlezcano  20   0  8136  484  408 S  0.0  0.2   0:00.00 lxc-init
>    2 dlezcano  20   0 90112 1764 1304 S  0.0  0.7   0:00.08 bash
>   29 root      20   0  121m 1392 1128 S  0.0  0.5   0:00.05 su
>   30 root      20   0 89984 1696 1328 S  0.0  0.6   0:00.05 bash
>   68 root      20   0 37628  888  544 S  0.0  0.3   0:00.00 lxcfs
>   74 root      20   0 14748 1040  868 R  0.0  0.4   0:00.02 top
>
> free:
> =====
>
>             total       used       free     shared    buffers     cached
> Mem:        262144       6153     255991          0          0          0
> -/+ buffers/cache:       6153     255991
>
>
> To be extended ...
>
> Signed-off-by: Daniel Lezcano <daniel.lezcano at free.fr>
> ---
>  lxcfs.c |  217
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 217 insertions(+)
>
> Index: lxcfs/lxcfs.c
> ===================================================================
> --- /dev/null
> +++ lxcfs/lxcfs.c
> @@ -0,0 +1,217 @@
> +#include <fuse.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <errno.h>
> +#include <mntent.h>
> +#include <limits.h>
> +#include <sys/param.h>
> +
> +#define PAGE_SIZE 4096
> +#define BUFFER_SIZE 2*PAGE_SIZE
> +
> +struct cginfo {
> +       char *cgpath;
> +       char buffer[BUFFER_SIZE];
> +       size_t buflen;
> +};
> +
> +struct lxcfs_info {
> +       char *name;
> +       struct cginfo cginfo;
> +};
> +
> +#ifndef LLONG_MAX
> +#define LLONG_MAX    9223372036854775807LL
> +#endif
> +
> +static int lxcfs_getattr(const char *path, struct stat *stbuf)
> +{
> +       struct fuse_context *context = fuse_get_context();
> +
> +       memset(stbuf, 0, sizeof(*stbuf));
> +
> +       stbuf->st_mode = S_IFREG | 0755;
> +       stbuf->st_nlink = 2;
> +       stbuf->st_uid = context->uid;
> +       stbuf->st_gid = context->gid;
> +
> +       return 0;
> +}
> +
> +static int lxcfs_open(const char *path, struct fuse_file_info *fi)
> +{
> +       struct fuse_context *context = fuse_get_context();
> +       struct lxcfs_info *lxcfs_info = context->private_data;
> +       struct cginfo *cginfo = &lxcfs_info->cginfo;
> +       char limit_in_bytes[MAXPATHLEN];
> +       char usage_in_bytes[MAXPATHLEN];
> +
> +       FILE *limit_file, *usage_file;
> +       long long limit, usage;
> +
> +       int err;
> +
> +       snprintf(limit_in_bytes, MAXPATHLEN, "%s/%s/memory.limit_in_bytes",
> +                cginfo->cgpath, lxcfs_info->name);
> +
> +       snprintf(usage_in_bytes, MAXPATHLEN, "%s/%s/memory.usage_in_bytes",
> +                cginfo->cgpath, lxcfs_info->name);
> +
> +       limit_file = fopen(limit_in_bytes, "r");
> +       if (!limit_file)
> +               return -errno;
> +
> +       fscanf(limit_file, "%lld", &limit);
> +       if (limit == LLONG_MAX)
> +               return 0;
> +
> +       usage_file = fopen(usage_in_bytes, "r");
> +       if (!usage_file)
> +               goto out_close_limit;
> +
> +       fscanf(limit_file, "%lld", &limit);
> +
> +       cginfo->buflen = 0;
> +       cginfo->buflen += sprintf(cginfo->buffer, "MemTotal:      %lld
> kB\n", limit >> 10);
> +       cginfo->buflen += sprintf(cginfo->buffer + cginfo->buflen,
> +                                 "MemFree:       %lld kB\n", (limit -
> usage) >> 10);
> +
> +       err = 0;
> +out:
> +
> +       fclose(limit_file);
> +       fclose(usage_file);
> +
> +       return err;
> +
> +out_close_limit:
> +       err = -errno;
> +       fclose(limit_file);
> +       goto out;
> +}
> +
> +static int lxcfs_read(const char *path, char *buf, size_t size,
> +                     off_t offset, struct fuse_file_info *fi)
> +{
> +       struct fuse_context *context = fuse_get_context();
> +       struct lxcfs_info *lxcfs_info = context->private_data;
> +       struct cginfo *cginfo = &lxcfs_info->cginfo;
> +
> +       size_t wrote = offset + size > cginfo->buflen ? cginfo->buflen -
> offset : size;
> +
> +       memcpy(buf, cginfo->buffer + offset, wrote);
> +
> +       return wrote;
> +}
> +
> +static int lxcfs_release(const char *path, struct fuse_file_info *fi)
> +{
> +       return 0;
> +}
> +
> +static int get_cgroup_mount(const char *mtab, char *mnt)
> +{
> +        struct mntent *mntent;
> +        FILE *file = NULL;
> +        int err = -1;
> +
> +        file = setmntent(mtab, "r");
> +        if (!file)
> +                goto out;
> +
> +        while ((mntent = getmntent(file))) {
> +
> +               /* there is a cgroup mounted named "lxc" */
> +               if (!strcmp(mntent->mnt_fsname, "lxc") &&
> +                   !strcmp(mntent->mnt_type, "cgroup")) {
> +                       strcpy(mnt, mntent->mnt_dir);
> +                       err = 0;
> +                       break;
> +               }
> +
> +               /* fallback to the first non-lxc cgroup found */
> +                if (!strcmp(mntent->mnt_type, "cgroup") && err) {
> +                       strcpy(mnt, mntent->mnt_dir);
> +                       err = 0;
> +               }
> +        };
> +
> +        fclose(file);
> +out:
> +        return err;
> +}
> +
> +static char *cgroup_name(void)
> +{
> +       char *path = "/proc/self/cgroup", *name;
> +        char line[MAXPATHLEN];
> +        FILE *file;
> +
> +        file = fopen(path, "r");
> +        if (!file)
> +                return NULL;
> +
> +        fscanf(file, "%s", line);
> +
> +        strtok(line, ":");
> +        strtok(NULL, ":");
> +        name = strtok(NULL, ":");
> +        name = strtok(name, "/");
> +
> +        return strdup(name);
> +}
> +
> +static void *lxcfs_init(struct fuse_conn_info *conn)
> +{
> +       struct lxcfs_info *lxcfs_info;
> +
> +       lxcfs_info = malloc(sizeof(*lxcfs_info));
> +       if (!lxcfs_info)
> +               return NULL;
> +
> +       lxcfs_info->cginfo.cgpath = malloc(MAXPATHLEN);
> +       if (!lxcfs_info->cginfo.cgpath)
> +               goto out_free_info;
> +
> +       if (get_cgroup_mount("/etc/mtab", lxcfs_info->cginfo.cgpath))
> +               if (get_cgroup_mount("/proc/mounts",
> lxcfs_info->cginfo.cgpath))
> +                       goto out_free_cgroup;
> +
> +       lxcfs_info->name = cgroup_name();
> +       if (!lxcfs_info->name)
> +               goto out_free_cgroup;
> +
> +out:
> +       return lxcfs_info;
> +
> +out_free_cgroup:
> +       free(lxcfs_info->cginfo.cgpath);
> +out_free_info:
> +       free(lxcfs_info);
> +       lxcfs_info = NULL;
> +       goto out;
> +}
> +
> +static void lxcfs_destroy(void *private_data)
> +{
> +       struct lxcfs_info *lxcfs_info = private_data;
> +
> +       free(lxcfs_info->cginfo.cgpath);
> +       free(lxcfs_info->name);
> +       free(lxcfs_info);
> +}
> +
> +static struct fuse_operations lxcfs_ops = {
> +       .getattr = lxcfs_getattr,
> +       .open    = lxcfs_open,
> +       .read    = lxcfs_read,
> +       .release = lxcfs_release,
> +       .init    = lxcfs_init,
> +       .destroy = lxcfs_destroy,
> +};
> +
> +int main(int argc, char *argv[])
> +{
> +       return fuse_main(argc, argv, &lxcfs_ops, NULL);
> +}
>
>
Great. Let me see.
Oh, forgot about memsw? "swap in use" is: memory.memsw.usage_in_bytes -
memory.usage_in_bytes. "available swap" is: memory.memsw.limit_in_bytes -
memory.limit_in_bytes because memsw is memory + swap.

-- 
Krzysztof Taraszka
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20090902/2c766a09/attachment.html>


More information about the lxc-devel mailing list