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); -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list