On Mon, Oct 05, 2009 at 09:17:37AM +0900, Ryota Ozaki wrote: > Hi, > > The patch implements the missing memory control APIs for lxc, i.e., > domainGetMaxMemory, domainSetMaxMemory, domainSetMemory, and improves > domainGetInfo to return proper amount of used memory via cgroup. > > And also it includes trivial two fixes; add missing virCgroupSetMemory in > libvirt_private.syms and fix invalid lxcError argument in lxcDomainGetInfo. > > Thanks, > ozaki-r > > >From 530e56db9367fcb325aeaa7fb0d52a008db2f19f Mon Sep 17 00:00:00 2001 > From: Ryota Ozaki <ozaki.ryota@xxxxxxxxx> > Date: Mon, 5 Oct 2009 02:07:04 +0900 > Subject: [PATCH] lxc: implement missing APIs to control the amount of memory > > * src/libvirt_private.syms: Export virCgroupGetMemoryUsage > and add missing virCgroupSetMemory > * src/lxc/lxc_driver.c: Implement missing memory functions > * src/util/cgroup.c, src/util/cgroup.h: Add the function > to get used memory > --- > src/libvirt_private.syms | 2 + > src/lxc/lxc_driver.c | 122 ++++++++++++++++++++++++++++++++++++++++++++-- > src/util/cgroup.c | 20 ++++++++ > src/util/cgroup.h | 1 + > 4 files changed, 140 insertions(+), 5 deletions(-) > > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index 49bbf96..3be3724 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -53,6 +53,8 @@ virCgroupForDriver; > virCgroupRemove; > virCgroupFree; > virCgroupAddTask; > +virCgroupSetMemory; > +virCgroupGetMemoryUsage; > virCgroupSetCpuShares; > virCgroupGetCpuShares; > virCgroupDenyDevicePath; > diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c > index 5fb4105..8ec4ae4 100644 > --- a/src/lxc/lxc_driver.c > +++ b/src/lxc/lxc_driver.c > @@ -450,6 +450,7 @@ static int lxcDomainGetInfo(virDomainPtr dom, > > if (!virDomainIsActive(vm) || driver->cgroup == NULL) { > info->cpuTime = 0; > + info->memory = vm->def->memory; > } else { > if (virCgroupForDomain(driver->cgroup, vm->def->name, > &cgroup, 0) != 0) { > lxcError(dom->conn, dom, VIR_ERR_INTERNAL_ERROR, > @@ -458,13 +459,18 @@ static int lxcDomainGetInfo(virDomainPtr dom, > } > > if (virCgroupGetCpuacctUsage(cgroup, &(info->cpuTime)) < 0) { > - lxcError(dom->conn, dom, VIR_ERR_OPERATION_FAILED, > ("cannot read cputime for domain")); > + lxcError(dom->conn, dom, VIR_ERR_OPERATION_FAILED, > + "%s", _("cannot read cputime for domain")); > + goto cleanup; > + } > + if (virCgroupGetMemoryUsage(cgroup, &(info->memory)) < 0) { > + lxcError(dom->conn, dom, VIR_ERR_OPERATION_FAILED, > + "%s", _("cannot read memory usage for domain")); > goto cleanup; > } > } > > info->maxMem = vm->def->maxmem; > - info->memory = vm->def->memory; > info->nrVirtCpu = 1; > ret = 0; > > @@ -501,6 +507,112 @@ cleanup: > return ret; > } > > +/* Returns max memory in kb, 0 if error */ > +static unsigned long lxcDomainGetMaxMemory(virDomainPtr dom) { > + lxc_driver_t *driver = dom->conn->privateData; > + virDomainObjPtr vm; > + unsigned long ret = 0; > + > + lxcDriverLock(driver); > + vm = virDomainFindByUUID(&driver->domains, dom->uuid); > + lxcDriverUnlock(driver); > + > + if (!vm) { > + char uuidstr[VIR_UUID_STRING_BUFLEN]; > + virUUIDFormat(dom->uuid, uuidstr); > + lxcError(dom->conn, dom, VIR_ERR_NO_DOMAIN, > + _("no domain with matching uuid '%s'"), uuidstr); > + goto cleanup; > + } > + > + ret = vm->def->maxmem; > + > +cleanup: > + if (vm) > + virDomainObjUnlock(vm); > + return ret; > +} > + > +static int lxcDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) { > + lxc_driver_t *driver = dom->conn->privateData; > + virDomainObjPtr vm; > + int ret = -1; > + > + lxcDriverLock(driver); > + vm = virDomainFindByUUID(&driver->domains, dom->uuid); > + lxcDriverUnlock(driver); > + > + if (!vm) { > + char uuidstr[VIR_UUID_STRING_BUFLEN]; > + virUUIDFormat(dom->uuid, uuidstr); > + lxcError(dom->conn, dom, VIR_ERR_NO_DOMAIN, > + _("no domain with matching uuid '%s'"), uuidstr); > + goto cleanup; > + } > + > + if (newmax < vm->def->memory) { > + lxcError(dom->conn, dom, VIR_ERR_INVALID_ARG, > + "%s", _("cannot set max memory lower than > current memory")); > + goto cleanup; > + } > + > + vm->def->maxmem = newmax; > + ret = 0; > + > +cleanup: > + if (vm) > + virDomainObjUnlock(vm); > + return ret; > +} > + > +static int lxcDomainSetMemory(virDomainPtr dom, unsigned long newmem) { > + lxc_driver_t *driver = dom->conn->privateData; > + virDomainObjPtr vm; > + virCgroupPtr cgroup = NULL; > + int ret = -1; > + > + lxcDriverLock(driver); > + vm = virDomainFindByUUID(&driver->domains, dom->uuid); > + lxcDriverUnlock(driver); > + if (!vm) { > + char uuidstr[VIR_UUID_STRING_BUFLEN]; > + virUUIDFormat(dom->uuid, uuidstr); > + lxcError(dom->conn, dom, VIR_ERR_NO_DOMAIN, > + _("no domain with matching uuid '%s'"), uuidstr); > + goto cleanup; > + } > + > + if (newmem > vm->def->maxmem) { > + lxcError(dom->conn, dom, VIR_ERR_INVALID_ARG, > + "%s", _("cannot set memory higher than max memory")); > + goto cleanup; > + } > + > + if (virDomainIsActive(vm)) { > + if (virCgroupForDomain(driver->cgroup, vm->def->name, > &cgroup, 0) != 0) { > + lxcError(dom->conn, dom, VIR_ERR_INTERNAL_ERROR, > + _("Unable to get cgroup for %s¥n"), vm->def->name); > + goto cleanup; > + } > + > + if (virCgroupSetMemory(cgroup, newmem) < 0) { > + lxcError(dom->conn, dom, VIR_ERR_OPERATION_FAILED, > + "%s", _("cannot set memory for domain")); > + goto cleanup; > + } > + } else { > + vm->def->memory = newmem; > + } > + ret = 0; > + > +cleanup: > + if (vm) > + virDomainObjUnlock(vm); > + if (cgroup) > + virCgroupFree(&cgroup); > + return ret; > +} > + > static char *lxcDomainDumpXML(virDomainPtr dom, > int flags) > { > @@ -2103,9 +2215,9 @@ static virDriver lxcDriver = { > NULL, /* domainReboot */ > lxcDomainDestroy, /* domainDestroy */ > lxcGetOSType, /* domainGetOSType */ > - NULL, /* domainGetMaxMemory */ > - NULL, /* domainSetMaxMemory */ > - NULL, /* domainSetMemory */ > + lxcDomainGetMaxMemory, /* domainGetMaxMemory */ > + lxcDomainSetMaxMemory, /* domainSetMaxMemory */ > + lxcDomainSetMemory, /* domainSetMemory */ > lxcDomainGetInfo, /* domainGetInfo */ > NULL, /* domainSave */ > NULL, /* domainRestore */ > diff --git a/src/util/cgroup.c b/src/util/cgroup.c > index 2e646fd..e56d293 100644 > --- a/src/util/cgroup.c > +++ b/src/util/cgroup.c > @@ -702,6 +702,26 @@ int virCgroupSetMemory(virCgroupPtr group, > unsigned long kb) > } > > /** > + * virCgroupGetMemoryUsage: > + * > + * @group: The cgroup to change memory for > + * @kb: Pointer to returned used memory in kilobytes > + * > + * Returns: 0 on success > + */ > +int virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb) > +{ > + uint64_t usage_in_bytes; > + int ret; > + ret = virCgroupGetValueU64(group, > + VIR_CGROUP_CONTROLLER_MEMORY, > + "memory.usage_in_bytes", &usage_in_bytes); > + if (ret == 0) > + *kb = (unsigned long) usage_in_bytes >> 10; > + return ret; > +} > + > +/** > * virCgroupDenyAllDevices: > * > * @group: The cgroup to deny devices for > diff --git a/src/util/cgroup.h b/src/util/cgroup.h > index aba56c6..aa36632 100644 > --- a/src/util/cgroup.h > +++ b/src/util/cgroup.h > @@ -41,6 +41,7 @@ int virCgroupForDomain(virCgroupPtr driver, > int virCgroupAddTask(virCgroupPtr group, pid_t pid); > > int virCgroupSetMemory(virCgroupPtr group, unsigned long kb); > +int virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb); > > int virCgroupDenyAllDevices(virCgroupPtr group); > > -- ACK, this looks reasonable to me Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list