[libvirt] [PATCH] lxc: fuse mount for /proc/cpuinfo

Cedric Bosdonnat cbosdonnat at suse.com
Wed Sep 2 16:00:20 UTC 2015


Ignore that one, I'll resend another version: I forgot to commit a few
fixes for make check and make syntax-check

--
Cedric

On Wed, 2015-09-02 at 09:54 +0200, Cédric Bosdonnat wrote:
> We already have a fuse mount to reflect the cgroup memory restrictions
> in the container. This commit adds the same for the number of available
> CPUs. Only the CPUs listed by virProcessGetAffinity are shown in the
> container's cpuinfo.
> ---
>  src/lxc/lxc_container.c |  42 ++++++++++++-------
>  src/lxc/lxc_fuse.c      | 109 +++++++++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 136 insertions(+), 15 deletions(-)
> 
> diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
> index a433552..7ae13a8 100644
> --- a/src/lxc/lxc_container.c
> +++ b/src/lxc/lxc_container.c
> @@ -1055,24 +1055,38 @@ static int lxcContainerMountProcFuse(virDomainDefPtr def,
>                                       const char *stateDir)
>  {
>      int ret;
> -    char *meminfo_path = NULL;
> +    char *src_path = NULL;
> +    char *dst_path = NULL;
> +    const char *paths[] = {"meminfo", "cpuinfo"};
> +    size_t i;
>  
> -    VIR_DEBUG("Mount /proc/meminfo stateDir=%s", stateDir);
> +    for (i = 0; i < 2; i++) {
> +        VIR_DEBUG("Mount /proc/%s stateDir=%s", paths[i], stateDir);
> +
> +        if ((ret = virAsprintf(&src_path,
> +                               "/.oldroot/%s/%s.fuse/%s",
> +                               stateDir,
> +                               def->name,
> +                               paths[i])) < 0)
> +            return ret;
> +
> +        if ((ret = virAsprintf(&dst_path,
> +                               "/proc/%s",
> +                               paths[i])) < 0) {
> +            VIR_FREE(src_path);
> +            return ret;
> +        }
>  
> -    if ((ret = virAsprintf(&meminfo_path,
> -                           "/.oldroot/%s/%s.fuse/meminfo",
> -                           stateDir,
> -                           def->name)) < 0)
> -        return ret;
> +        if ((ret = mount(src_path, dst_path,
> +                         NULL, MS_BIND, NULL)) < 0) {
> +            virReportSystemError(errno,
> +                                 _("Failed to mount %s on %s"),
> +                                 src_path, dst_path);
> +        }
>  
> -    if ((ret = mount(meminfo_path, "/proc/meminfo",
> -                     NULL, MS_BIND, NULL)) < 0) {
> -        virReportSystemError(errno,
> -                             _("Failed to mount %s on /proc/meminfo"),
> -                             meminfo_path);
> +        VIR_FREE(src_path);
> +        VIR_FREE(dst_path);
>      }
> -
> -    VIR_FREE(meminfo_path);
>      return ret;
>  }
>  #else
> diff --git a/src/lxc/lxc_fuse.c b/src/lxc/lxc_fuse.c
> index 34a69cc..9c88147 100644
> --- a/src/lxc/lxc_fuse.c
> +++ b/src/lxc/lxc_fuse.c
> @@ -42,6 +42,61 @@
>  #if WITH_FUSE
>  
>  static const char *fuse_meminfo_path = "/meminfo";
> +static const char *fuse_cpuinfo_path = "/cpuinfo";
> +
> +static virBufferPtr lxcProcComputeCpuinfo() {
> +    FILE *fd = NULL;
> +    char *line = NULL;
> +    size_t n;
> +    bool writeProc = false;
> +    virBuffer buffer = VIR_BUFFER_INITIALIZER;
> +    virBufferPtr new_cpuinfo = &buffer;
> +    pid_t pid;
> +    virBitmapPtr cpuAffinity = NULL;
> +
> +    fd = fopen("/proc/cpuinfo", "r");
> +    if (fd == NULL) {
> +        virReportSystemError(errno, _("%s"), "Cannot open /proc/cpuinfo");
> +        goto error;
> +    }
> +
> +    pid = getpid();
> +    if (!(cpuAffinity = virProcessGetAffinity(pid)))
> +        goto error;
> +
> +    while (getline(&line, &n, fd) > 0) {
> +        if (STRPREFIX(line, "processor\t:")) {
> +            unsigned long cpuid = 0;
> +            char *suffix = NULL;
> +            if (virStrToLong_ul(line + 12, &suffix, 10, &cpuid) < 0) {
> +                goto error;
> +            }
> +
> +            if (virBitmapGetBit(cpuAffinity, cpuid, &writeProc) < 0) {
> +                goto error;
> +            }
> +        }
> +
> +        if (writeProc) {
> +            virBufferAdd(new_cpuinfo, line, -1);
> +
> +            if (virBufferCheckError(new_cpuinfo) < 0) {
> +                goto error;
> +            }
> +        }
> +    }
> +
> + cleanup:
> +    VIR_FREE(line);
> +    VIR_FORCE_FCLOSE(fd);
> +    virBitmapFree(cpuAffinity);
> +    return new_cpuinfo;
> +
> + error:
> +    virBufferFreeAndReset(new_cpuinfo);
> +    new_cpuinfo = NULL;
> +    goto cleanup;
> +}
>  
>  static int lxcProcGetattr(const char *path, struct stat *stbuf)
>  {
> @@ -50,6 +105,7 @@ static int lxcProcGetattr(const char *path, struct stat *stbuf)
>      struct stat sb;
>      struct fuse_context *context = fuse_get_context();
>      virDomainDefPtr def = (virDomainDefPtr)context->private_data;
> +    virBufferPtr cpuinfo = NULL;
>  
>      memset(stbuf, 0, sizeof(struct stat));
>      if (virAsprintf(&mempath, "/proc/%s", path) < 0)
> @@ -76,12 +132,36 @@ static int lxcProcGetattr(const char *path, struct stat *stbuf)
>          stbuf->st_atime = sb.st_atime;
>          stbuf->st_ctime = sb.st_ctime;
>          stbuf->st_mtime = sb.st_mtime;
> +    } else if (STREQ(path, fuse_cpuinfo_path)) {
> +        if (!(cpuinfo = lxcProcComputeCpuinfo())) {
> +            res = -EIO;
> +            goto cleanup;
> +        }
> +
> +        if (stat(mempath, &sb) < 0) {
> +            res = -errno;
> +            goto cleanup;
> +        }
> +
> +        stbuf->st_uid = def->idmap.uidmap ? def->idmap.uidmap[0].target : 0;
> +        stbuf->st_gid = def->idmap.gidmap ? def->idmap.gidmap[0].target : 0;
> +        stbuf->st_mode = sb.st_mode;
> +        stbuf->st_nlink = 1;
> +        stbuf->st_blksize = sb.st_blksize;
> +        stbuf->st_size = virBufferUse(cpuinfo);
> +        stbuf->st_blocks = stbuf->st_size / 512;
> +        if (stbuf->st_size % 512 != 0)
> +            stbuf->st_blocks++;
> +        stbuf->st_atime = sb.st_atime;
> +        stbuf->st_ctime = sb.st_ctime;
> +        stbuf->st_mtime = sb.st_mtime;
>      } else {
>          res = -ENOENT;
>      }
>  
>   cleanup:
>      VIR_FREE(mempath);
> +    virBufferFreeAndReset(cpuinfo);
>      return res;
>  }
>  
> @@ -96,6 +176,7 @@ static int lxcProcReaddir(const char *path, void *buf,
>      filler(buf, ".", NULL, 0);
>      filler(buf, "..", NULL, 0);
>      filler(buf, fuse_meminfo_path + 1, NULL, 0);
> +    filler(buf, fuse_cpuinfo_path + 1, NULL, 0);
>  
>      return 0;
>  }
> @@ -103,7 +184,8 @@ static int lxcProcReaddir(const char *path, void *buf,
>  static int lxcProcOpen(const char *path ATTRIBUTE_UNUSED,
>                         struct fuse_file_info *fi ATTRIBUTE_UNUSED)
>  {
> -    if (!STREQ(path, fuse_meminfo_path))
> +    if (!STREQ(path, fuse_meminfo_path) &&
> +        !STREQ(path, fuse_cpuinfo_path))
>          return -ENOENT;
>  
>      if ((fi->flags & 3) != O_RDONLY)
> @@ -234,6 +316,28 @@ static int lxcProcReadMeminfo(char *hostpath, virDomainDefPtr def,
>      return res;
>  }
>  
> +static int lxcProcReadCpuinfo(char *buf, size_t size, off_t offset)
> +{
> +    virBufferPtr new_cpuinfo = lxcProcComputeCpuinfo();
> +    int new_size = -1;
> +    int copied = -1;
> +
> +    if (!new_cpuinfo)
> +        goto error;
> +
> +    copied = size;
> +    new_size = virBufferUse(new_cpuinfo);
> +
> +    if ((new_size - offset) < size)
> +        copied = new_size - offset;
> +
> +    memcpy(buf, virBufferCurrentContent(new_cpuinfo) + offset, copied);
> +
> + error:
> +    virBufferFreeAndReset(new_cpuinfo);
> +    return copied;
> +}
> +
>  static int lxcProcRead(const char *path ATTRIBUTE_UNUSED,
>                         char *buf ATTRIBUTE_UNUSED,
>                         size_t size ATTRIBUTE_UNUSED,
> @@ -254,6 +358,9 @@ static int lxcProcRead(const char *path ATTRIBUTE_UNUSED,
>      if (STREQ(path, fuse_meminfo_path)) {
>          if ((res = lxcProcReadMeminfo(hostpath, def, buf, size, offset)) < 0)
>              res = lxcProcHostRead(hostpath, buf, size, offset);
> +    } else if (STREQ(path, fuse_cpuinfo_path)) {
> +        if ((res = lxcProcReadCpuinfo(buf, size, offset)) < 0)
> +            res = lxcProcHostRead(hostpath, buf, size, offset);
>      }
>  
>      VIR_FREE(hostpath);





More information about the libvir-list mailing list