[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