Re: [libvirt] [PATCH v3 13/13] Enable PCI Multifunction hotplug/unplug
Shivaprasad G Bhatwrites: > The flow is to parse and create a list of devices and pass onto the > hotplug functions. > > The patch also removes all checks forbidding the multifunction hotplug. > > Signed-off-by: Shivaprasad G Bhat > --- > src/qemu/qemu_driver.c | 166 > ++- > src/qemu/qemu_hotplug.c | 66 +-- > 2 files changed, 140 insertions(+), 92 deletions(-) > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index e970ad6..0519a33 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -7453,6 +7453,77 @@ qemuDomainUndefine(virDomainPtr dom) > return qemuDomainUndefineFlags(dom, 0); > } > > +static bool > +qemuDomainPCIAddressIsSingleFunctionAddr(virDomainDeviceDefPtr dev) > +{ > + > +virDomainDeviceInfoPtr info = NULL; > +switch ((virDomainDeviceType) dev->type) { > +case VIR_DOMAIN_DEVICE_DISK: > +info = >data.disk->info; > +break; > +case VIR_DOMAIN_DEVICE_NET: > +info = >data.net->info; > +break; > +case VIR_DOMAIN_DEVICE_RNG: > +info = >data.rng->info; > +break; > +case VIR_DOMAIN_DEVICE_HOSTDEV: > +info = dev->data.hostdev->info; > +break; > +case VIR_DOMAIN_DEVICE_CONTROLLER: > +info = >data.controller->info; > +break; > +case VIR_DOMAIN_DEVICE_CHR: > +info = >data.chr->info; Remove this, not supported for PCI > +break; > +case VIR_DOMAIN_DEVICE_FS: > +case VIR_DOMAIN_DEVICE_INPUT: > +case VIR_DOMAIN_DEVICE_SOUND: > +case VIR_DOMAIN_DEVICE_VIDEO: > +case VIR_DOMAIN_DEVICE_WATCHDOG: > +case VIR_DOMAIN_DEVICE_HUB: > +case VIR_DOMAIN_DEVICE_SMARTCARD: > +case VIR_DOMAIN_DEVICE_MEMBALLOON: > +case VIR_DOMAIN_DEVICE_NVRAM: > +case VIR_DOMAIN_DEVICE_SHMEM: > +case VIR_DOMAIN_DEVICE_LEASE: > +case VIR_DOMAIN_DEVICE_REDIRDEV: > +case VIR_DOMAIN_DEVICE_MEMORY: > +case VIR_DOMAIN_DEVICE_NONE: > +case VIR_DOMAIN_DEVICE_TPM: > +case VIR_DOMAIN_DEVICE_PANIC: > +case VIR_DOMAIN_DEVICE_GRAPHICS: > +case VIR_DOMAIN_DEVICE_LAST: > +break; > +} > + > +if (info && info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { > +/* We do not support hotplug multi-function PCI device now, so we > should > + * reserve the whole slot. The function of the PCI device must be 0. > + */ > +if (info->addr.pci.function != 0) { > +virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Single function device addresses with > function=0" > + " expected")); > +return false; > +} > +} > +return true; > +} > + > +static bool isMultifunctionDeviceXML(const char *xml) isPCIMultifunctionDeviceXML > +{ > + xmlDocPtr xmlptr; > + > + if (!(xmlptr = virXMLParse(NULL, xml, _("(device_definition)" { > + /* We report error anyway later */ > + return false; > + } > + > + return STREQ((const char *)(xmlDocGetRootElement(xmlptr))->name, > "devices"); > +} > + > > static int qemuDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, > unsigned int flags) > @@ -7469,6 +7540,8 @@ static int qemuDomainAttachDeviceFlags(virDomainPtr > dom, const char *xml, > qemuDomainObjPrivatePtr priv; > virQEMUDriverConfigPtr cfg = NULL; > virCapsPtr caps = NULL; > +bool multifunction = false; > +size_t i; > > virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | >VIR_DOMAIN_AFFECT_CONFIG, -1); > @@ -7494,14 +7567,25 @@ static int qemuDomainAttachDeviceFlags(virDomainPtr > dom, const char *xml, > if (virDomainObjUpdateModificationImpact(vm, ) < 0) > goto endjob; > > -dev = virDomainDeviceDefParse(xml, vm->def, > - caps, driver->xmlopt, > - parse_flags); > -if (!dev || VIR_ALLOC(devlist) < 0) > -goto endjob; > +multifunction = isMultifunctionDeviceXML(xml); > > -if (VIR_APPEND_ELEMENT(devlist->devs, devlist->count, dev) < 0) > -goto endjob; > +if (multifunction) { > +if (!(devlist = virDomainDeviceDefParseXMLMany(xml, vm->def, > + caps, driver->xmlopt, > + parse_flags))) > +goto endjob; > +if > (virDomainPCIMultifunctionDeviceAddressValidateAssign(priv->pciaddrs, > devlist) < 0) > +goto endjob; > +} else { > +dev = virDomainDeviceDefParse(xml, vm->def, > + caps, driver->xmlopt, > + parse_flags); > +if (!dev || VIR_ALLOC(devlist) < 0) > +goto endjob; > +if
Re: [libvirt] [PATCH v3 12/13] Pass virDomainDeviceDefListPtr to hotplug functions
Shivaprasad G Bhatwrites: > This actually does all the things as though there were more than one > device in list. > > Signed-off-by: Shivaprasad G Bhat > --- > src/qemu/qemu_domain.c | 50 +++--- > src/qemu/qemu_domain.h |6 +-- > src/qemu/qemu_driver.c | 82 +++- > src/qemu/qemu_hotplug.c | 108 > --- > src/qemu/qemu_hotplug.h |6 +-- > 5 files changed, 176 insertions(+), 76 deletions(-) > > diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c > index da5f97d..9f9ad3a 100644 > --- a/src/qemu/qemu_domain.c > +++ b/src/qemu/qemu_domain.c > @@ -5528,14 +5528,21 @@ qemuDomainAttachDeviceConfigInternal(virQEMUCapsPtr > qemuCaps, > int > qemuDomainAttachDeviceConfig(virQEMUCapsPtr qemuCaps, > virDomainDefPtr vmdef, > - virDomainDeviceDefPtr dev, > + virDomainDeviceDefListPtr devlist, > virConnectPtr conn) > { > -if (virDomainDefCompatibleDevice(vmdef, dev, > - VIR_DOMAIN_DEVICE_ACTION_ATTACH) < 0) > -return -1; > +size_t i; > + > +for (i = 0; i < devlist->count; i++) > + if (virDomainDefCompatibleDevice(vmdef, devlist->devs[i], > + VIR_DOMAIN_DEVICE_ACTION_ATTACH) < > 0) > + return -1; > > -return qemuDomainAttachDeviceConfigInternal(qemuCaps, vmdef, dev, conn); > +for (i = 0; i < devlist->count; i++) > + if (qemuDomainAttachDeviceConfigInternal(qemuCaps, vmdef, > devlist->devs[i], conn) < 0) > + return -1; > + > +return 0; > } > > > @@ -5676,13 +5683,20 @@ qemuDomainDetachDeviceConfigInternal(virDomainDefPtr > vmdef, > > int > qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef, > - virDomainDeviceDefPtr dev) > + virDomainDeviceDefListPtr devlist) > { > -if (virDomainDefCompatibleDevice(vmdef, dev, > - VIR_DOMAIN_DEVICE_ACTION_DETACH) < 0) > -return -1; > +size_t i; > + > +for (i = 0; i < devlist->count; i++) > +if (virDomainDefCompatibleDevice(vmdef, devlist->devs[i], > + VIR_DOMAIN_DEVICE_ACTION_DETACH) < > 0) > +return -1; > > -return qemuDomainDetachDeviceConfigInternal(vmdef, dev); > +for (i = 0; i < devlist->count; i++) > +if (qemuDomainDetachDeviceConfigInternal(vmdef, devlist->devs[i]) < > 0) > +return -1; > + > +return 0; > } > > > @@ -5784,11 +5798,17 @@ qemuDomainUpdateDeviceConfigInternal(virQEMUCapsPtr > qemuCaps, > int > qemuDomainUpdateDeviceConfig(virQEMUCapsPtr qemuCaps, > virDomainDefPtr vmdef, > - virDomainDeviceDefPtr dev) > + virDomainDeviceDefListPtr devlist) > { > -if (virDomainDefCompatibleDevice(vmdef, dev, > - VIR_DOMAIN_DEVICE_ACTION_UPDATE) < 0) > -return -1; > +size_t i; > +for (i = 0; i < devlist->count; i++) > +if (virDomainDefCompatibleDevice(vmdef, devlist->devs[i], > + VIR_DOMAIN_DEVICE_ACTION_UPDATE) < > 0) > +return -1; > + > +for (i = 0; i < devlist->count; i++) > +if (qemuDomainUpdateDeviceConfigInternal(qemuCaps, vmdef, > devlist->devs[i]) < 0) > +return -1; > > -return qemuDomainUpdateDeviceConfigInternal(qemuCaps, vmdef, dev); > +return 0; > } > diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h > index 82e3308..acb3c4c 100644 > --- a/src/qemu/qemu_domain.h > +++ b/src/qemu/qemu_domain.h > @@ -672,18 +672,18 @@ int qemuDomainDefValidateDiskLunSource(const > virStorageSource *src) > int > qemuDomainAttachDeviceConfig(virQEMUCapsPtr qemuCaps, > virDomainDefPtr vmdef, > - virDomainDeviceDefPtr dev, > + virDomainDeviceDefListPtr dev, > virConnectPtr conn); > > int > qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef, > - virDomainDeviceDefPtr dev); > + virDomainDeviceDefListPtr dev); > > > int > qemuDomainUpdateDeviceConfig(virQEMUCapsPtr qemuCaps, > virDomainDefPtr vmdef, > - virDomainDeviceDefPtr dev); > + virDomainDeviceDefListPtr dev); > > > #endif /* __QEMU_DOMAIN_H__ */ > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index 9484576..e970ad6 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -7460,7 +7460,8 @@ static int qemuDomainAttachDeviceFlags(virDomainPtr > dom, const
Re: [libvirt] [PATCH v3 11/13] Move the detach of PCI device to the beginnging of live hotplug
Shivaprasad G Bhatwrites: > The hostdevices are the only devices which have dependencies > outside of themselves such that, other functions of the PCI > card should also have been detached from host driver before > attempting the hotplug. > > This patch moves the detach to the beginning of the hotplug > so that the following patch can detach all funtions first before > attempting to hotplug any. > > We need not move the detach for net devices using SRIOV as > all SRIOV devices are single function devices and can be independently > detached as usual. > > Signed-off-by: Shivaprasad G Bhat > --- > src/qemu/qemu_hotplug.c | 43 ++- > 1 file changed, 34 insertions(+), 9 deletions(-) > > diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c > index 9a546e2..6821ed5 100644 > --- a/src/qemu/qemu_hotplug.c > +++ b/src/qemu/qemu_hotplug.c > @@ -899,6 +899,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, > actualType = virDomainNetGetActualType(net); > > if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) { > +virDomainHostdevDefPtr hostdev = virDomainNetGetActualHostdev(net); > /* This is really a "smart hostdev", so it should be attached > * as a hostdev (the hostdev code will reach over into the > * netdev-specific code as appropriate), then also added to > @@ -907,8 +908,14 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, > * qemuDomainAttachHostDevice uses a connection to resolve > * a SCSI hostdev secret, which is not this case, so pass NULL. > */ > -ret = qemuDomainAttachHostDevice(NULL, driver, vm, > - virDomainNetGetActualHostdev(net)); > +if (qemuDomainAttachPCIHostDevicePrepare(driver, vm->def, > + hostdev, priv->qemuCaps) < > 0) > +goto cleanup; > + > +ret = qemuDomainAttachHostDevice(NULL, driver, vm, hostdev); > +if (!ret) > +qemuHostdevReAttachPCIDevices(driver, vm->def->name, , > 1); > + > goto cleanup; > } > > @@ -1248,10 +1255,6 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver, > if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1) < 0) > return -1; > > -if (qemuDomainAttachPCIHostDevicePrepare(driver, vm->def, > - hostdev, priv->qemuCaps) < 0) > -return -1; > - > backend = hostdev->source.subsys.u.pci.backend; > > /* Temporarily add the hostdev to the domain definition. This is needed > @@ -1330,8 +1333,6 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver, > if (releaseaddr) > qemuDomainReleaseDeviceAddress(vm, hostdev->info, NULL); > > -qemuHostdevReAttachPCIDevices(driver, vm->def->name, , 1); > - > VIR_FREE(devstr); > VIR_FREE(configfd_name); > VIR_FORCE_CLOSE(configfd); > @@ -4386,11 +4387,35 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm, > virDomainDeviceDefPtr dev, > virDomainPtr dom) > { > +virQEMUDriverPtr driver = dom->conn->privateData; > +virQEMUCapsPtr qemuCaps = NULL; > +qemuDomainObjPrivatePtr priv = vm->privateData; > + > +if (priv->qemuCaps) > +qemuCaps = virObjectRef(priv->qemuCaps); Unref / free the qemuCaps > +else if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, > vm->def->emulator))) > +return -1; > + > if (virDomainDefCompatibleDevice(vm->def, dev, > VIR_DOMAIN_DEVICE_ACTION_ATTACH) < 0) > return -1; > > -return qemuDomainAttachDeviceLiveInternal(vm, dev, dom); > +if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV && > +dev->data.hostdev->source.subsys.type == > VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI && > +qemuDomainAttachPCIHostDevicePrepare(driver, vm->def, > dev->data.hostdev, qemuCaps) < 0) > +return -1; > + > +if (qemuDomainAttachDeviceLiveInternal(vm, dev, dom) < 0) > +goto undoprepare; > + > +return 0; > + > + undoprepare: > +if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV && > +dev->data.hostdev->source.subsys.type == > VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) > +qemuHostdevReAttachPCIDevices(driver, vm->def->name, > >data.hostdev, 1); > + > +return -1; > } > > static int > > -- > libvir-list mailing list > libvir-list@redhat.com > https://www.redhat.com/mailman/listinfo/libvir-list -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 03/13] Introduce PCI Multifunction device parser
Shivaprasad G Bhatwrites: > This patch just introduces the parser function used by > the later patches. The parser disallows hostdevices to be > used with other virtio devices simultaneously. > > Signed-off-by: Shivaprasad G Bhat > --- > src/conf/domain_conf.c | 123 > ++ > src/conf/domain_conf.h | 19 +++ > src/libvirt_private.syms |3 + > 3 files changed, 124 insertions(+), 21 deletions(-) > > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > index ed0c471..873a309 100644 > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -860,6 +860,36 @@ virDomainXMLOptionClassDispose(void *obj) > (xmlopt->config.privFree)(xmlopt->config.priv); > } > > +/* virDomainDeviceDefListAddCopy - add a *copy* of the device to this list */ > +int > +virDomainDeviceDefListAddCopy(virDomainDeviceDefListPtr list, > + virDomainDeviceDefPtr dev, > + const virDomainDef *def, > + virCapsPtr caps, > + virDomainXMLOptionPtr xmlopt) > +{ > +virDomainDeviceDefPtr copy = virDomainDeviceDefCopy(dev, def, caps, > xmlopt); > + > +if (!copy) > +return -1; > +if (VIR_APPEND_ELEMENT(list->devs, list->count, copy) < 0) { > +virDomainDeviceDefFree(copy); > +return -1; > +} > +return 0; > +} > + > +void virDomainDeviceDefListFree(virDomainDeviceDefListPtr list) > +{ > +size_t i; > + > +if (!list) > +return; > +for (i = 0; i < list->count; i++) > +virDomainDeviceDefFree(list->devs[i]); > +VIR_FREE(list); > +} > + > /** > * virDomainKeyWrapCipherDefParseXML: > * > @@ -12880,25 +12910,16 @@ virDomainMemoryDefParseXML(xmlNodePtr memdevNode, > return NULL; > } > > - > -virDomainDeviceDefPtr > -virDomainDeviceDefParse(const char *xmlStr, > -const virDomainDef *def, > -virCapsPtr caps, > -virDomainXMLOptionPtr xmlopt, > -unsigned int flags) > +static > +virDomainDeviceDefPtr virDomainDeviceDefParseXML(xmlNodePtr node, > + const virDomainDef *def, > + virCapsPtr caps, > + virDomainXMLOptionPtr > xmlopt, > + xmlXPathContextPtr ctxt, > + unsigned int flags) > { > -xmlDocPtr xml; > -xmlNodePtr node; > -xmlXPathContextPtr ctxt = NULL; > virDomainDeviceDefPtr dev = NULL; > char *netprefix; > - > -if (!(xml = virXMLParseStringCtxt(xmlStr, _("(device_definition)"), > ))) > -goto error; > - > -node = ctxt->node; > - > if (VIR_ALLOC(dev) < 0) > goto error; > > @@ -13031,14 +13052,33 @@ virDomainDeviceDefParse(const char *xmlStr, > if (virDomainDeviceDefPostParse(dev, def, caps, flags, xmlopt) < 0) > goto error; > > - cleanup: > +return dev; > + error: > +return NULL; > +} > + > +virDomainDeviceDefPtr > +virDomainDeviceDefParse(const char *xmlStr, > +const virDomainDef *def, > +virCapsPtr caps, > +virDomainXMLOptionPtr xmlopt, > +unsigned int flags) > +{ > +xmlDocPtr xml; > +xmlNodePtr node; > +xmlXPathContextPtr ctxt = NULL; > +virDomainDeviceDefPtr dev = NULL; > + > +if (!(xml = virXMLParseStringCtxt(xmlStr, _("(device_definition)"), > ))) > +return NULL; > + > +node = ctxt->node; > + > +dev = virDomainDeviceDefParseXML(node, def, caps, xmlopt, ctxt, flags); > + > xmlFreeDoc(xml); > xmlXPathFreeContext(ctxt); > return dev; > - > - error: > -VIR_FREE(dev); Missed this ... > -goto cleanup; > } > > > @@ -24365,3 +24405,44 @@ virDomainObjGetShortName(virDomainObjPtr vm) > > return ret; > } > + > + > +virDomainDeviceDefListPtr > +virDomainDeviceDefParseXMLMany(const char *xml, > + const virDomainDef *def, > + virCapsPtr caps, > + virDomainXMLOptionPtr xmlopt, > + unsigned int flags) > +{ > +xmlXPathContextPtr ctxt = NULL; > +xmlDocPtr xmlPtr; > +xmlNodePtr node, root; > +virDomainDeviceDefPtr dev = NULL; > +virDomainDeviceDefListPtr devlist; > + > +if (!(xmlPtr = virXMLParseStringCtxt(xml, _("(device_definition)"), > ))) > +return NULL; > + > +if (VIR_ALLOC(devlist) < 0) > + goto exit; > + > +root = xmlDocGetRootElement(xmlPtr); > +node = root->children; > +while (node) { > +if (node->type == XML_ELEMENT_NODE) { > +dev = virDomainDeviceDefParseXML(node,
Re: [libvirt] [PATCH] conf/qemu: enforce NUMA nodes only for x86 memory hotplug
Peter Krempa <pkre...@redhat.com> writes: > On Tue, Aug 18, 2015 at 15:35:11 +0530, Nikunj A Dadhania wrote: >> libvirt enforces at least one NUMA node for memory hotplug support on >> all architectures. While it might be required for some x86 guest, >> PowerPC can hotplug memory on non-NUMA system. >> >> The generic checks are replaced with arch specific check and xml >> validation too does not enforce "node" for non-x86 arch. >> >> CC: Peter Krempa <pkre...@redhat.com> >> Signed-off-by: Nikunj A Dadhania <nik...@linux.vnet.ibm.com> >> --- >> src/conf/domain_conf.c | 9 ++--- >> src/qemu/qemu_command.c | 28 +--- >> 2 files changed, 23 insertions(+), 14 deletions(-) >> >> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c >> index fd0450f..4cb2d4a 100644 >> --- a/src/conf/domain_conf.c >> +++ b/src/conf/domain_conf.c > > ... > >> @@ -12437,7 +12438,7 @@ virDomainMemoryTargetDefParseXML(xmlNodePtr node, >> xmlNodePtr save = ctxt->node; >> ctxt->node = node; >> >> -if (virXPathUInt("string(./node)", ctxt, >targetNode) < 0) { >> +if (virXPathUInt("string(./node)", ctxt, >targetNode) < 0 && >> ARCH_IS_X86(domDef->os.arch)) { > > The parser code should not be made architecture dependant. In this case > we will need to adjust the code in a way that it will set a known value > in case the numa node was not provided in the device XML and the check > itself will need to be moved into the post parse callback so that the > decision can be made on a per-hypervisor basis. Sure, the only requirement is node should not be made mandatory in parser code. > >> virReportError(VIR_ERR_XML_ERROR, "%s", >> _("invalid or missing value of memory device node")); >> goto cleanup; > > ... > >> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c >> index ae03618..51160e7 100644 >> --- a/src/qemu/qemu_command.c >> +++ b/src/qemu/qemu_command.c >> @@ -4979,8 +4979,12 @@ qemuBuildMemoryBackendStr(unsigned long long size, >> *backendProps = NULL; >> *backendType = NULL; >> >> -/* memory devices could provide a invalid guest node */ >> -if (guestNode >= virDomainNumaGetNodeCount(def->numa)) { >> +/* memory devices could provide a invalid guest node. Moreover, >> + * x86 guests needs at least one numa node to support memory >> + * hotplug >> + */ >> +if ((virDomainNumaGetNodeCount(def->numa) == 0 && >> ARCH_IS_X86(def->os.arch)) || >> +guestNode > virDomainNumaGetNodeCount(def->numa)) { > > If we make this ARCH dependent here it will be hard to adjust it again > in the future. Also I think we should whitelist PPC rather than > blacklisting x86, since other ARCHes and OSes might have the same > problem here. Sure. > >> virReportError(VIR_ERR_CONFIG_UNSUPPORTED, >> _("can't add memory backend for guest node '%d' as " >> "the guest has only '%zu' NUMA nodes configured"), >> @@ -4991,10 +4995,12 @@ qemuBuildMemoryBackendStr(unsigned long long size, >> if (!(props = virJSONValueNewObject())) >> return -1; >> >> -memAccess = virDomainNumaGetNodeMemoryAccessMode(def->numa, guestNode); >> -if (virDomainNumatuneGetMode(def->numa, guestNode, ) < 0 && >> -virDomainNumatuneGetMode(def->numa, -1, ) < 0) >> -mode = VIR_DOMAIN_NUMATUNE_MEM_STRICT; >> +if (virDomainNumaGetNodeCount(def->numa)) { >> +memAccess = virDomainNumaGetNodeMemoryAccessMode(def->numa, >> guestNode); >> +if (virDomainNumatuneGetMode(def->numa, guestNode, ) < 0 && >> +virDomainNumatuneGetMode(def->numa, -1, ) < 0) >> +mode = VIR_DOMAIN_NUMATUNE_MEM_STRICT; >> +} >> >> if (pagesize == 0) { >> /* Find the huge page size we want to use */ >> @@ -9238,11 +9244,11 @@ qemuBuildCommandLine(virConnectPtr conn, >> goto error; >> } >> >> -/* due to guest support, qemu would silently enable NUMA with one >> node >> - * once the memory hotplug backend is enabled. To avoid possible >> - * confusion we will enforce user originated numa configuration >> along >> - * with memory hotplug. */ >> -if (vi
Re: [libvirt] [PATCH] conf/qemu: enforce NUMA nodes only for x86 memory hotplug
Nikunj A Dadhania nik...@linux.vnet.ibm.com writes: libvirt enforces at least one NUMA node for memory hotplug support on all architectures. While it might be required for some x86 guest, PowerPC can hotplug memory on non-NUMA system. The generic checks are replaced with arch specific check and xml validation too does not enforce node for non-x86 arch. CC: Peter Krempa pkre...@redhat.com Ping ? -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] util: Remove empty resource partition created by libvirt
Daniel P. Berrange berra...@redhat.com writes: On Wed, Aug 12, 2015 at 11:09:12AM +0530, Nikunj A Dadhania wrote: Hi Daniel, Daniel P. Berrange berra...@redhat.com writes: On Tue, Aug 11, 2015 at 04:57:15PM +0530, Nikunj A Dadhania wrote: The default resource partition is created in the domain start path if it is not existing. Even when libvirtd is stopped after shutting down all domains, the resource partition still exists. The patch adds code to removes the default resource partition in the cgroup removal path of the domain. If the default resource partition is found to have no child cgroup, the default resource partition will be removed. Moreover, the code does not remove the user provided resource partitions. Signed-off-by: Nikunj A Dadhania nik...@linux.vnet.ibm.com I don't think we want to be doing this. In non-systemd hosts this will be deleting the heirarchy that the sysadmin manually pre-created for their VMs. In a systemd host it will also end up deleting slices that were created by systemd. AFAIU, there are three cases here: 1) User created resource partition, for example /production/foo As this is created by user, we should not touch them. And my patch does not remove them 2) systemd created /machine.slice If not libvirt, should systemd clean this up when the libvirtd service is stopped ? Currently, my patch does remove this when its found empty It isn't libvirtd's job to delete /machine.slice - systemd will periodically prune empty slices itself. Before runnning machine.slice . ├── blkio │ ├── system.slice │ └── user.slice ├── cpu - cpu,cpuacct ├── cpuacct - cpu,cpuacct ├── cpu,cpuacct │ ├── system.slice │ └── user.slice ├── cpuset ├── devices │ ├── system.slice │ └── user.slice ├── freezer ├── hugetlb ├── memory │ ├── system.slice │ └── user.slice ├── net_cls - net_cls,net_prio ├── net_cls,net_prio ├── net_prio - net_cls,net_prio ├── perf_event └── systemd ├── system.slice └── user.slice After starting systemd-machined: . ├── blkio │ ├── machine.slice │ ├── system.slice │ └── user.slice ├── cpu - cpu,cpuacct ├── cpuacct - cpu,cpuacct ├── cpu,cpuacct │ ├── machine.slice │ ├── system.slice │ └── user.slice ├── cpuset ├── devices │ ├── machine.slice │ ├── system.slice │ └── user.slice ├── freezer ├── hugetlb ├── memory │ ├── machine.slice │ ├── system.slice │ └── user.slice ├── net_cls - net_cls,net_prio ├── net_cls,net_prio ├── net_prio - net_cls,net_prio ├── perf_event └── systemd ├── machine.slice ├── system.slice └── user.slice systemd leaves out cpuset/freezer. So these are basically created by libvirt and not by systemd. When I went through systemd code, it seems cpuset/freezer is disabled on purpose. systemd/src/core/main.c static int initialize_join_controllers(void) { /* By default, mount cpu + cpuacct together, and net_cls * + net_prio. We'd like to add cpuset to the mix, but * cpuset doesn't really work for groups with no initialized * attributes. */ Some more details here: http://www.freedesktop.org/wiki/Software/systemd/ControlGroupInterface/ Note that the number of cgroup attributes currently exposed as unit properties is limited. This will be extended later on, as their kernel interfaces are cleaned up. For example cpuset or freezer are currently not exposed at all due to the broken inheritance semantics of the kernel logic. 3) libvirt created /machine As this was created manually by libvirt, should we delete it here in libvirt daemon No, you can't assume /machine is created by libvirtd - it could have been created by the user, just like case 3. I was thinking of an idea to create a stub directory libvirt-owned in the machine/machine.slice if libvirt created this directory. So while on the exit path if we find the directory empty and is owned by libvirt, we can clean that up. Regards, Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] conf/qemu: enforce NUMA nodes only for x86 memory hotplug
libvirt enforces at least one NUMA node for memory hotplug support on all architectures. While it might be required for some x86 guest, PowerPC can hotplug memory on non-NUMA system. The generic checks are replaced with arch specific check and xml validation too does not enforce node for non-x86 arch. CC: Peter Krempa pkre...@redhat.com Signed-off-by: Nikunj A Dadhania nik...@linux.vnet.ibm.com --- src/conf/domain_conf.c | 9 ++--- src/qemu/qemu_command.c | 28 +--- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index fd0450f..4cb2d4a 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -12430,6 +12430,7 @@ virDomainMemorySourceDefParseXML(xmlNodePtr node, static int virDomainMemoryTargetDefParseXML(xmlNodePtr node, + const virDomainDef *domDef, xmlXPathContextPtr ctxt, virDomainMemoryDefPtr def) { @@ -12437,7 +12438,7 @@ virDomainMemoryTargetDefParseXML(xmlNodePtr node, xmlNodePtr save = ctxt-node; ctxt-node = node; -if (virXPathUInt(string(./node), ctxt, def-targetNode) 0) { +if (virXPathUInt(string(./node), ctxt, def-targetNode) 0 ARCH_IS_X86(domDef-os.arch)) { virReportError(VIR_ERR_XML_ERROR, %s, _(invalid or missing value of memory device node)); goto cleanup; @@ -12457,6 +12458,7 @@ virDomainMemoryTargetDefParseXML(xmlNodePtr node, static virDomainMemoryDefPtr virDomainMemoryDefParseXML(xmlNodePtr memdevNode, + const virDomainDef *domDef, xmlXPathContextPtr ctxt, unsigned int flags) { @@ -12495,7 +12497,7 @@ virDomainMemoryDefParseXML(xmlNodePtr memdevNode, goto error; } -if (virDomainMemoryTargetDefParseXML(node, ctxt, def) 0) +if (virDomainMemoryTargetDefParseXML(node, domDef, ctxt, def) 0) goto error; if (virDomainDeviceInfoParseXML(memdevNode, NULL, def-info, flags) 0) @@ -12647,7 +12649,7 @@ virDomainDeviceDefParse(const char *xmlStr, goto error; break; case VIR_DOMAIN_DEVICE_MEMORY: -if (!(dev-data.memory = virDomainMemoryDefParseXML(node, ctxt, flags))) +if (!(dev-data.memory = virDomainMemoryDefParseXML(node, def, ctxt, flags))) goto error; break; case VIR_DOMAIN_DEVICE_NONE: @@ -16328,6 +16330,7 @@ virDomainDefParseXML(xmlDocPtr xml, for (i = 0; i n; i++) { virDomainMemoryDefPtr mem = virDomainMemoryDefParseXML(nodes[i], + def, ctxt, flags); if (!mem) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index ae03618..51160e7 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4979,8 +4979,12 @@ qemuBuildMemoryBackendStr(unsigned long long size, *backendProps = NULL; *backendType = NULL; -/* memory devices could provide a invalid guest node */ -if (guestNode = virDomainNumaGetNodeCount(def-numa)) { +/* memory devices could provide a invalid guest node. Moreover, + * x86 guests needs at least one numa node to support memory + * hotplug + */ +if ((virDomainNumaGetNodeCount(def-numa) == 0 ARCH_IS_X86(def-os.arch)) || +guestNode virDomainNumaGetNodeCount(def-numa)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _(can't add memory backend for guest node '%d' as the guest has only '%zu' NUMA nodes configured), @@ -4991,10 +4995,12 @@ qemuBuildMemoryBackendStr(unsigned long long size, if (!(props = virJSONValueNewObject())) return -1; -memAccess = virDomainNumaGetNodeMemoryAccessMode(def-numa, guestNode); -if (virDomainNumatuneGetMode(def-numa, guestNode, mode) 0 -virDomainNumatuneGetMode(def-numa, -1, mode) 0) -mode = VIR_DOMAIN_NUMATUNE_MEM_STRICT; +if (virDomainNumaGetNodeCount(def-numa)) { +memAccess = virDomainNumaGetNodeMemoryAccessMode(def-numa, guestNode); +if (virDomainNumatuneGetMode(def-numa, guestNode, mode) 0 +virDomainNumatuneGetMode(def-numa, -1, mode) 0) +mode = VIR_DOMAIN_NUMATUNE_MEM_STRICT; +} if (pagesize == 0) { /* Find the huge page size we want to use */ @@ -9238,11 +9244,11 @@ qemuBuildCommandLine(virConnectPtr conn, goto error; } -/* due to guest support, qemu would silently enable NUMA with one node - * once the memory hotplug backend is enabled. To avoid possible - * confusion we will enforce user originated numa configuration along - * with memory hotplug
Re: [libvirt] [PATCH] conf/qemu: enforce NUMA nodes only for x86 memory hotplug
David Gibson da...@gibson.dropbear.id.au writes: On Tue, Aug 18, 2015 at 03:35:11PM +0530, Nikunj A Dadhania wrote: libvirt enforces at least one NUMA node for memory hotplug support on all architectures. While it might be required for some x86 guest, PowerPC can hotplug memory on non-NUMA system. The generic checks are replaced with arch specific check and xml validation too does not enforce node for non-x86 arch. CC: Peter Krempa pkre...@redhat.com Signed-off-by: Nikunj A Dadhania nik...@linux.vnet.ibm.com For future reference, can you CC Andrea Bolognani abolo...@redhat.com on Power related libvirt patches? He's handling most of our Power / libvirt work here at Red Hat. Sure David Regards, Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] util: Remove empty resource partition created by libvirt
Michal Privoznik mpriv...@redhat.com writes: On 12.08.2015 07:39, Nikunj A Dadhania wrote: Hi Daniel, Daniel P. Berrange berra...@redhat.com writes: On Tue, Aug 11, 2015 at 04:57:15PM +0530, Nikunj A Dadhania wrote: The default resource partition is created in the domain start path if it is not existing. Even when libvirtd is stopped after shutting down all domains, the resource partition still exists. The patch adds code to removes the default resource partition in the cgroup removal path of the domain. If the default resource partition is found to have no child cgroup, the default resource partition will be removed. Moreover, the code does not remove the user provided resource partitions. Signed-off-by: Nikunj A Dadhania nik...@linux.vnet.ibm.com I don't think we want to be doing this. In non-systemd hosts this will be deleting the heirarchy that the sysadmin manually pre-created for their VMs. In a systemd host it will also end up deleting slices that were created by systemd. AFAIU, there are three cases here: 1) User created resource partition, for example /production/foo As this is created by user, we should not touch them. And my patch does not remove them 2) systemd created /machine.slice If not libvirt, should systemd clean this up when the libvirtd service is stopped ? No, machined should clean that up based on signalization sent by libvirt when it is started up again. I guess the scenario is as follows: 1) libvirt is starting a container 2) as part of the process, a remote procedure is called (via dbus) on machined to precreate the machine.slice 3) the container is started 4) libvirtd.service is stopped 5) container is stopped In my case I was looking for: 3) the container is started 4) the container is stopped 5) libvirtd.service is stopped Who would remove machine.slice in this case? Basically, there are no containers running currently. Now you have dangling machine.slice. But this in fact is correct, because libvirt needs to clean up its runtime metadata too. Therefore the process should go on like this: 6) libvirtd.service is started again 7) libvirt notices that the container has stopped 8) as part of cleanup process it instructs machined to remove the machine.slice Are you suggesting that current libvirtd along with machined is doing the above 3 steps? Or we would need to enable that? Currently, my patch does remove this when its found empty 3) libvirt created /machine As this was created manually by libvirt, should we delete it here in libvirt daemon This one can make sense. Regards, Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] util: Remove empty resource partition created by libvirt
Daniel P. Berrange berra...@redhat.com writes: On Wed, Aug 12, 2015 at 11:09:12AM +0530, Nikunj A Dadhania wrote: Hi Daniel, Daniel P. Berrange berra...@redhat.com writes: On Tue, Aug 11, 2015 at 04:57:15PM +0530, Nikunj A Dadhania wrote: The default resource partition is created in the domain start path if it is not existing. Even when libvirtd is stopped after shutting down all domains, the resource partition still exists. The patch adds code to removes the default resource partition in the cgroup removal path of the domain. If the default resource partition is found to have no child cgroup, the default resource partition will be removed. Moreover, the code does not remove the user provided resource partitions. Signed-off-by: Nikunj A Dadhania nik...@linux.vnet.ibm.com I don't think we want to be doing this. In non-systemd hosts this will be deleting the heirarchy that the sysadmin manually pre-created for their VMs. In a systemd host it will also end up deleting slices that were created by systemd. AFAIU, there are three cases here: 1) User created resource partition, for example /production/foo As this is created by user, we should not touch them. And my patch does not remove them 2) systemd created /machine.slice If not libvirt, should systemd clean this up when the libvirtd service is stopped ? Currently, my patch does remove this when its found empty It isn't libvirtd's job to delete /machine.slice - systemd will periodically prune empty slices itself. Let me check that, did not see this happening. 3) libvirt created /machine As this was created manually by libvirt, should we delete it here in libvirt daemon No, you can't assume /machine is created by libvirtd - it could have been created by the user, just like case 3. Did you mean case 1 here? Regards, Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] util: Remove empty resource partition created by libvirt
The default resource partition is created in the domain start path if it is not existing. Even when libvirtd is stopped after shutting down all domains, the resource partition still exists. The patch adds code to removes the default resource partition in the cgroup removal path of the domain. If the default resource partition is found to have no child cgroup, the default resource partition will be removed. Moreover, the code does not remove the user provided resource partitions. Signed-off-by: Nikunj A Dadhania nik...@linux.vnet.ibm.com --- src/util/vircgroup.c | 55 1 file changed, 55 insertions(+) diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c index 0599ba5..4dc0702 100644 --- a/src/util/vircgroup.c +++ b/src/util/vircgroup.c @@ -42,6 +42,7 @@ #define __VIR_CGROUP_ALLOW_INCLUDE_PRIV_H__ #include vircgrouppriv.h +#include dirname.h #include virutil.h #include viralloc.h #include virerror.h @@ -3311,6 +3312,59 @@ virCgroupRemoveRecursively(char *grppath) /** + * virCgroupRemoveEmptyParent: + * + * @group-path: The group path + * + * Cleanup the libvirt created partition directory if there are no + * child group existing. For the given @group-path, find the parent + * directory. For resource partition created by libvirt check + * existence of child cgroup. Remove the resource partition if no + * child cgroup exist. + * + * Returns: void + */ +static void +virCgroupRemoveEmptyParent(char *grppath) +{ +char *parent = NULL, *partition = NULL; +struct dirent *ent; +DIR *grpdir; +int direrr; +int is_empty = 1; + +if (!(parent = mdir_name(grppath))) +goto cleanup; + +partition = strrchr(parent, '/'); +if (STRNEQ(partition, /machine) STRNEQ(partition, /machine.slice)) +goto cleanup; + +grpdir = opendir(parent); +if (grpdir == NULL) +goto cleanup; + +while ((direrr = virDirRead(grpdir, ent, NULL)) 0) { +if (ent-d_name[0] == '.') continue; +if (ent-d_type == DT_DIR) { +is_empty = 0; +break; +} +} +closedir(grpdir); + +if (is_empty) { +VIR_DEBUG(Removing empty parent cgroup %s, parent); +if (rmdir(parent) != 0) +VIR_ERROR(_(Unable to remove %s (%d)), parent, errno); +} + + cleanup: +VIR_FREE(parent); +return; +} + +/** * virCgroupRemove: * * @group: The group to be removed @@ -3352,6 +3406,7 @@ virCgroupRemove(virCgroupPtr group) VIR_DEBUG(Removing cgroup %s and all child cgroups, grppath); rc = virCgroupRemoveRecursively(grppath); +virCgroupRemoveEmptyParent(grppath); VIR_FREE(grppath); } VIR_DEBUG(Done removing cgroup %s, group-path); -- 2.4.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] util: Remove empty resource partition created by libvirt
Hi Daniel, Daniel P. Berrange berra...@redhat.com writes: On Tue, Aug 11, 2015 at 04:57:15PM +0530, Nikunj A Dadhania wrote: The default resource partition is created in the domain start path if it is not existing. Even when libvirtd is stopped after shutting down all domains, the resource partition still exists. The patch adds code to removes the default resource partition in the cgroup removal path of the domain. If the default resource partition is found to have no child cgroup, the default resource partition will be removed. Moreover, the code does not remove the user provided resource partitions. Signed-off-by: Nikunj A Dadhania nik...@linux.vnet.ibm.com I don't think we want to be doing this. In non-systemd hosts this will be deleting the heirarchy that the sysadmin manually pre-created for their VMs. In a systemd host it will also end up deleting slices that were created by systemd. AFAIU, there are three cases here: 1) User created resource partition, for example /production/foo As this is created by user, we should not touch them. And my patch does not remove them 2) systemd created /machine.slice If not libvirt, should systemd clean this up when the libvirtd service is stopped ? Currently, my patch does remove this when its found empty 3) libvirt created /machine As this was created manually by libvirt, should we delete it here in libvirt daemon Regards, Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 1/1] Set pci-ohci as the USB default controller for PPC64.
Li Zhang zhlci...@gmail.com writes: From: Li Zhang zhlci...@linux.vnet.ibm.com PPC64 prefers to set pci-ohci controller as default USB controller. Currently, libvirt is using legacy USB controller as default. There are problems with VGA which can't work correctly with USB Keyboard and USB Mouse. That requires would require a rephrase. While providing -nodefaults, ppc64 should be specifying the usb controller explicitly in place of using the legacy controller(-usb). Qemu spapr initialization code when sees -usb adds a USB Keyboard and USB Mouse by default. And libvirt too has added a USB keyboard and USB mouse. A recent fix in the in qemu VGA code uncoverd this problem, which resulted in addition of extra keyboard and mouse to the qemu machine. This patch is to set pci-ohci as USB default controller. Signed-off-by: Li Zhang zhlci...@linux.vnet.ibm.com --- src/qemu/qemu_command.c | 5 +++-- tests/qemuxml2argvdata/qemuxml2argv-pseries-usb-default.args | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 379c094..46e851a 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8466,8 +8466,9 @@ qemuBuildCommandLine(virConnectPtr conn, } else if (cont-type == VIR_DOMAIN_CONTROLLER_TYPE_USB cont-model == -1 !qemuDomainMachineIsQ35(def) - (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_PIIX3_USB_UHCI) || -def-os.arch == VIR_ARCH_PPC64)) { + (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_PIIX3_USB_UHCI) || +(!virQEMUCapsGet(qemuCaps, QEMU_CAPS_PCI_OHCI) + def-os.arch == VIR_ARCH_PPC64))) { if (usblegacy) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, %s, _(Multiple legacy USB controllers are diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-usb-default.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-usb-default.args index 3a21b76..eac7c56 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-pseries-usb-default.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-usb-default.args @@ -3,5 +3,5 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \ -nographic -nodefconfig -nodefaults \ -chardev socket,id=charmonitor,path=/tmp/test-monitor,server,nowait \ -mon chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c \ --usb -chardev pty,id=charserial0 \ +-device pci-ohci,id=usb,bus=pci,addr=0x1 -chardev pty,id=charserial0 \ -device spapr-vty,chardev=charserial0,reg=0x3000 -- 1.8.2.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [RFC PATCH] Behaviour of topology, vcpus and maxcpus
Nikunj A Dadhania nik...@linux.vnet.ibm.com writes: I have observed the following with libvirt xml: vcpu6/vcpu cpu topology sockets='1' cores='4' threads='2'/ /cpu So according to the topology maximum supported is 8 vcpus, while the libvirt sets that to 6 - specified in vcpu tag. Shouldn't libvirt error this out as the mismatch between the topology definition and the vcpu count? There is an upper bound check already in place where if we have maxcpu topology-supported cpus, that errors out. For eg. vcpu12/vcpu cpu topology sockets='1' cores='4' threads='2'/ /cpu The below patch make sures that libvirt does the lower bound check as well. Ping, Any comments? Regards Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [RFC PATCH] Behaviour of topology, vcpus and maxcpus
I have observed the following with libvirt xml: vcpu6/vcpu cpu topology sockets='1' cores='4' threads='2'/ /cpu So according to the topology maximum supported is 8 vcpus, while the libvirt sets that to 6 - specified in vcpu tag. Shouldn't libvirt error this out as the mismatch between the topology definition and the vcpu count? There is an upper bound check already in place where if we have maxcpu topology-supported cpus, that errors out. For eg. vcpu12/vcpu cpu topology sockets='1' cores='4' threads='2'/ /cpu The below patch make sures that libvirt does the lower bound check as well. Regards Nikunj diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index f96110b..aa25940 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -12933,6 +12933,14 @@ virDomainDefParseXML(xmlDocPtr xml, goto error; } +if (def-cpu-sockets +def-maxvcpus +def-cpu-sockets * def-cpu-cores * def-cpu-threads) { +virReportError(VIR_ERR_XML_DETAIL, %s, + _(CPUs provided is less than topology)); +goto error; +} + if (def-cpu-cells_cpus def-maxvcpus) { virReportError(VIR_ERR_INTERNAL_ERROR, %s, _(Number of CPUs in numa exceeds the -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 06/10] vcpubandwidth: introduce two new libvirt APIs
On Thu, 14 Jul 2011 16:14:01 +0900, Taku Izumi izumi.t...@jp.fujitsu.com wrote: On Wed, 13 Jul 2011 16:55:28 +0800 Wen Congyang we...@cn.fujitsu.com wrote: At 07/13/2011 04:50 PM, Nikunj A. Dadhania Write: On Wed, 13 Jul 2011 14:26:23 +0800, Wen Congyang we...@cn.fujitsu.com wrote: At 07/07/2011 10:32 AM, Taku Izumi Write: So why introduce VCPU level apis? Adam Litke said IBM's performance team nead to control cpu bandwidth for each vcpu. Right, but we do not export that as a User API, that was my suggestion. We can internally control each vcpu's bandwidth, i.e. divide equally. Hmm, I heard that some server could run CPUs at different speed. May be this patch can simulate this behavior. That happens on my laptop as well, depending on the machine load CPU frequency is changed but it is done transparently. I means explicitly CPU speed configuring. ;) I am not sure if we are trying to simulate that here. So why not leave the flexible interface here, and let users make the decision? In my mind, the flexibility is not always a good thing. It is nothing but troublesome for the person who doesn't like detailed setting. I don't know how many people want this flexibility. I think we should implement the flexibility. If we do not implement, and we want it later, we can not reuse these codes(add new element, and reimplement). IMHO, at present we can use the current SetSchedulerParameters API and whenever we need flexibility an API as suggested in this series could be If we need flexibilty, not only an API shoule be added. We should add new element in the XML config file. It means that libvirt should support inflexibility and flexibilty. It is very bad. If we want to support flexibility later, it is better to support it now. I think nobody needs such a flexibility in the future and I like the simpler way. I had an offline discussion with folks(Adam and Ryan) here at IBM. Simulating a machine with different cpu speed does not seem like a compelling enough case to justify the added configuration complexity. An explicit qouta setting for each vcpu will require user to audit the cputune section to add/remove tunings just to change the vcpu count to the domain. We do not feel that this is the desired behaviour. In our experience, user don't want to make these kinds of decisions. They would rather prefer libvirt to just do the right thing by default. Adam pointed that in the future it is no problem to have the simple API and a more detailed API combined: cputune period quota vcpu id=0 quota.../quota /vcpu /cputune But, the worst thing is the decision is prolonged. If IBM people can accept the current implementation, I also do. Can you accept this, Nikunj ? Still not convinced. If you can't, shall we decide by lot? ;) Not sure if this is the right approach. :-) danpb/DV, what do you think? Regards Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 06/10] vcpubandwidth: introduce two new libvirt APIs
On Wed, 13 Jul 2011 14:26:23 +0800, Wen Congyang we...@cn.fujitsu.com wrote: At 07/07/2011 10:32 AM, Taku Izumi Write: So why introduce VCPU level apis? Adam Litke said IBM's performance team nead to control cpu bandwidth for each vcpu. Right, but we do not export that as a User API, that was my suggestion. We can internally control each vcpu's bandwidth, i.e. divide equally. Hmm, I heard that some server could run CPUs at different speed. May be this patch can simulate this behavior. That happens on my laptop as well, depending on the machine load CPU frequency is changed but it is done transparently. I means explicitly CPU speed configuring. ;) I am not sure if we are trying to simulate that here. So why not leave the flexible interface here, and let users make the decision? In my mind, the flexibility is not always a good thing. It is nothing but troublesome for the person who doesn't like detailed setting. I don't know how many people want this flexibility. I think we should implement the flexibility. If we do not implement, and we want it later, we can not reuse these codes(add new element, and reimplement). IMHO, at present we can use the current SetSchedulerParameters API and whenever we need flexibility an API as suggested in this series could be added. Thanks Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 06/10] vcpubandwidth: introduce two new libvirt APIs
On Wed, 06 Jul 2011 14:56:27 +0800, Gui Jianfeng guijianf...@cn.fujitsu.com wrote: On 2011-7-5 16:41, Nikunj A. Dadhania wrote: On Tue, 05 Jul 2011 15:06:06 +0800, Wen Congyang we...@cn.fujitsu.com wrote: At 07/04/2011 07:19 PM, Nikunj A. Dadhania Write: On Thu, 30 Jun 2011 11:13:18 +0800, Wen Congyang we...@cn.fujitsu.com wrote: We want to control bandwidth for each vcpu, so we can not use the API virDomainSetSchedulerParameters(). Introduce two new APIs to change and query bandwidth for each vcpu. Will we have different cpu bandwidth for different vcpus? Something like this: vcpu1: 100/25 vcpu2: 100/50 vcpu3: 100/30 vcpu4: 100/40 IMO, that is not required, we can have a top level bandwitdh for the VM and then redistribute it among vcpus equally, without user knowing about it. Something like this: VM1(4vcpu) has to be throttled at 1CPU bandwidth using SetSchedParamters. Internally libvirt splits it equally: vcpu1: 100/25 vcpu2: 100/25 vcpu3: 100/25 vcpu4: 100/25 So why introduce VCPU level apis? Adam Litke said IBM's performance team nead to control cpu bandwidth for each vcpu. Right, but we do not export that as a User API, that was my suggestion. We can internally control each vcpu's bandwidth, i.e. divide equally. Hmm, I heard that some server could run CPUs at different speed. May be this patch can simulate this behavior. That happens on my laptop as well, depending on the machine load CPU frequency is changed but it is done transparently. I am not sure if we are trying to simulate that here. Regards Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 06/10] vcpubandwidth: introduce two new libvirt APIs
On Tue, 05 Jul 2011 15:06:06 +0800, Wen Congyang we...@cn.fujitsu.com wrote: At 07/04/2011 07:19 PM, Nikunj A. Dadhania Write: On Thu, 30 Jun 2011 11:13:18 +0800, Wen Congyang we...@cn.fujitsu.com wrote: We want to control bandwidth for each vcpu, so we can not use the API virDomainSetSchedulerParameters(). Introduce two new APIs to change and query bandwidth for each vcpu. Will we have different cpu bandwidth for different vcpus? Something like this: vcpu1: 100/25 vcpu2: 100/50 vcpu3: 100/30 vcpu4: 100/40 IMO, that is not required, we can have a top level bandwitdh for the VM and then redistribute it among vcpus equally, without user knowing about it. Something like this: VM1(4vcpu) has to be throttled at 1CPU bandwidth using SetSchedParamters. Internally libvirt splits it equally: vcpu1: 100/25 vcpu2: 100/25 vcpu3: 100/25 vcpu4: 100/25 So why introduce VCPU level apis? Adam Litke said IBM's performance team nead to control cpu bandwidth for each vcpu. Right, but we do not export that as a User API, that was my suggestion. We can internally control each vcpu's bandwidth, i.e. divide equally. Regards Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 06/10] vcpubandwidth: introduce two new libvirt APIs
On Wed, 6 Jul 2011 10:18:05 +0900, Taku Izumi izumi.t...@jp.fujitsu.com wrote: Nikunj is correct here. We only need to ensure that the bandwidth is distributed equally between all of the cpus. This can be accomplished internally by creating a cgroup for each vcpu and ensuring that 'cpu.share' is the same for each vcpu cgroup. When taken together, virsh I/F and domain XML schema are the following: #virsh schedinfo VM --set cpuperiod=10 --config #virsh schedinfo VM --set cpuquota=5 --config .. vcpu4/vcpu cputune period10/period quota5/quota /cputune When specified above, the qemu driver creates cgroup for each vcpus and specified as follows: The quota value is divided by the number of vcpus. vcpu#: (quota/period) vcpu0: 12500/10 vcpu1: 12500/10 vcpu2: 12500/10 vcpu3: 12500/10 I am with you till this point. This is what I was visualizing the interface as, thanks for putting it. But, these values cannot be confirmed form the domain XML file. Do not understand what do you mean here. Regards, Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 06/10] vcpubandwidth: introduce two new libvirt APIs
On Thu, 30 Jun 2011 11:13:18 +0800, Wen Congyang we...@cn.fujitsu.com wrote: We want to control bandwidth for each vcpu, so we can not use the API virDomainSetSchedulerParameters(). Introduce two new APIs to change and query bandwidth for each vcpu. Will we have different cpu bandwidth for different vcpus? Something like this: vcpu1: 100/25 vcpu2: 100/50 vcpu3: 100/30 vcpu4: 100/40 IMO, that is not required, we can have a top level bandwitdh for the VM and then redistribute it among vcpus equally, without user knowing about it. Something like this: VM1(4vcpu) has to be throttled at 1CPU bandwidth using SetSchedParamters. Internally libvirt splits it equally: vcpu1: 100/25 vcpu2: 100/25 vcpu3: 100/25 vcpu4: 100/25 So why introduce VCPU level apis? Regards, Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [RFC] Add persistent XML for cpu tunables
On Tue, 29 Mar 2011 15:31:19 +0800, Daniel Veillard veill...@redhat.com wrote: On Tue, Mar 29, 2011 at 02:32:18PM +0800, Osier Yang wrote: Example of cputune XML: cputune shares2048/shares vcpupin vcpu='0' cpuset='0-4,^1'/ vcpupin vcpu='1' cpuset='1,3'/ vcpupin vcpu='2' cpuset='0,2'/ /cputune shares is to define the the proportional weighted cpu share for the domain. Hum, what does 2048 there means ? I assume there is an unit but it's not defined. Can we get a precide definition of the semantic of the shares construct. If I were to use it I need to know what it means, and I can't just from that description. Drivers in QEmu and LXC just pass that down to linux, but it still doesn't provide a semantic for it and whatever linux implements at the time is not really a good answer. The number is relative wrt other domains/cgroup, so if we have two VMs each having 2048, both of them will get equal share, i.e. 50% each. In a different scenario, if we have VM1's share as 1024 and VM2's share as 2048, that translates as VM1=33% and VM2=66% share of the CPU. Regards Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] virsh: fix memtune's help message for swap_hard_limit
On Wed, 16 Mar 2011 09:37:32 +0900, KAMEZAWA Hiroyuki kamezawa.hir...@jp.fujitsu.com wrote: On Tue, 15 Mar 2011 14:27:19 + Daniel P. Berrange berra...@redhat.com wrote: NACK to both these changes. The XML and public API must *never* be changed once included in a release. The current names may not be the perfect choices, but we can't change them now I'm afraid. Hmm. Then, only messages should be fixed. Nikunj, please fix. Ok, here is the patch with doc changes and cgroup api rename == From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com * Correct the documentation for cgroup: the swap_hard_limit indicates mem+swap_hard_limit. * Change cgroup private apis to: virCgroupGet/SetMemSwapHardLimit Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- docs/formatdomain.html.in|5 +++-- include/libvirt/libvirt.h.in |3 ++- src/libvirt_private.syms |4 ++-- src/lxc/lxc_controller.c |2 +- src/lxc/lxc_driver.c |4 ++-- src/qemu/qemu_cgroup.c |2 +- src/qemu/qemu_driver.c |6 +++--- src/util/cgroup.c| 16 src/util/cgroup.h|4 ++-- 9 files changed, 24 insertions(+), 22 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index dad268d..52bd4e6 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -231,8 +231,9 @@ kilobytes (i.e. blocks of 1024 bytes)/dd dtcodeswap_hard_limit/code/dt dd The optional codeswap_hard_limit/code element is the maximum - swap the guest can use. The units for this value are kilobytes - (i.e. blocks of 1024 bytes)/dd + memory plus swap the guest can use. The units for this value are + kilobytes (i.e. blocks of 1024 bytes). This has to be more than + hard_limit value provided/dd dtcodemin_guarantee/code/dt dd The optional codemin_guarantee/code element is the guaranteed minimum memory allocation for the guest. The units for this value are diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 055eb2e..87bb9c5 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -729,7 +729,8 @@ typedef enum { * VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT: * * Macro for the swap tunable swap_hard_limit: it represents the maximum swap - * the guest can use. + * plus memory the guest can use. This limit has to be more than + * VIR_DOMAIN_MEMORY_HARD_LIMIT. */ #define VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT swap_hard_limit diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 2ce4bed..025988e 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -72,7 +72,7 @@ virCgroupGetFreezerState; virCgroupGetMemoryHardLimit; virCgroupGetMemorySoftLimit; virCgroupGetMemoryUsage; -virCgroupGetSwapHardLimit; +virCgroupGetMemSwapHardLimit; virCgroupMounted; virCgroupRemove; virCgroupSetCpuShares; @@ -80,7 +80,7 @@ virCgroupSetFreezerState; virCgroupSetMemory; virCgroupSetMemoryHardLimit; virCgroupSetMemorySoftLimit; -virCgroupSetSwapHardLimit; +virCgroupSetMemSwapHardLimit; # command.h diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index af0b70c..cfb0356 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -135,7 +135,7 @@ static int lxcSetContainerResources(virDomainDefPtr def) } if(def-mem.swap_hard_limit) { -rc = virCgroupSetSwapHardLimit(cgroup, def-mem.swap_hard_limit); +rc = virCgroupSetMemSwapHardLimit(cgroup, def-mem.swap_hard_limit); if (rc != 0) { virReportSystemError(-rc, _(Unable to set swap hard limit for domain %s), diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index c4fe936..0eca48e 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -780,7 +780,7 @@ static int lxcDomainSetMemoryParameters(virDomainPtr dom, continue; } -rc = virCgroupSetSwapHardLimit(cgroup, params[i].value.ul); +rc = virCgroupSetMemSwapHardLimit(cgroup, params[i].value.ul); if (rc != 0) { virReportSystemError(-rc, %s, _(unable to set swap_hard_limit tunable)); @@ -886,7 +886,7 @@ static int lxcDomainGetMemoryParameters(virDomainPtr dom, break; case 2: /* fill swap hard limit here */ -rc = virCgroupGetSwapHardLimit(cgroup, val); +rc = virCgroupGetMemSwapHardLimit(cgroup, val); if (rc != 0) { virReportSystemError(-rc, %s, _(unable to get swap hard limit)); diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index e5536c0..a25b486 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -291,7 +291,7 @@ int qemuSetupCgroup(struct qemud_driver *driver, } if (vm-def
Re: [libvirt] [PATCH] virsh: fix memtune's help message for swap_hard_limit
On Fri, 4 Mar 2011 14:46:12 +0900, KAMEZAWA Hiroyuki kamezawa.hir...@jp.fujitsu.com wrote: On Thu, 03 Mar 2011 14:47:36 +0800 Osier Yang jy...@redhat.com wrote: Yes, I think it's better. Should I prepare patches ? or you'll do ? Let's see other guys's opinions before doing it, :) A patch (full change version) is here. maybe good input for discussion. == From 0bceb6f204f7551c701d9f60fecd82562b38bd50 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki kamezawa.hir...@jp.fujitsu.com Date: Fri, 4 Mar 2011 14:46:08 +0900 Subject: [PATCH] Rename swap_hard_limit as memswap_hard_limit This patch affects qemu and lxc, using memory cgroup. Linux's memory cgroup's memory.memsw.limit_in_bytes is a limit for memory+swap, not for swap. (This behavior is for avoiding bad influence for global vmscan and never disturb kswapd behavior by user's setting.) Argh, thats me... :( Thanks for the patch Kame. Reviewed-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Regards, Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] Add persistent XML for cpu tunables
On Sun, 27 Feb 2011 22:39:15 +0800, Osier Yang jy...@redhat.com wrote: These are pretty rough patches, something like a draft, I beleive there must be many problems, please review it heavily, :-) New XML: cputune shares2048/shares vcpupin vcpu='0' cpuset='0-4,^1'/ vcpupin vcpu='1' cpuset='1,3'/ vcpupin vcpu='2' cpuset='0,2'/ /cputune shares is to define the the proportional weighted cpu share for the domain. vcpupin is to define the cpu affinities of vcpus, it will not be displayed if one doesn't specify it explicitly in XML or set the cpu affinites for vcpu via vcpupin, means there will be no vcpupin element in domain XML by default, and the constraints are: - Error if one specify entries more than the count of maxvcpus. - Error when one specify entries for same vcpu. - Error if value of attribute vcpu is more than count of maxvcpus - 1. Attribute cpuset works same as cpuset of element vcpu, reuse the codes for parsing and formating value of cpuset of element vcpu. NB, the idea to add persistent XML for cpushares is from Nikunj A. Dadhania: https://www.redhat.com/archives/libvir-list/2011-January/msg01183.html Thanks for picking the cpushares in this series. Regards Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 1/6] cputune: new tests for testing cputune xml
On Sun, 27 Feb 2011 22:39:16 +0800, Osier Yang jy...@redhat.com wrote: --- tests/qemuxml2argvdata/qemuxml2argv-cputune.args |4 ++ tests/qemuxml2argvdata/qemuxml2argv-cputune.xml | 33 ++ tests/qemuxml2argvtest.c |1 + tests/qemuxml2xmltest.c |1 + 4 files changed, 39 insertions(+), 0 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cputune.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-cputune.xml diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cputune.args b/tests/qemuxml2argvdata/qemuxml2argv-cputune.args new file mode 100644 index 000..c41cec0 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-cputune.args @@ -0,0 +1,4 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ +pc -m 214 -smp 2 -name QEMUGuest1 -nographic \ +-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \ +-hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cputune.xml b/tests/qemuxml2argvdata/qemuxml2argv-cputune.xml new file mode 100644 index 000..76173ec --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-cputune.xml @@ -0,0 +1,33 @@ +domain type='qemu' + nameQEMUGuest1/name + uuidc7a5fdbd-edaf-9455-926a-d65c16db1809/uuid + memory219136/memory + currentMemory219136/currentMemory + vcpu2/vcpu + cputune +shares2048/shares +vcpupin vcpu='0' cpuset='0'/ +vcpupin vcpu='1' cpuset='1'/ + /cputune + os +type arch='i686' machine='pc'hvm/type +boot dev='hd'/ + /os + cpu +topology sockets='2' cores='1' threads='1'/ + /cpu + clock offset='utc'/ + on_poweroffdestroy/on_poweroff + on_rebootrestart/on_reboot + on_crashdestroy/on_crash + devices +emulator/usr/bin/qemu/emulator +disk type='block' device='disk' + source dev='/dev/HostVG/QEMUGuest1'/ + target dev='hda' bus='ide'/ + address type='drive' controller='0' bus='0' unit='0'/ +/disk +controller type='ide' index='0'/ +memballoon model='virtio'/ + /devices +/domain diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index d2864ef..ffa93bf 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -490,6 +490,7 @@ mymain(int argc, char **argv) DO_TEST(memtune, false, QEMU_CAPS_NAME); DO_TEST(blkiotune, false, QEMU_CAPS_NAME); +DO_TEST(cputune, false, QEMU_CAPS_NAME); free(driver.stateDir); virCapabilitiesFree(driver.caps); diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 67e721b..3ee94fc 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -184,6 +184,7 @@ mymain(int argc, char **argv) DO_TEST(encrypted-disk); DO_TEST(memtune); DO_TEST(blkiotune); +DO_TEST(cputune); DO_TEST(smp); Reviewed-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Regards Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 3/6] cputune: support cputune for qemu driver
On Sun, 27 Feb 2011 22:39:18 +0800, Osier Yang jy...@redhat.com wrote: When domain startup, setting cpu affinity and cpu shares according to the cputune xml specified in domain xml. Modify qemudDomainPinVcpu to update domain config for vcpupin, and modify qemuSetSchedulerParameters to update domain config for cpu shares. * src/qemu/qemu_cgroup.c * src/qemu/qemu_driver.c * src/qemu/qemu_process.c --- src/qemu/qemu_cgroup.c | 15 + src/qemu/qemu_driver.c |9 + src/qemu/qemu_process.c | 80 +++ 3 files changed, 104 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index b39b5e1..f578f9e 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -340,6 +340,21 @@ int qemuSetupCgroup(struct qemud_driver *driver, vm-def-name); } +if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU)) { +if (vm-def-cputune.shares != 0) { Osier, we will need patch 5/6 before this to compile, some patch reordering required here. Regards Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 0/6] new virsh command blkiotune support
On Wed, 16 Feb 2011 11:53:06 +0800, Gui Jianfeng guijianf...@cn.fujitsu.com wrote: Hi All, This series implements a new command blkiotune for virsh. A lot of code borrows from memtune. You are able to tune blkio cgroup tunables by this command as follows. Show tunables #virsh blkiotune My_guest weight : 900 Tune tunables(Set IO weight) #virsh blkiotune My_guest --weight 500 #virsh blkiotune My_guest weight : 500 Reviewed the v3 of the patch series, looks good to me. Reviewed-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Regards, Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 2/4 v2] cgroup: Implement blkio.weight tuning API.
On Thu, 27 Jan 2011 13:18:44 +0800, Gui Jianfeng guijianf...@cn.fujitsu.com wrote: Implement blkio.weight tuning API. Signed-off-by: Gui Jianfeng guijianf...@cn.fujitsu.com --- src/libvirt_private.syms |2 ++ src/util/cgroup.c| 39 +++ src/util/cgroup.h|3 +++ 3 files changed, 44 insertions(+), 0 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 2ce4bed..97b9851 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -77,6 +77,8 @@ virCgroupMounted; virCgroupRemove; virCgroupSetCpuShares; virCgroupSetFreezerState; +virCgroupSetWeight; +virCgroupGetWeight; As and after thought, shouldn't we call this as virCgroupSetBlkioWeight virCgroupGetBlkioWeight The current API does not indicate that it is Block IO weight. Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [RFC/PATCH v2] Adding persistent entry for cpu tunable
On Fri, 28 Jan 2011 15:19:11 +0800, Osier Yang jy...@redhat.com wrote: 于 2011年01月28日 13:23, Nikunj A. Dadhania 写道: From: Nikunj A. Dadhanianik...@linux.vnet.ibm.com Make cpu share persistent and add support for parsing them. docs/formatdomain.html.in: Document cputune element src/conf/domain_conf.c,src/conf/domain_conf.h: Add cputune element parsing src/lxc/lxc_controller.c: Use the parsed cputune shares value src/qemu/qemu_cgroup.c: Use the parsed cputune shares value AFAIK, hacking on domain XML schema is also needed, docs/schema/domain.rng Yep, missed it, added in below patch +if (def-cputune.shares) +virBufferVSprintf(buf, cputune\n); +if (def-cputune.shares) { +virBufferVSprintf(buf, shares%lu/shares\n, + def-cputune.shares); +} +if (def-cputune.shares) +virBufferVSprintf(buf, /cputune\n); + Above 3 'if' clauses can be merged? At present, we have only one cpu tunable, we will add more, have kept it that way keeping this in mind, please look at memtune case. diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index e5536c0..d4e73bd 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -304,6 +304,21 @@ int qemuSetupCgroup(struct qemud_driver *driver, vm-def-name); } +if ((rc = qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU))) { +if (vm-def-cputune.shares != 0) { +rc = virCgroupSetCpuShares(cgroup, vm-def-cputune.shares); +if (rc != 0) { +virReportSystemError(-rc, + _(Unable to set cpu shares for domain %s), + vm-def-name); +goto cleanup; +} +} +} else { +VIR_WARN(CPU cgroup is disabled in qemu configuration file: %s, + vm-def-name); +} s/CPU cgroup/cpu controller/ ? Or perhaps cgroup controller 'cpu' is better, and the other possibility here is it's not mounted? Made it say cpu controller group Thanks for the review. Here is the updated v2 patch === From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Make cpu share persistent and add support for parsing them. docs/formatdomain.html.in: Document cputune element docs/schema/domain.rng: add cputune src/conf/domain_conf.c,src/conf/domain_conf.h: Add cputune element parsing src/lxc/lxc_controller.c: Use the parsed cputune shares value src/qemu/qemu_cgroup.c: Use the parsed cputune shares value Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- docs/formatdomain.html.in | 11 +++ docs/schemas/domain.rng | 12 src/conf/domain_conf.c| 14 ++ src/conf/domain_conf.h|3 +++ src/lxc/lxc_controller.c | 10 ++ src/qemu/qemu_cgroup.c| 15 +++ 6 files changed, 65 insertions(+), 0 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index dad268d..e8c04e8 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -200,6 +200,9 @@ lt;swap_hard_limitgt;2097152lt;/swap_hard_limitgt; lt;min_guaranteegt;65536lt;/min_guaranteegt; lt;/memtunegt; + lt;cputunegt; +lt;sharesgt;1024lt;/sharesgt; + lt;/cputunegt; lt;vcpu cpuset=1-4,^3,6 current=1gt;2lt;/vcpugt; .../pre @@ -237,6 +240,14 @@ dd The optional codemin_guarantee/code element is the guaranteed minimum memory allocation for the guest. The units for this value are kilobytes (i.e. blocks of 1024 bytes)/dd + dtcodecputune/code/dt + dd The optional codecputune/code element provides details + regarding the cpu tuneable parameters for the domain. If this is + omitted, it defaults to the OS provided defaults./dd + dtcodeshares/code/dt + dd The optional codeshares/code element is the proportional + weighted share for the domain. If this is omitted, it defaults to the OS + provided defaults./dd dtcodevcpu/code/dt ddThe content of this element defines the maximum number of virtual CPUs allocated for the guest OS, which must be between 1 and diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index a79ca6a..5f68477 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -336,6 +336,18 @@ /element /optional + !-- All the cpu related tunables would go in the cputune -- + optional +element name=cputune + !-- Proportional weighted share for the VM -- + optional +element name=shares + ref name=cpushares/ +/element + /optional +/element + /optional + optional element name=vcpu optional diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index c7de054..cd57364 100644 --- a/src/conf/domain_conf.c +++ b
Re: [libvirt] [PATCH 3/4 v2] qemu: Implement blkio tunable XML configuration and parsing.
On Thu, 27 Jan 2011 13:19:25 +0800, Gui Jianfeng guijianf...@cn.fujitsu.com wrote: Implement blkio tunable XML configuration and parsing. Signed-off-by: Gui Jianfeng guijianf...@cn.fujitsu.com --- src/conf/domain_conf.c | 15 ++- src/conf/domain_conf.h |4 src/qemu/qemu_cgroup.c | 16 +++- src/qemu/qemu_conf.c |3 ++- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 645767e..1d4cd30 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4810,7 +4810,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, { xmlNodePtr *nodes = NULL, node = NULL; char *tmp = NULL; -int i, n; +int i, n, w; This variable is not needed now. Otherwise, I am fine. Reviewed-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Regards, Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 4/4] LXC: LXC Blkio weight configuration support.
On Thu, 27 Jan 2011 13:19:48 +0800, Gui Jianfeng guijianf...@cn.fujitsu.com wrote: LXC Blkio weight configuration support. Signed-off-by: Gui Jianfeng guijianf...@cn.fujitsu.com --- src/lxc/lxc_controller.c | 10 ++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index af0b70c..7bb3581 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -104,6 +104,16 @@ static int lxcSetContainerResources(virDomainDefPtr def) goto cleanup; } +if (def-blkio.weight) { +rc = virCgroupSetWeight(cgroup, def-blkio.weight); +if (rc != 0) { +virReportSystemError(-rc, + _(Unable to set Blkio weight for domain %s), + def-name); +goto cleanup; +} +} + rc = virCgroupSetMemory(cgroup, def-mem.max_balloon); if (rc != 0) { virReportSystemError(-rc, Reviewed-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Regards, Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [RFC/PATCH REPOST] Adding persistent entry for cpu tunable
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Make cpu share persistent and add support for parsing them. docs/formatdomain.html.in: Document cputune element src/conf/domain_conf.c,src/conf/domain_conf.h: Add cputune element parsing src/lxc/lxc_controller.c: Use the parsed cputune shares value src/qemu/qemu_cgroup.c: Use the parsed cputune shares value Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- docs/formatdomain.html.in | 11 +++ src/conf/domain_conf.c| 14 ++ src/conf/domain_conf.h|3 +++ src/lxc/lxc_controller.c | 10 ++ src/qemu/qemu_cgroup.c| 15 +++ 5 files changed, 53 insertions(+), 0 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 55e2cbd..522dc06 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -280,6 +280,9 @@ lt;swap_hard_limitgt;2097152lt;/swap_hard_limitgt; lt;min_guaranteegt;65536lt;/min_guaranteegt; lt;/memtunegt; + lt;cputunegt; +lt;sharesgt;1024lt;/sharesgt; + lt;/cputunegt; lt;vcpu cpuset=1-4,^3,6 current=1gt;2lt;/vcpugt; .../pre @@ -317,6 +320,14 @@ dd The optional codemin_guarantee/code element is the guaranteed minimum memory allocation for the guest. The units for this value are kilobytes (i.e. blocks of 1024 bytes)/dd + dtcodecputune/code/dt + dd The optional codecputune/code element provides details + regarding the cpu tuneable parameters for the domain. If this is + omitted, it defaults to the OS provided defaults./dd + dtcodeshares/code/dt + dd The optional codeshares/code element is the proportional + weighted share for the domain. If this is omitted, it defaults to the OS + provided defaults./dd dtcodevcpu/code/dt ddThe content of this element defines the maximum number of virtual CPUs allocated for the guest OS, which must be between 1 and diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 645767e..63c8927 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4904,6 +4904,11 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, def-mem.swap_hard_limit) 0) def-mem.swap_hard_limit = 0; +/* Extract cpu tunables */ +if (virXPathULong(string(./cputune/shares[1]), ctxt, + def-cputune.shares) 0) +def-cputune.shares = 0; + n = virXPathULong(string(./vcpu[1]), ctxt, count); if (n == -2) { virDomainReportError(VIR_ERR_XML_ERROR, %s, @@ -7313,6 +7318,15 @@ char *virDomainDefFormat(virDomainDefPtr def, def-mem.swap_hard_limit) virBufferVSprintf(buf, /memtune\n); +if (def-cputune.shares) +virBufferVSprintf(buf, cputune\n); +if (def-cputune.shares) { +virBufferVSprintf(buf, shares%lu/shares\n, + def-cputune.shares); +} +if (def-cputune.shares) +virBufferVSprintf(buf, /cputune\n); + if (def-mem.hugepage_backed) { virBufferAddLit(buf, memoryBacking\n); virBufferAddLit(buf, hugepages/\n); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index cf7bdc0..a2c83d3 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -981,6 +981,9 @@ struct _virDomainDef { unsigned short maxvcpus; int cpumasklen; char *cpumask; +struct { +unsigned long shares; /* proportional weight */ +} cputune; /* These 3 are based on virDomainLifeCycleAction enum flags */ int onReboot; diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index af0b70c..24edb49 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -144,6 +144,16 @@ static int lxcSetContainerResources(virDomainDefPtr def) } } +if(def-cputune.shares) { +rc = virCgroupSetCpuShares(cgroup, def-cputune.shares); +if (rc != 0) { +virReportSystemError(-rc, + _(Unable to set cpu shares for domain %s), + def-name); +goto cleanup; +} +} + rc = virCgroupDenyAllDevices(cgroup); if (rc != 0) { virReportSystemError(-rc, diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index e5536c0..d4e73bd 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -304,6 +304,21 @@ int qemuSetupCgroup(struct qemud_driver *driver, vm-def-name); } +if ((rc = qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU))) { +if (vm-def-cputune.shares != 0) { +rc = virCgroupSetCpuShares(cgroup, vm-def-cputune.shares); +if (rc != 0) { +virReportSystemError(-rc, + _(Unable to set cpu shares for domain %s), + vm-def-name); +goto cleanup
Re: [libvirt] [PATCH 3/3] qemu: Implement blkio tunable XML configuration and parsing.
On Sun, 23 Jan 2011 14:19:44 +0800, Gui Jianfeng guijianf...@cn.fujitsu.com wrote: Implement blkio tunable XML configuration and parsing. Signed-off-by: Gui Jianfeng guijianf...@cn.fujitsu.com --- src/conf/domain_conf.c | 17 - src/conf/domain_conf.h |4 src/qemu/qemu_cgroup.c | 16 +++- src/qemu/qemu_conf.c |3 ++- 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 645767e..a05ada5 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4810,7 +4810,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, { xmlNodePtr *nodes = NULL, node = NULL; char *tmp = NULL; -int i, n; +int i, n, w; long id = -1; virDomainDefPtr def; unsigned long count; @@ -4887,6 +4887,13 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, if (node) def-mem.hugepage_backed = 1; +/* Extract blkio cgroup tunables */ +w = virXPathULong(string(./blkiotune/weight), ctxt, + def-blkio.weight); +if (w 0 || def-blkio.weight 1000 || def-blkio.weight 100) +virDomainReportError(VIR_ERR_XML_ERROR, %s, + _(I/O weight should fall in [100, 1000])); + The weight limit [100, 1000] is cgroup specific and should not come at this layer as there would be other HVs that will support Block IO paramters and would not have such limits. So should be better taken care at the cgroup layer than here. diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index cf7bdc0..b117869 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -969,6 +969,10 @@ struct _virDomainDef { char *description; struct { +unsigned long weight; +} blkio; + How about the throttle parameters? index e5536c0..a3e8e6a 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -54,7 +54,6 @@ int qemuCgroupControllerActive(struct qemud_driver *driver, return 0; } - int qemuSetupDiskPathAllow(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED, const char *path, size_t depth ATTRIBUTE_UNUSED, @@ -270,6 +269,21 @@ int qemuSetupCgroup(struct qemud_driver *driver, } } +if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_BLKIO)) { +if (vm-def-blkio.weight != 0) { +rc = virCgroupSetWeight(cgroup, vm-def-blkio.weight); +if(rc != 0) { +virReportSystemError(-rc, + _(Unable to set io weight for domain %s), + vm-def-name); +goto cleanup; +} +} +} else { +VIR_WARN(Blkio cgroup is disabled in qemu configuration file: %s, + vm-def-name); +} + Similar changes would be needed for LXC as well which uses cgroup apis. Regards, Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] virsh fails to define a domain
I am using the git version of libvirt. The domain file was working previously. [nikunj@dhruv ~]$ rpm -q qemu-kvm qemu-kvm-0.12.3-8.fc13.x86_64 Some more debugging suggested that qemuCapsExtractDeviceStr is returning an error. The output of the pci-assign,? is not returning any useful information on my system. [nikunj@dhruv ~]$ qemu-kvm -device pci-assign,? property pci-assign.? not found can't set property ? to on for pci-assign [nikunj@dhruv ~]$ This is supposedly related to f892f5a562cbb6e5b914adced1000df20c3174d6 commit. Don't know what could be a valid fix for this tough. Regards Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] virsh fails to define a domain
On Wed, 19 Jan 2011 15:17:01 +0100, Jiri Denemark jdene...@redhat.com wrote: On Wed, Jan 19, 2011 at 19:36:34 +0530, Nikunj A. Dadhania wrote: Some more debugging suggested that qemuCapsExtractDeviceStr is returning an error. The output of the pci-assign,? is not returning any useful information on my system. [nikunj@dhruv ~]$ qemu-kvm -device pci-assign,? property pci-assign.? not found can't set property ? to on for pci-assign [nikunj@dhruv ~]$ This is supposedly related to f892f5a562cbb6e5b914adced1000df20c3174d6 commit. Don't know what could be a valid fix for this tough. 93681a3683badadd9003226142a729ec5733d2fb is the fix you are looking for. Thanks, thats solves the issue. Regards Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [RFC/PATCH v1] Adding entry for cpu tunable shares in xml
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Make cpu share persistent and add support for parsing them. docs/formatdomain.html.in: Document cputune element src/conf/domain_conf.c,src/conf/domain_conf.h: Add cputune element parsing src/lxc/lxc_controller.c: Use the parsed cputune shares value src/qemu/qemu_cgroup.c: Use the parsed cputune shares value Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- docs/formatdomain.html.in | 11 +++ src/conf/domain_conf.c| 14 ++ src/conf/domain_conf.h|3 +++ src/lxc/lxc_controller.c | 10 ++ src/qemu/qemu_cgroup.c| 15 +++ 5 files changed, 53 insertions(+), 0 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 55e2cbd..522dc06 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -280,6 +280,9 @@ lt;swap_hard_limitgt;2097152lt;/swap_hard_limitgt; lt;min_guaranteegt;65536lt;/min_guaranteegt; lt;/memtunegt; + lt;cputunegt; +lt;sharesgt;1024lt;/sharesgt; + lt;/cputunegt; lt;vcpu cpuset=1-4,^3,6 current=1gt;2lt;/vcpugt; .../pre @@ -317,6 +320,14 @@ dd The optional codemin_guarantee/code element is the guaranteed minimum memory allocation for the guest. The units for this value are kilobytes (i.e. blocks of 1024 bytes)/dd + dtcodecputune/code/dt + dd The optional codecputune/code element provides details + regarding the cpu tuneable parameters for the domain. If this is + omitted, it defaults to the OS provided defaults./dd + dtcodeshares/code/dt + dd The optional codeshares/code element is the proportional + weighted share for the domain. If this is omitted, it defaults to the OS + provided defaults./dd dtcodevcpu/code/dt ddThe content of this element defines the maximum number of virtual CPUs allocated for the guest OS, which must be between 1 and diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 645767e..63c8927 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4904,6 +4904,11 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, def-mem.swap_hard_limit) 0) def-mem.swap_hard_limit = 0; +/* Extract cpu tunables */ +if (virXPathULong(string(./cputune/shares[1]), ctxt, + def-cputune.shares) 0) +def-cputune.shares = 0; + n = virXPathULong(string(./vcpu[1]), ctxt, count); if (n == -2) { virDomainReportError(VIR_ERR_XML_ERROR, %s, @@ -7313,6 +7318,15 @@ char *virDomainDefFormat(virDomainDefPtr def, def-mem.swap_hard_limit) virBufferVSprintf(buf, /memtune\n); +if (def-cputune.shares) +virBufferVSprintf(buf, cputune\n); +if (def-cputune.shares) { +virBufferVSprintf(buf, shares%lu/shares\n, + def-cputune.shares); +} +if (def-cputune.shares) +virBufferVSprintf(buf, /cputune\n); + if (def-mem.hugepage_backed) { virBufferAddLit(buf, memoryBacking\n); virBufferAddLit(buf, hugepages/\n); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index cf7bdc0..a2c83d3 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -981,6 +981,9 @@ struct _virDomainDef { unsigned short maxvcpus; int cpumasklen; char *cpumask; +struct { +unsigned long shares; /* proportional weight */ +} cputune; /* These 3 are based on virDomainLifeCycleAction enum flags */ int onReboot; diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index af0b70c..24edb49 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -144,6 +144,16 @@ static int lxcSetContainerResources(virDomainDefPtr def) } } +if(def-cputune.shares) { +rc = virCgroupSetCpuShares(cgroup, def-cputune.shares); +if (rc != 0) { +virReportSystemError(-rc, + _(Unable to set cpu shares for domain %s), + def-name); +goto cleanup; +} +} + rc = virCgroupDenyAllDevices(cgroup); if (rc != 0) { virReportSystemError(-rc, diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index e5536c0..d4e73bd 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -304,6 +304,21 @@ int qemuSetupCgroup(struct qemud_driver *driver, vm-def-name); } +if ((rc = qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_CPU))) { +if (vm-def-cputune.shares != 0) { +rc = virCgroupSetCpuShares(cgroup, vm-def-cputune.shares); +if (rc != 0) { +virReportSystemError(-rc, + _(Unable to set cpu shares for domain %s), + vm-def-name); +goto cleanup
[libvirt] [PATCH v5] memtune: Let virsh know the unlimited value for memory tunables
On Thu, 13 Jan 2011 09:24:09 +0100, Matthias Bolte matthias.bo...@googlemail.com wrote: 2011/1/13 Nikunj A. Dadhania nik...@linux.vnet.ibm.com: [snip] diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 3c6a54a..3ee47b9 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -696,6 +696,7 @@ typedef enum { */ #define VIR_DOMAIN_MEMORY_FIELD_LENGTH 80 +#define VIR_DOMAIN_MEMORY_PARAM_UNLIMITED INT64_MAX [snip] First add a define VIR_DOMAIN_MEMORY_PARAM_UNLIMITED for the magic value INT64_MAX10, but stick to this value, because changing it could break existing applications. Second make virsh memtune detect VIR_DOMAIN_MEMORY_PARAM_UNLIMITED and print unlimited in that case instead of the actual numeric value. Third make virsh memtune accept -1 as unlimited and translate it to VIR_DOMAIN_MEMORY_PARAM_UNLIMITED. You already addressed the second and third point in your patch so we're close to a proper workaround. Here is one more spin and guess we would be finally there :) From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Display or set unlimited values for memory paramters. Unlimited is represented by INT64_MAX in memory cgroup. v5: return back to max as (INT64_MAX 10) for backward portablity. v4: Fix handling of setting unlimited values v3: Make virCgroupSet memory call ull Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Reported-by: Justin Clift jcl...@redhat.com --- include/libvirt/libvirt.h.in |1 + src/lxc/lxc_driver.c |2 + src/qemu/qemu_driver.c |2 + src/util/cgroup.c| 78 +- src/util/cgroup.h| 14 tools/virsh.c| 13 ++- 6 files changed, 75 insertions(+), 35 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 3c6a54a..055eb2e 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -696,6 +696,7 @@ typedef enum { */ #define VIR_DOMAIN_MEMORY_FIELD_LENGTH 80 +#define VIR_DOMAIN_MEMORY_PARAM_UNLIMITED (INT64_MAX 10) /** * VIR_DOMAIN_MEMORY_HARD_LIMIT: diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index eb58086..2db9954 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -815,7 +815,7 @@ static int lxcDomainGetMemoryParameters(virDomainPtr dom, int i; virCgroupPtr cgroup = NULL; virDomainObjPtr vm = NULL; -unsigned long val; +unsigned long long val; int ret = -1; int rc; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index e915705..6648c6a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7077,7 +7077,7 @@ static int qemuDomainGetMemoryParameters(virDomainPtr dom, int i; virCgroupPtr group = NULL; virDomainObjPtr vm = NULL; -unsigned long val; +unsigned long long val; int ret = -1; int rc; diff --git a/src/util/cgroup.c b/src/util/cgroup.c index 3ba6325..cd9caba 100644 --- a/src/util/cgroup.c +++ b/src/util/cgroup.c @@ -355,8 +355,6 @@ static int virCgroupSetValueU64(virCgroupPtr group, } -#if 0 -/* This is included for completeness, but not yet used */ static int virCgroupSetValueI64(virCgroupPtr group, int controller, @@ -376,6 +374,8 @@ static int virCgroupSetValueI64(virCgroupPtr group, return rc; } +#if 0 +/* This is included for completeness, but not yet used */ static int virCgroupGetValueI64(virCgroupPtr group, int controller, const char *key, @@ -858,12 +858,22 @@ int virCgroupForDomain(virCgroupPtr driver ATTRIBUTE_UNUSED, * * Returns: 0 on success */ -int virCgroupSetMemory(virCgroupPtr group, unsigned long kb) +int virCgroupSetMemory(virCgroupPtr group, unsigned long long kb) { -return virCgroupSetValueU64(group, -VIR_CGROUP_CONTROLLER_MEMORY, -memory.limit_in_bytes, -kb 10); +unsigned long long maxkb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED; + +if (kb maxkb) +return -EINVAL; +else if (kb == maxkb) +return virCgroupSetValueI64(group, +VIR_CGROUP_CONTROLLER_MEMORY, +memory.limit_in_bytes, +-1); +else +return virCgroupSetValueU64(group, +VIR_CGROUP_CONTROLLER_MEMORY, +memory.limit_in_bytes, +kb 10); } /** @@ -894,7 +904,7 @@ int virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb) * * Returns: 0 on success */ -int virCgroupSetMemoryHardLimit(virCgroupPtr group, unsigned long kb) +int virCgroupSetMemoryHardLimit(virCgroupPtr group, unsigned long long kb) { return
[libvirt] [PATCH v3] memtune: Let virsh know the unlimited value for memory tunables
On Tue, 11 Jan 2011 08:19:30 -0700, Eric Blake ebl...@redhat.com wrote: On 01/10/2011 10:18 PM, Nikunj A. Dadhania wrote: [snip] @@ -907,7 +907,7 @@ int virCgroupSetMemoryHardLimit(virCgroupPtr group, unsigned long kb) * * Returns: 0 on success */ -int virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long *kb) +int virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long long *kb) So why is Get changed to ull, but Set remains with just unsigned long? This patch is still incomplete. I think you need to touch both functions, and also virCgroupSetMemory. Also, in virCgroupSetMemory, you need to check for overflow, and fail if someone requests an impossible amount of kb. { long long unsigned int limit_in_bytes; int ret; @@ -915,7 +915,12 @@ int virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long *kb) VIR_CGROUP_CONTROLLER_MEMORY, memory.limit_in_bytes, limit_in_bytes); if (ret == 0) -*kb = (unsigned long) limit_in_bytes 10; +{ +if (limit_in_bytes != INT64_MAX) +*kb = (unsigned long long) limit_in_bytes 10; This cast is not necessary, since limit_in_bytes is already ull. Hi Eric, Thanks for reviewing. Here is the patch, now the set calls are also ull. Still virCgroupGetMemoryUsage is not changed, this will require changes in virDomainInfoPtr (info-memory). I am not sure if I should have them in this patch. From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Display unlimited when the memory cgroup settings says so. Unlimited is represented by INT64_MAX in memory cgroup. v3: Make virCgroupSet memory call ull Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Reported-by: Justin Clift jcl...@redhat.com --- include/libvirt/libvirt.h.in |1 + src/lxc/lxc_driver.c |2 +- src/qemu/qemu_driver.c |2 +- src/util/cgroup.c| 45 +- src/util/cgroup.h| 14 +++-- tools/virsh.c|9 +++- 6 files changed, 52 insertions(+), 21 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 3c6a54a..6475936 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -696,6 +696,7 @@ typedef enum { */ #define VIR_DOMAIN_MEMORY_FIELD_LENGTH 80 +#define VIR_DOMAIN_MEMORY_PARAM_UNLIMITED UINT64_MAX /** * VIR_DOMAIN_MEMORY_HARD_LIMIT: diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index eb58086..2db9954 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -815,7 +815,7 @@ static int lxcDomainGetMemoryParameters(virDomainPtr dom, int i; virCgroupPtr cgroup = NULL; virDomainObjPtr vm = NULL; -unsigned long val; +unsigned long long val; int ret = -1; int rc; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index e915705..6648c6a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7077,7 +7077,7 @@ static int qemuDomainGetMemoryParameters(virDomainPtr dom, int i; virCgroupPtr group = NULL; virDomainObjPtr vm = NULL; -unsigned long val; +unsigned long long val; int ret = -1; int rc; diff --git a/src/util/cgroup.c b/src/util/cgroup.c index 3ba6325..f8991cf 100644 --- a/src/util/cgroup.c +++ b/src/util/cgroup.c @@ -858,8 +858,11 @@ int virCgroupForDomain(virCgroupPtr driver ATTRIBUTE_UNUSED, * * Returns: 0 on success */ -int virCgroupSetMemory(virCgroupPtr group, unsigned long kb) +int virCgroupSetMemory(virCgroupPtr group, unsigned long long kb) { +if (kb (VIR_DOMAIN_MEMORY_PARAM_UNLIMITED 10)) +return -EINVAL; + return virCgroupSetValueU64(group, VIR_CGROUP_CONTROLLER_MEMORY, memory.limit_in_bytes, @@ -883,6 +886,7 @@ int virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb) memory.usage_in_bytes, usage_in_bytes); if (ret == 0) *kb = (unsigned long) usage_in_bytes 10; + return ret; } @@ -894,7 +898,7 @@ int virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb) * * Returns: 0 on success */ -int virCgroupSetMemoryHardLimit(virCgroupPtr group, unsigned long kb) +int virCgroupSetMemoryHardLimit(virCgroupPtr group, unsigned long long kb) { return virCgroupSetMemory(group, kb); } @@ -907,7 +911,7 @@ int virCgroupSetMemoryHardLimit(virCgroupPtr group, unsigned long kb) * * Returns: 0 on success */ -int virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long *kb) +int virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long long *kb) { long long unsigned int limit_in_bytes; int ret; @@ -915,7 +919,12 @@ int virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long *kb
[libvirt] [PATCH v4] memtune: Let virsh know the unlimited value for memory tunables
On Wed, 12 Jan 2011 10:21:04 -0700, Eric Blake ebl...@redhat.com wrote: On 01/12/2011 12:56 AM, Nikunj A. Dadhania wrote: Here is the patch, now the set calls are also ull. Still virCgroupGetMemoryUsage is not changed, this will require changes in virDomainInfoPtr (info-memory). I am not sure if I should have them in this patch. It can be a separate patch, if desired, but it is probably still needed. virCgroupGetMemoryUsage is called only from lxcDomainGetInfo, that is the reason I thought that this change may not be needed. +++ b/tools/virsh.c @@ -2987,9 +2987,14 @@ cmdMemtune(vshControl * ctl, const vshCmd * cmd) params[i].value.l); break; case VIR_DOMAIN_MEMORY_PARAM_ULLONG: -vshPrint(ctl, %-15s: %llu\n, params[i].field, - params[i].value.ul); +{ +if (params[i].value.ul == VIR_DOMAIN_MEMORY_PARAM_UNLIMITED) +vshPrint(ctl, %-15s: unlimited\n, params[i].field); +else +vshPrint(ctl, %-15s: %llu\n, params[i].field, + params[i].value.ul); Do we want any back-compat considerations? That is, if a newer virsh is talking to an older server, which still answered INT64_MAX10 instead of the new VIR_DOMAIN_MEMORY_PARAM_UNLIMITED, should we recognize that situation as another reason to print unlimited? As Mattias suggested in the other mail, this adds more complications. My take is to have VIR_DOMAIN_MEMORY_PARAM_UNLIMITED as the max value. Here is the patch which adds setting as well as displaying the unlimited values. Now in virsh to specify unlimited the user would need to pass -1 for example: virsh # memtune lxcbb1 --hard-limit -1 From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Display and set unlimited when the memory cgroup settings. Unlimited is represented by INT64_MAX in memory cgroup. v4: Fix handling of setting unlimited values v3: Make virCgroupSet memory call ull Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Reported-by: Justin Clift jcl...@redhat.com --- include/libvirt/libvirt.h.in |1 src/lxc/lxc_driver.c |2 - src/qemu/qemu_driver.c |2 - src/util/cgroup.c| 93 +++--- src/util/cgroup.h| 14 +++--- tools/virsh.c| 13 +- 6 files changed, 90 insertions(+), 35 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 3c6a54a..3ee47b9 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -696,6 +696,7 @@ typedef enum { */ #define VIR_DOMAIN_MEMORY_FIELD_LENGTH 80 +#define VIR_DOMAIN_MEMORY_PARAM_UNLIMITED INT64_MAX /** * VIR_DOMAIN_MEMORY_HARD_LIMIT: diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index eb58086..2db9954 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -815,7 +815,7 @@ static int lxcDomainGetMemoryParameters(virDomainPtr dom, int i; virCgroupPtr cgroup = NULL; virDomainObjPtr vm = NULL; -unsigned long val; +unsigned long long val; int ret = -1; int rc; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index e915705..6648c6a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7077,7 +7077,7 @@ static int qemuDomainGetMemoryParameters(virDomainPtr dom, int i; virCgroupPtr group = NULL; virDomainObjPtr vm = NULL; -unsigned long val; +unsigned long long val; int ret = -1; int rc; diff --git a/src/util/cgroup.c b/src/util/cgroup.c index 3ba6325..03a1263 100644 --- a/src/util/cgroup.c +++ b/src/util/cgroup.c @@ -355,8 +355,6 @@ static int virCgroupSetValueU64(virCgroupPtr group, } -#if 0 -/* This is included for completeness, but not yet used */ static int virCgroupSetValueI64(virCgroupPtr group, int controller, @@ -376,6 +374,8 @@ static int virCgroupSetValueI64(virCgroupPtr group, return rc; } +#if 0 +/* This is included for completeness, but not yet used */ static int virCgroupGetValueI64(virCgroupPtr group, int controller, const char *key, @@ -858,12 +858,22 @@ int virCgroupForDomain(virCgroupPtr driver ATTRIBUTE_UNUSED, * * Returns: 0 on success */ -int virCgroupSetMemory(virCgroupPtr group, unsigned long kb) +int virCgroupSetMemory(virCgroupPtr group, unsigned long long kb) { -return virCgroupSetValueU64(group, -VIR_CGROUP_CONTROLLER_MEMORY, -memory.limit_in_bytes, -kb 10); +unsigned long long maxkb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED 10; + +if (kb maxkb) +return -EINVAL; +else if (kb == maxkb) +return
Re: [libvirt] [PATCH] memtune: Let virsh know the unlimited value for memory tunables
On Mon, 10 Jan 2011 12:02:36 -0700, Eric Blake ebl...@redhat.com wrote: On 01/07/2011 12:09 AM, Nikunj A. Dadhania wrote: From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Display unlimited when the memory cgroup settings says so. Unlimited is represented by INT64_MAX in memory cgroup. Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Reported-by: Justin Clift jcl...@redhat.com --- tools/virsh.c | 10 -- 1 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 55e2a68..bee875c 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2987,9 +2987,15 @@ cmdMemtune(vshControl * ctl, const vshCmd * cmd) params[i].value.l); break; case VIR_DOMAIN_MEMORY_PARAM_ULLONG: -vshPrint(ctl, %-15s: %llu\n, params[i].field, - params[i].value.ul); +{ +unsigned long long max_kbytes = INT64_MAX 10; Yuck - why do the clients have to know the magic value? Realised this but was late, and did not send a following patch :( Why not patch the source to actually return INT64_MAX rather than INT64_MAX10 when returning unlimited? Actually, due to the issue of cross-versioning between virsh and the actual libvirt running, we may have to check for both values. But even having a constant (VIR_DOMAIN_MEMORY_PARAM_UNLIMITED) rather than making guests recompute things might be nice. I like this option of having a constant and here is the patch. From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Display unlimited when the memory cgroup settings says so. Unlimited is represented by INT64_MAX in memory cgroup. Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Reported-by: Justin Clift jcl...@redhat.com --- include/libvirt/libvirt.h.in |1 + src/lxc/lxc_driver.c |2 +- src/qemu/qemu_driver.c |2 +- src/util/cgroup.c| 27 +-- src/util/cgroup.h|6 +++--- tools/virsh.c|9 +++-- 6 files changed, 34 insertions(+), 13 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 3c6a54a..cb53f6b 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -696,6 +696,7 @@ typedef enum { */ #define VIR_DOMAIN_MEMORY_FIELD_LENGTH 80 +#define VIR_DOMAIN_MEMORY_PARAM_UNLIMITED (UINT64_MAX) /** * VIR_DOMAIN_MEMORY_HARD_LIMIT: diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index eb58086..2db9954 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -815,7 +815,7 @@ static int lxcDomainGetMemoryParameters(virDomainPtr dom, int i; virCgroupPtr cgroup = NULL; virDomainObjPtr vm = NULL; -unsigned long val; +unsigned long long val; int ret = -1; int rc; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index e915705..6648c6a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7077,7 +7077,7 @@ static int qemuDomainGetMemoryParameters(virDomainPtr dom, int i; virCgroupPtr group = NULL; virDomainObjPtr vm = NULL; -unsigned long val; +unsigned long long val; int ret = -1; int rc; diff --git a/src/util/cgroup.c b/src/util/cgroup.c index 3ba6325..c81ebba 100644 --- a/src/util/cgroup.c +++ b/src/util/cgroup.c @@ -907,7 +907,7 @@ int virCgroupSetMemoryHardLimit(virCgroupPtr group, unsigned long kb) * * Returns: 0 on success */ -int virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long *kb) +int virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long long *kb) { long long unsigned int limit_in_bytes; int ret; @@ -915,7 +915,12 @@ int virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long *kb) VIR_CGROUP_CONTROLLER_MEMORY, memory.limit_in_bytes, limit_in_bytes); if (ret == 0) -*kb = (unsigned long) limit_in_bytes 10; +{ +if (limit_in_bytes != INT64_MAX) +*kb = (unsigned long long) limit_in_bytes 10; +else +*kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED; +} return ret; } @@ -944,7 +949,7 @@ int virCgroupSetMemorySoftLimit(virCgroupPtr group, unsigned long kb) * * Returns: 0 on success */ -int virCgroupGetMemorySoftLimit(virCgroupPtr group, unsigned long *kb) +int virCgroupGetMemorySoftLimit(virCgroupPtr group, unsigned long long *kb) { long long unsigned int limit_in_bytes; int ret; @@ -952,7 +957,12 @@ int virCgroupGetMemorySoftLimit(virCgroupPtr group, unsigned long *kb) VIR_CGROUP_CONTROLLER_MEMORY, memory.soft_limit_in_bytes, limit_in_bytes); if (ret == 0) -*kb = (unsigned long) limit_in_bytes 10; +{ +if (limit_in_bytes != INT64_MAX
Re: [libvirt] Need a better word than allocated or ascertained
CC'ing Balbir.. On Fri, 07 Jan 2011 10:33:08 +0100, Zdenek Styblik sty...@turnovfree.net wrote: On 01/07/2011 10:10 AM, Justin Clift wrote: On 07/01/2011, at 6:12 PM, Nikunj A. Dadhania wrote: snip Guaranteed sounds best to me. Thats not Gauranteed to the best of my knowlegde Balbir suggest enforced, I guessed i dropped it somewhere. https://www.redhat.com/archives/libvir-list/2010-August/msg00712.html Balbir's suggested wording (from the email): limit to enforce on memory contention Does that mean it's the minimum memory limit it would really like to have, but can't guarantee it? (ie it's not guaranteed) I'm getting a bit confused here. enforced really doesn't fit into the context, or does it? What should it say/explain? [soft-limit] Who is target audience? And I think the last question is very important, because your technical mambo-jumbo might be just fine and tip-top to the last bit, but if nobody else understands it, then such help seems to be a bit helpless to me. Meaning: * allocated/guaranteed I can imagine; * ascertained gave me really non-sense translation, although that might be caused by crappy dictionary; * enforced - uh ... how? what? when? Is it when host is running low on memory and/or there are many VMs competing for memory? If so, please explain it somewhere if it isn't already(yeah, I'm trying to figure out the meaning). Or what happens when memory reaches 'soft-limit'? ---SNIP--- Soft limit This limit causes nxqddb to display a warning dialog box(see figure 5.19) if the number of matches found from your search exceeds the specified limit. Hard limit This limit tells nxqddb to abort the search operation if ... ---SNIP--- source ~ http://www.hsdi.com/qddb/usersguide/node37.html Or got it all wrong(wouldn't be the first time :]). Take this reply easy as it sounds kind of furious to me. Zdenek -- Zdenek Styblik Net/Linux admin OS TurnovFree.net email: sty...@turnovfree.net jabber: sty...@jabber.turnovfree.net -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] Bug in virsh memtune on RHEL6?
On Fri, 7 Jan 2011 03:16:56 +1100, Justin Clift jcl...@redhat.com wrote: On 07/01/2011, at 2:48 AM, Eric Blake wrote: On 01/06/2011 08:29 AM, Justin Clift wrote: Hi all, Getting strange numbers from the virsh memtune command on RHEL 6. (git head compiled, rather than RHEL 6 packages) virsh # list Id Name State -- 4 Fedora_14_x64running virsh # memtune Fedora_14_x64 hard_limit : 9007199254740991 soft_limit : 9007199254740991 swap_hard_limit: 9007199254740991 Those numbers are supposed to be kilobytes, but the host box itself only has 12GB ram. Bug? Smells like a case of mistakenly treating either -1 or INT64_MAX as a valid value (that integer is 0x1f___, which happens to be UINT64_MAX11 or INT64_MAX10), rather than recognizing it as meaning unlimited or undeterminable. If unlimited is the intended meaning, virsh can probably be taught to display it differently, perhaps by also referencing the host's limits. Yeah, that sounds like it might be the cause. As Eric suggested, thats the value for unlimited, i.e. -1(64bit) and then (INT_MAX10) for getting kbytes. I will send a patch to display it as unlimited. Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] memtune: Let virsh know the unlimited value for memory tunables
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Display unlimited when the memory cgroup settings says so. Unlimited is represented by INT64_MAX in memory cgroup. Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Reported-by: Justin Clift jcl...@redhat.com --- tools/virsh.c | 10 -- 1 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 55e2a68..bee875c 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2987,9 +2987,15 @@ cmdMemtune(vshControl * ctl, const vshCmd * cmd) params[i].value.l); break; case VIR_DOMAIN_MEMORY_PARAM_ULLONG: -vshPrint(ctl, %-15s: %llu\n, params[i].field, - params[i].value.ul); +{ +unsigned long long max_kbytes = INT64_MAX 10; +if (params[i].value.ul == max_kbytes) +vshPrint(ctl, %-15s: unlimited\n, params[i].field); +else +vshPrint(ctl, %-15s: %llu\n, params[i].field, + params[i].value.ul); break; +} case VIR_DOMAIN_MEMORY_PARAM_DOUBLE: vshPrint(ctl, %-15s: %f\n, params[i].field, params[i].value.d); -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] Need a better word than allocated or ascertained
On Thu, 06 Jan 2011 09:52:57 -0700, Eric Blake ebl...@redhat.com wrote: On 01/06/2011 09:46 AM, Zdenek Styblik wrote: On 01/06/11 17:36, Justin Clift wrote: Hi us, [...] Ascertained doesn't really make sense to me in this context. Wondering if anyone has better suggestions? :) Hello, assured/guaranteed? Please please, not ascertained. In the name of all not-native-English speaking people :) Guaranteed sounds best to me. Thats not Gauranteed to the best of my knowlegde Balbir suggest enforced, I guessed i dropped it somewhere. https://www.redhat.com/archives/libvir-list/2010-August/msg00712.html Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCHv2] virsh: fix range of memtune command
On Wed, 20 Oct 2010 13:29:45 -0600, Eric Blake ebl...@redhat.com wrote: * tools/virsh.c (cmdMemtune): Use long long for memory sizes. Simplify allocation, and plug memory leak. --- No need to cripple virsh with a 32-bit limit. Change from v1: fix compilation failure, rebase on top of other recent memtune fixes tools/virsh.c | 19 --- 1 files changed, 8 insertions(+), 11 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index ca9a61e..6a11a7a 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2905,7 +2905,7 @@ static int cmdMemtune(vshControl * ctl, const vshCmd * cmd) { virDomainPtr dom; -int hard_limit, soft_limit, swap_hard_limit, min_guarantee; +long long hard_limit, soft_limit, swap_hard_limit, min_guarantee; int nparams = 0; unsigned int i = 0; virMemoryParameterPtr params = NULL, temp = NULL; @@ -2918,24 +2918,22 @@ cmdMemtune(vshControl * ctl, const vshCmd * cmd) return FALSE; hard_limit = -vshCommandOptInt(cmd, VIR_DOMAIN_MEMORY_HARD_LIMIT, hard_limit); +vshCommandOptLongLong(cmd, VIR_DOMAIN_MEMORY_HARD_LIMIT, NULL); if (hard_limit) nparams++; soft_limit = -vshCommandOptInt(cmd, VIR_DOMAIN_MEMORY_SOFT_LIMIT, soft_limit); +vshCommandOptLongLong(cmd, VIR_DOMAIN_MEMORY_SOFT_LIMIT, NULL); if (soft_limit) nparams++; swap_hard_limit = -vshCommandOptInt(cmd, VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT, - swap_hard_limit); +vshCommandOptLongLong(cmd, VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT, NULL); if (swap_hard_limit) nparams++; min_guarantee = -vshCommandOptInt(cmd, VIR_DOMAIN_MEMORY_MIN_GUARANTEE, - min_guarantee); +vshCommandOptLongLong(cmd, VIR_DOMAIN_MEMORY_MIN_GUARANTEE, NULL); if (min_guarantee) nparams++; @@ -2954,8 +2952,7 @@ cmdMemtune(vshControl * ctl, const vshCmd * cmd) } /* now go get all the memory parameters */ -params = vshMalloc(ctl, sizeof(virMemoryParameter) * nparams); -memset(params, 0, sizeof(virMemoryParameter) * nparams); +params = vshCalloc(ctl, nparams, sizeof(*params)); if (virDomainGetMemoryParameters(dom, params, nparams, 0) != 0) { vshError(ctl, %s, _(Unable to get memory parameters)); goto cleanup; @@ -2995,9 +2992,8 @@ cmdMemtune(vshControl * ctl, const vshCmd * cmd) ret = TRUE; } else { /* set the memory parameters */ -params = vshMalloc(ctl, sizeof(virMemoryParameter) * nparams); +params = vshCalloc(ctl, nparams, sizeof(*params)); -memset(params, 0, sizeof(virMemoryParameter) * nparams); for (i = 0; i nparams; i++) { temp = params[i]; temp-type = VIR_DOMAIN_MEMORY_PARAM_ULLONG; @@ -3037,6 +3033,7 @@ cmdMemtune(vshControl * ctl, const vshCmd * cmd) } cleanup: +VIR_FREE(params); virDomainFree(dom); return ret; } ACK Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] Update comments for the memory tunables macros
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com include/libvirt/libvirt.h.in: Update comment with actual description Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- include/libvirt/libvirt.h.in | 12 1 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index ca8e6fa..1b9874e 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -699,7 +699,8 @@ typedef enum { /** * VIR_DOMAIN_MEMORY_HARD_LIMIT: * - * Macro for the well-known tunable hard_limit. + * Macro for the memory tunable hard_limit: it represents the maximum memory + * the guest can use. */ #define VIR_DOMAIN_MEMORY_HARD_LIMIT hard_limit @@ -707,7 +708,8 @@ typedef enum { /** * VIR_DOMAIN_MEMORY_SOFT_LIMIT: * - * Macro for the well-known tunable soft_limit. + * Macro for the memory tunable soft_limit: it represents the memory upper + * limit enforced during memory contention. */ #define VIR_DOMAIN_MEMORY_SOFT_LIMIT soft_limit @@ -715,7 +717,8 @@ typedef enum { /** * VIR_DOMAIN_MEMORY_MIN_GUARANTEE: * - * Macro for the well-known tunable min_guarantee. + * Macro for the memory tunable min_guarantee: it represents the minimum + * memory guaranteed to be reserved for the guest. */ #define VIR_DOMAIN_MEMORY_MIN_GUARANTEE min_guarantee @@ -723,7 +726,8 @@ typedef enum { /** * VIR_DOMAIN_SWAP_HARD_LIMIT: * - * Macro for the well-known tunable swap_hard_limit. + * Macro for the swap tunable swap_hard_limit: it represents the maximum swap + * the guest can use. */ #define VIR_DOMAIN_SWAP_HARD_LIMIT swap_hard_limit -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] memtune: Add min_guarantee to the virsh tool
On Tue, 19 Oct 2010 15:00:21 +0200, Matthias Bolte matthias.bo...@googlemail.com wrote: 2010/10/18 Nikunj A. Dadhania nik...@linux.vnet.ibm.com: Hi, I am adding the min_guarantee to the memtune command with this patch. I have tested this at the virsh tool level. This parameter is not supported by QEMU or LXC. Can be used by ESX and in future by other hypervisors. Nikunj From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com tools/virsh.c: Add new memory tunable min_guarantee, currently the user would be ESX. Well, who said ESX could support this? :) I guess you did: https://www.redhat.com/archives/libvir-list/2010-August/msg00613.html === ESX itself also allows to set what's called memoryMinGaurantee in the thread, but this is not exposed in libvirt. === Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] memtune: Add min_guarantee to the virsh tool
On Tue, 19 Oct 2010 15:49:05 +0200, Daniel Veillard veill...@redhat.com wrote: On Tue, Oct 19, 2010 at 03:00:21PM +0200, Matthias Bolte wrote: 2010/10/18 Nikunj A. Dadhania nik...@linux.vnet.ibm.com: [...] tools/virsh.c: Add new memory tunable min_guarantee, currently the user would be ESX. Well, who said ESX could support this? :) I didn't, I just said that you added min_guarantee to libvirt, but didn't expose it in virsh. Hum ... I assumed there was an use case for it. On the other hand since it's now part of libvirt API as VIR_DOMAIN_MEMORY_MIN_GUARANTEE enum value, it's cleaner to have it available at the virsh level. If there is really no use (or no potential use in a reasonable future) for it, the best is to remove it altogether from the API and the of virsh, before next week release. Nikunj I could not find any reference to the well-known tunable min_guarantee (it's clearly not well known ...) but can you tell us where this comes from ? VMWare: === Reservation: Gauranteed lower bound on the amount of the physical memory that the host reserves for the VM even in case of the overcommit. The VM is allowed to allocate till this level and after it has hit the reservation, those pages are not reclaimed. In case, if guest is not using till the reservation, the host can use that portion of memory. And maybe in future cgroups. I would also appreciate a patch to include/libvirt/libvirt.h.in which change the comments for VIR_DOMAIN_MEMORY_HARD_LIMIT, VIR_DOMAIN_MEMORY_SOFT_LIMIT, VIR_DOMAIN_MEMORY_MIN_GUARANTEE, and VIR_DOMAIN_SWAP_HARD_LIMIT relapcing the non-reference well known with an actual description of what the tunable means. We cannot keep something that vague in the header and generated documentation, Sure, will send a patch Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] Update docs for memory parameters and memtune command
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com docs/formatdomain.html.in: Add memtune element details src/libvirt.c: Update virDomainGetMemoryParameters api description, make it more clear that the user first needs to call the api to get the number of parameters supported and then call again to get the values. tools/virsh.pod: Add usage of new command memtune in virsh manpage Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- docs/formatdomain.html.in | 21 + src/libvirt.c | 20 +--- tools/virsh.pod |8 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 8ec7446..9b4c6d7 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -194,6 +194,11 @@ lt;memoryBackinggt; lt;hugepages/gt; lt;/memoryBackinggt; + lt;memtunegt; +lt;hard_limitgt;1048576lt;/hard_limitgt; +lt;soft_limitgt;131072lt;/soft_limitgt; +lt;swap_hard_limitgt;2097152lt;/swap_hard_limitgt; + lt;/memtunegt; lt;vcpu cpuset=1-4,^3,6gt;2lt;/vcpugt; .../pre @@ -211,6 +216,22 @@ codehugepages/code element set within it. This tells the hypervisor that the guest should have its memory allocated using hugepages instead of the normal native page size./dd + dtcodememtune/code/dt + dd The optional codememtune/code element provides details + regarding the memory tuneable parameters for the domain. If this is + omitted, it defaults to the OS provided defaults./dd + dtcodehard_limit/code/dt + dd The optional codehard_limit/code element is the maximum memory + the guest can use. The units for this value are kilobytes (i.e. blocks + of 1024 bytes)/dd + dtcodesoft_limit/code/dt + dd The optional codesoft_limit/code element is the memory limit to + enforce during memory contention. The units for this value are + kilobytes (i.e. blocks of 1024 bytes)/dd + dtcodeswap_hard_limit/code/dt + dd The optional codeswap_hard_limit/code element is the maximum + swap the guest can use. The units for this value are kilobytes + (i.e. blocks of 1024 bytes)/dd dtcodevcpu/code/dt ddThe content of this element defines the number of virtual CPUs allocated for the guest OS, which must be between 1 and diff --git a/src/libvirt.c b/src/libvirt.c index 2868460..629d97b 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -3063,9 +3063,23 @@ error: * Get the memory parameters, the @params array will be filled with the values * equal to the number of parameters suggested by @nparams * - * As a special case, if @nparams is zero and @params is NULL, the API will - * set the number of parameters supported by the HV in @nparams and return - * SUCCESS. + * As the value of @nparams is dynamic, call the API setting @nparams to 0 and + * @params as NULL, the API returns the number of parameters supported by the + * HV by updating @nparams on SUCCESS. The caller should then allocate @params + * array, i.e. (sizeof(@virMemoryParameter) * @nparams) bytes and call the API + * again. + * + * Here is the sample code snippet: + * + * if ((virDomainGetMemoryParameters(dom, NULL, nparams, 0) == 0) + * (nparams != 0)) { + * params = vshMalloc(ctl, sizeof(virMemoryParameter) * nparams); + * memset(params, 0, sizeof(virMemoryParameter) * nparams); + * if (virDomainGetMemoryParameters(dom, params, nparams, 0)) { + * vshError(ctl, %s, _(Unable to get memory parameters)); + * goto error; + * } + * } * * This function requires privileged access to the hypervisor. This function * expects the caller to allocate the @param diff --git a/tools/virsh.pod b/tools/virsh.pod index e0471b1..cb8e942 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -456,6 +456,14 @@ Change the maximum memory allocation limit in the guest domain. This should not change the current memory use. The memory limit is specified in kilobytes. +=item Bmemtune Idomain-id + +Displays the domain memory parameters. + +=item Bmemtune Idomain-id optional I--hard-limit Bkilobytes optional I--soft-limit Bkilobytes optional I--swap-hard-limit Bkilobytes + +Allows you to set the domain memory parameters. LXC and QEMU/KVM supports these parameters. + =item Bsetvcpus Idomain-id Icount Change the number of virtual CPUs active in the guest domain. Note that -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Update docs for memory parameters and memtune command
On Mon, 18 Oct 2010 09:55:46 +0200, Matthias Bolte matthias.bo...@googlemail.com wrote: 2010/10/18 Nikunj A. Dadhania nik...@linux.vnet.ibm.com: From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com docs/formatdomain.html.in: Add memtune element details [...] @@ -211,6 +216,22 @@ codehugepages/code element set within it. This tells the hypervisor that the guest should have its memory allocated using hugepages instead of the normal native page size./dd + dtcodememtune/code/dt + dd The optional codememtune/code element provides details + regarding the memory tuneable parameters for the domain. If this is + omitted, it defaults to the OS provided defaults./dd + dtcodehard_limit/code/dt + dd The optional codehard_limit/code element is the maximum memory + the guest can use. The units for this value are kilobytes (i.e. blocks + of 1024 bytes)/dd Well, the maximum of memory a guest can use is also controlled by the memory and currentMemory element in some way. How does hard_limit relate to those two? memory and currentMemory are related to balloon size, while these are operating system provided limits. + dtcodesoft_limit/code/dt + dd The optional codesoft_limit/code element is the memory limit to + enforce during memory contention. The units for this value are + kilobytes (i.e. blocks of 1024 bytes)/dd Is this an upper or a lower limit? Does it mean in case of contention this guest may only use up to soft_limit kilobytes of memory (upper limit)? Or does it mean in case of contention make sure that this guest can access at least soft_limit kilobytes of memory (lower limit)? Upper limit of memory the guest can use(i.e upto soft_limit) during contention. Balbir, correct me if this isn't correct. How does this relate to the memory and currentMemory element? At present no relation, they are implemented by the OS. How does it related to the min_guarantee element? It is not related to min_guarantee. + dtcodeswap_hard_limit/code/dt + dd The optional codeswap_hard_limit/code element is the maximum + swap the guest can use. The units for this value are kilobytes + (i.e. blocks of 1024 bytes)/dd What about the min_guarantee element anyway? It's not implemented in virsh. Missed it, I will add the docs about min_gaurantee and send the updated patch. It is not implemented in virsh. However, I have taken care of parsing them in domain configuration. Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH] Update docs for memory parameters and memtune command
Hi Matthias, Here goes the updated patch. From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com docs/formatdomain.html.in: Add memtune element details, added min_guarantee src/libvirt.c: Update virDomainGetMemoryParameters api description, make it more clear that the user first needs to call the api to get the number of parameters supported and then call again to get the values. tools/virsh.pod: Add usage of new command memtune in virsh manpage Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- docs/formatdomain.html.in | 26 ++ src/libvirt.c | 20 +--- tools/virsh.pod |8 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 8ec7446..2b8ee34 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -194,6 +194,12 @@ lt;memoryBackinggt; lt;hugepages/gt; lt;/memoryBackinggt; + lt;memtunegt; +lt;hard_limitgt;1048576lt;/hard_limitgt; +lt;soft_limitgt;131072lt;/soft_limitgt; +lt;swap_hard_limitgt;2097152lt;/swap_hard_limitgt; +lt;min_guaranteegt;65536lt;/min_guaranteegt; + lt;/memtunegt; lt;vcpu cpuset=1-4,^3,6gt;2lt;/vcpugt; .../pre @@ -211,6 +217,26 @@ codehugepages/code element set within it. This tells the hypervisor that the guest should have its memory allocated using hugepages instead of the normal native page size./dd + dtcodememtune/code/dt + dd The optional codememtune/code element provides details + regarding the memory tuneable parameters for the domain. If this is + omitted, it defaults to the OS provided defaults./dd + dtcodehard_limit/code/dt + dd The optional codehard_limit/code element is the maximum memory + the guest can use. The units for this value are kilobytes (i.e. blocks + of 1024 bytes)/dd + dtcodesoft_limit/code/dt + dd The optional codesoft_limit/code element is the memory limit to + enforce during memory contention. The units for this value are + kilobytes (i.e. blocks of 1024 bytes)/dd + dtcodeswap_hard_limit/code/dt + dd The optional codeswap_hard_limit/code element is the maximum + swap the guest can use. The units for this value are kilobytes + (i.e. blocks of 1024 bytes)/dd + dtcodemin_guarantee/code/dt + dd The optional codemin_guarantee/code element is the guaranteed + minimum memory allocation for the guest. The units for this value are + kilobytes (i.e. blocks of 1024 bytes)/dd dtcodevcpu/code/dt ddThe content of this element defines the number of virtual CPUs allocated for the guest OS, which must be between 1 and diff --git a/src/libvirt.c b/src/libvirt.c index 2868460..629d97b 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -3063,9 +3063,23 @@ error: * Get the memory parameters, the @params array will be filled with the values * equal to the number of parameters suggested by @nparams * - * As a special case, if @nparams is zero and @params is NULL, the API will - * set the number of parameters supported by the HV in @nparams and return - * SUCCESS. + * As the value of @nparams is dynamic, call the API setting @nparams to 0 and + * @params as NULL, the API returns the number of parameters supported by the + * HV by updating @nparams on SUCCESS. The caller should then allocate @params + * array, i.e. (sizeof(@virMemoryParameter) * @nparams) bytes and call the API + * again. + * + * Here is the sample code snippet: + * + * if ((virDomainGetMemoryParameters(dom, NULL, nparams, 0) == 0) + * (nparams != 0)) { + * params = vshMalloc(ctl, sizeof(virMemoryParameter) * nparams); + * memset(params, 0, sizeof(virMemoryParameter) * nparams); + * if (virDomainGetMemoryParameters(dom, params, nparams, 0)) { + * vshError(ctl, %s, _(Unable to get memory parameters)); + * goto error; + * } + * } * * This function requires privileged access to the hypervisor. This function * expects the caller to allocate the @param diff --git a/tools/virsh.pod b/tools/virsh.pod index e0471b1..cb8e942 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -456,6 +456,14 @@ Change the maximum memory allocation limit in the guest domain. This should not change the current memory use. The memory limit is specified in kilobytes. +=item Bmemtune Idomain-id + +Displays the domain memory parameters. + +=item Bmemtune Idomain-id optional I--hard-limit Bkilobytes optional I--soft-limit Bkilobytes optional I--swap-hard-limit Bkilobytes + +Allows you to set the domain memory parameters. LXC and QEMU/KVM supports these parameters. + =item Bsetvcpus Idomain-id Icount Change the number of virtual CPUs active in the guest domain. Note that -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH] memtune: Add min_guarantee to the virsh tool
Hi, I am adding the min_guarantee to the memtune command with this patch. I have tested this at the virsh tool level. This parameter is not supported by QEMU or LXC. Can be used by ESX and in future by other hypervisors. Nikunj From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com tools/virsh.c: Add new memory tunable min_guarantee, currently the user would be ESX. tools/virsh.pod: Update the manpage Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- tools/virsh.c | 17 +++-- tools/virsh.pod |2 +- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index fe35eb9..e79bfbb 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2632,6 +2632,8 @@ static const vshCmdOptDef opts_memtune[] = { N_(Memory during contention in kilobytes)}, {VIR_DOMAIN_SWAP_HARD_LIMIT, VSH_OT_STRING, VSH_OFLAG_NONE, N_(Max swap in kilobytes)}, +{VIR_DOMAIN_MEMORY_MIN_GUARANTEE, VSH_OT_STRING, VSH_OFLAG_NONE, + N_(Min guaranteed memory in kilobytes)}, {NULL, 0, 0, NULL} }; @@ -2639,7 +2641,7 @@ static int cmdMemtune(vshControl * ctl, const vshCmd * cmd) { virDomainPtr dom; -int hard_limit, soft_limit, swap_hard_limit; +int hard_limit, soft_limit, swap_hard_limit, min_guarantee; int nparams = 0; unsigned int i = 0; virMemoryParameterPtr params = NULL, temp = NULL; @@ -2667,6 +2669,12 @@ cmdMemtune(vshControl * ctl, const vshCmd * cmd) if (swap_hard_limit) nparams++; +min_guarantee = +vshCommandOptInt(cmd, VIR_DOMAIN_MEMORY_MIN_GUARANTEE, + min_guarantee); +if (min_guarantee) +nparams++; + if (nparams == 0) { /* get the number of memory parameters */ if ((virDomainGetMemoryParameters(dom, NULL, nparams, 0) != 0) @@ -2711,7 +2719,7 @@ cmdMemtune(vshControl * ctl, const vshCmd * cmd) params[i].value.b); break; default: -vshPrint(ctl, unimplemented scheduler parameter type\n); +vshPrint(ctl, unimplemented memory parameter type\n); } } @@ -2746,6 +2754,11 @@ cmdMemtune(vshControl * ctl, const vshCmd * cmd) strncpy(temp-field, VIR_DOMAIN_SWAP_HARD_LIMIT, sizeof(temp-field)); swap_hard_limit = 0; +} else if (min_guarantee) { +temp-value.ul = min_guarantee; +strncpy(temp-field, VIR_DOMAIN_MEMORY_MIN_GUARANTEE, +sizeof(temp-field)); +min_guarantee = 0; } } if (virDomainSetMemoryParameters(dom, params, nparams, 0) != 0) diff --git a/tools/virsh.pod b/tools/virsh.pod index cb8e942..5f06360 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -460,7 +460,7 @@ kilobytes. Displays the domain memory parameters. -=item Bmemtune Idomain-id optional I--hard-limit Bkilobytes optional I--soft-limit Bkilobytes optional I--swap-hard-limit Bkilobytes +=item Bmemtune Idomain-id optional I--hard-limit Bkilobytes optional I--soft-limit Bkilobytes optional I--swap-hard-limit Bkilobytes -I--min-guarantee Bkilobytes Allows you to set the domain memory parameters. LXC and QEMU/KVM supports these parameters. -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v4 04/13] XML parsing for memory tunables
On Tue, 12 Oct 2010 16:54:39 +0200, Daniel Veillard veill...@redhat.com wrote: On Fri, Oct 08, 2010 at 05:45:23PM +0530, Nikunj A. Dadhania wrote: From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Adding parsing code for memory tunables in the domain xml file v4: * Add memtune in tests/qemuxml2xmltest.c * Fix: insert memtune element only when any of them is set v2: + Fix typo min_guarantee The patch is fine except the usual space and tabs mixups and the fact that a number of drivers still needed to be converted to the change of the definition structure. grep -- -memory src/*/* isn't that hard and would have shown that even the driver for your own IBM Phyp hardware failed to compile after your patch !! anyway once cleaned up the patch makes sensei, ACK, but please use make syntax-check and do not configure out drivers when you are developping patches, Thanks Daniel, Did not know about the make syntax-check. And as you guessed, I did not compile it for other drivers, just went out of my mind, I will take care next time. Regards, Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v4 07/13] Implement driver interface domainGetMemoryParamters for QEmu
On Tue, 12 Oct 2010 17:51:54 +0200, Daniel Veillard veill...@redhat.com wrote: On Fri, Oct 08, 2010 at 05:45:55PM +0530, Nikunj A. Dadhania wrote: From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com V4: * prototype change: add unsigned int flags Driver interface for getting memory parameters, eg. hard_limit, soft_limit and swap_hard_limit. +qemuReportError(VIR_ERR_INVALID_ARG, +%s, _(Invalid parameter count)); +goto cleanup; +} okay, this mean the application must always call with 0 first to get the exact value or this will break, fine but probably need to be made more clear from the description in libvirt.c TODO Sure, I will take care of updating the api desc in libvirt.c, I haven't used word always there. +if (virCgroupForDomain(driver-cgroup, vm-def-name, group, 0) != 0) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +_(cannot find cgroup for domain %s), vm-def-name); +goto cleanup; +} + +for (i = 0; i *nparams; i++) { +virMemoryParameterPtr param = params[i]; +val = 0; +param-value.ul = 0; +param-type = VIR_DOMAIN_MEMORY_FIELD_ULLONG; + +switch(i) { +case 0: /* fill memory hard limit here */ +rc = virCgroupGetMemoryHardLimit(group, val); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to get memory hard limit)); +continue; +} +if (virStrcpyStatic(param-field, VIR_DOMAIN_MEMORY_HARD_LIMIT) == NULL) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(Field memory hard limit too long for destination)); +continue; +} +param-value.ul = val; +break; + +case 1: /* fill memory soft limit here */ +rc = virCgroupGetMemorySoftLimit(group, val); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to get memory soft limit)); +continue; +} +if (virStrcpyStatic(param-field, VIR_DOMAIN_MEMORY_SOFT_LIMIT) == NULL) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(Field memory soft limit too long for destination)); +continue; +} +param-value.ul = val; +break; + +case 2: /* fill swap hard limit here */ +rc = virCgroupGetSwapHardLimit(group, val); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to get swap hard limit)); +continue; +} +if (virStrcpyStatic(param-field, VIR_DOMAIN_SWAP_HARD_LIMIT) == NULL) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(Field swap hard limit too long for destination)); +continue; +} +param-value.ul = val; +break; + +default: +break; +/* should not hit here */ +} +} Okay, I'm not sure we actually need a loop here, but it may help refactoring... I guess this is related to my previous thinking, if nparams QEMU_NB_MEM_PARAM, fill only till nparams and return. But with the change of the logic, I think loop may not be required now. I'm still having a problem with the code ignoring any error occuring in the loop, and fixing this in the same way. If there is an error the application *must* learn about it instead of trusting uninitialized memory as being data ! Maybe a memset is in order actually before entering that loop to avoid edge case problems... TODO too By TODO you mean the error handling, right? I am taking care of setting the values to zero currently, and it does not tell the application whether to use this value or not. One option could be adding VIR_DOMAIN_MEMORY_INVALID in virMemoryParameterType and setting it in the beginning of the loop. Comments? Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v4 10/13] Implement driver interface domainSetMemoryParamters for LXC
On Tue, 12 Oct 2010 18:32:19 +0200, Daniel Veillard veill...@redhat.com wrote: On Fri, Oct 08, 2010 at 05:46:28PM +0530, Nikunj A. Dadhania wrote: From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Add support in the lxc driver for various memory controllable parameters v4: + prototype change: add unsigned int flags v2: + Use #define string constants for hard_limit, etc + fix typo: min_guarantee Acked-by: Daniel P. Berrange berra...@redhat.com Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com [...] +if (vm == NULL) { +char uuidstr[VIR_UUID_STRING_BUFLEN]; +virUUIDFormat(dom-uuid, uuidstr); +lxcError(VIR_ERR_NO_DOMAIN, + _(No domain with matching uuid '%s'), uuidstr); +goto cleanup; +} Hum, the qemu driver was reporting if (vm == NULL) { qemuReportError(VIR_ERR_INTERNAL_ERROR, _(No such domain %s), dom-uuid); goto cleanup; } the 2 should be harmonized I guess, but since the LXC reporting is better I left this as a TODO, seems that's a more general cleanup needed between drivers. Let me look at this and I will provide a patch. +for (i = 0; i nparams; i++) { +virMemoryParameterPtr param = params[i]; + +if (STREQ(param-field, VIR_DOMAIN_MEMORY_HARD_LIMIT)) { +int rc; +if (param-type != VIR_DOMAIN_MEMORY_FIELD_ULLONG) { +lxcError(VIR_ERR_INVALID_ARG, %s, + _(invalid type for memory hard_limit tunable, expected a 'ullong')); +continue; +} + +rc = virCgroupSetMemoryHardLimit(cgroup, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set memory hard_limit tunable)); +} +} else if (STREQ(param-field, VIR_DOMAIN_MEMORY_SOFT_LIMIT)) { +int rc; +if (param-type != VIR_DOMAIN_MEMORY_FIELD_ULLONG) { +lxcError(VIR_ERR_INVALID_ARG, %s, + _(invalid type for memory soft_limit tunable, expected a 'ullong')); +continue; +} + +rc = virCgroupSetMemorySoftLimit(cgroup, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set memory soft_limit tunable)); +} +} else if (STREQ(param-field, VIR_DOMAIN_SWAP_HARD_LIMIT)) { +int rc; +if (param-type != VIR_DOMAIN_MEMORY_FIELD_ULLONG) { +lxcError(VIR_ERR_INVALID_ARG, %s, + _(invalid type for swap_hard_limit tunable, expected a 'ullong')); +continue; +} + +rc = virCgroupSetSwapHardLimit(cgroup, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set swap_hard_limit tunable)); +} +} else if (STREQ(param-field, VIR_DOMAIN_MEMORY_MIN_GUARANTEE)) { +lxcError(VIR_ERR_INVALID_ARG, + _(Memory tunable `%s' not implemented), param-field); +} else { +lxcError(VIR_ERR_INVALID_ARG, + _(Parameter `%s' not supported), param-field); +} +} +ret = 0; Same problem of error reporting as in the QEmu driver, I moved ret = 0; before the loop and et ret = -1; on all errors ! One clarification: Will it return error back immediately if an error occurs? Or will it try setting all of them one by one and if anyone of them succeed, success is returned. +cleanup: +if (cgroup) +virCgroupFree(cgroup); +if (vm) +virDomainObjUnlock(vm); +lxcDriverUnlock(driver); +return ret; +} + After those modifications, ACK, applied to my tree, Thanks Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v4 13/13] Remote protocol changes and implements virDomainSet/GetMemoryParameters
On Tue, 12 Oct 2010 19:27:05 +0200, Daniel Veillard veill...@redhat.com wrote: On Fri, Oct 08, 2010 at 05:47:03PM +0530, Nikunj A. Dadhania wrote: From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com v4: * prototype change: add unsigned int flags, regenerate files v3: * Squased all the remote driver changes to one single big patch and auto-generated is around 40% * Implements domainSetMemoryParameters and domainGetMemoryParameters for remote driver daemon/remote.c src/remote/remote_driver.c * Auto generate the files using rpcgen and helper scripts in daemon/ directory src/remote/remote_protocol.x daemon/remote_dispatch_args.h daemon/remote_dispatch_prototypes.h daemon/remote_dispatch_ret.h daemon/remote_dispatch_table.h src/remote/remote_protocol.c src/remote/remote_protocol.h Acked-by: Daniel P. Berrange berra...@redhat.com Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com [...] +nparams = args-params.params_len; +nparams = args-flags; obvious bug: flags = args-flags; Oops :) - CP That reminds me that I didn't see flags being checked against 0 on the QEmu and LXC drivers, we should check them ! I will take care of this. +if (nparams REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX) { +remoteDispatchFormatError (rerr, %s, _(nparams too large)); +return -1; I did a lot of reformating and code cleanups in the non-generated files, to try to keep the source readable on a 80 columns editor. Thanks, With that done, I think I can ACK the whole serie, and pushed it, but there is still a number of small TODOs for which I would appreciate patches, thanks a lot ! Thanks a lot to you and Daniel Berrange. Both of you have spend a lot of time on reviewing and on top of that fixing the patches as well. Regards, Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 04/13] XML parsing for memory tunables
On Tue, 12 Oct 2010 19:19:21 +0530, Balbir Singh bal...@linux.vnet.ibm.com wrote: * Nikunj A. Dadhania nik...@linux.vnet.ibm.com [2010-10-08 14:43:34]: On Fri, 8 Oct 2010 14:10:53 +0530, Balbir Singh bal...@linux.vnet.ibm.com wrote: * Nikunj A. Dadhania nik...@linux.vnet.ibm.com [2010-10-08 12:00:44]: On Thu, 7 Oct 2010 12:49:29 +0100, Daniel P. Berrange berra...@redhat.com wrote: On Mon, Oct 04, 2010 at 12:47:22PM +0530, Nikunj A. Dadhania wrote: On Mon, 4 Oct 2010 12:16:42 +0530, Balbir Singh bal...@linux.vnet.ibm.com wrote: * Nikunj A. Dadhania nik...@linux.vnet.ibm.com [2010-09-28 15:26:30]: snip +unsigned long hard_limit; +unsigned long soft_limit; +unsigned long min_guarantee; +unsigned long swap_hard_limit; The hard_limit, soft_limit, swap_hard_limit are s64 and the value is in bytes. What is the unit supported in this implementation? Actually if libvirt is built on 32bit these aren't big enough - make them into 'unsigned long long' data types I reckon. I was thinking that as we are having the unit of KB, we would be able to represent 2^42 bytes of memory limit, ie. 4 Terabytes. Won't this suffice in case of 32bit? How would you represent -1 (2^63 -1) as unlimited or max limit we use today? I think I have answered this question in the thread: this is specific to cgroup that -1 means unlimited, this may not be true for other HVs. OK, so how do we handle unlimited values in general? At present, API does not have a way to do this. We have added a flag in the API, let me think of some way I could use it for such setting unlimited values. Regards Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 04/13] XML parsing for memory tunables
On Thu, 7 Oct 2010 12:49:29 +0100, Daniel P. Berrange berra...@redhat.com wrote: On Mon, Oct 04, 2010 at 12:47:22PM +0530, Nikunj A. Dadhania wrote: On Mon, 4 Oct 2010 12:16:42 +0530, Balbir Singh bal...@linux.vnet.ibm.com wrote: * Nikunj A. Dadhania nik...@linux.vnet.ibm.com [2010-09-28 15:26:30]: snip +unsigned long hard_limit; +unsigned long soft_limit; +unsigned long min_guarantee; +unsigned long swap_hard_limit; The hard_limit, soft_limit, swap_hard_limit are s64 and the value is in bytes. What is the unit supported in this implementation? Actually if libvirt is built on 32bit these aren't big enough - make them into 'unsigned long long' data types I reckon. I was thinking that as we are having the unit of KB, we would be able to represent 2^42 bytes of memory limit, ie. 4 Terabytes. Won't this suffice in case of 32bit? Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 12/13] Adding memtune command to virsh tool
On Thu, 7 Oct 2010 12:59:57 +0100, Daniel P. Berrange berra...@redhat.com wrote: On Tue, Sep 28, 2010 at 03:27:19PM +0530, Nikunj A. Dadhania wrote: +LIBVIRT_0.8.5 { +global: +virDomainSetMemoryParameters; +virDomainGetMemoryParameters; +} LIBVIRT_0.8.2; This chunk should actually be with the change to 'src/libvirt.c' in the second patch. Done Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 04/13] XML parsing for memory tunables
On Thu, 7 Oct 2010 12:48:26 +0100, Daniel P. Berrange berra...@redhat.com wrote: On Tue, Sep 28, 2010 at 03:26:30PM +0530, Nikunj A. Dadhania wrote: From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Adding parsing code for memory tunables in the domain xml file v2: + Fix typo min_guarantee Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/conf/domain_conf.c | 50 +--- src/conf/domain_conf.h | 12 --- src/esx/esx_vmx.c | 30 +- src/lxc/lxc_controller.c |2 +- src/lxc/lxc_driver.c | 12 +-- src/openvz/openvz_driver.c |8 --- src/qemu/qemu_conf.c |8 --- src/qemu/qemu_driver.c | 18 src/test/test_driver.c | 12 +-- src/uml/uml_conf.c |2 +- src/uml/uml_driver.c | 14 ++-- 11 files changed, 104 insertions(+), 64 deletions(-) ACK, looks fine, though it'd be good to add one or two example data files to tests/qemuxml2xmltest.c to ensure that we roundtrip through the XML parser+formatter correctly. Sure, will add the files, and send the updated series Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 01/13] Adding structure and defines for virDomainSet/GetMemoryParameters
On Thu, 7 Oct 2010 12:45:22 +0100, Daniel P. Berrange berra...@redhat.com wrote: On Tue, Sep 28, 2010 at 03:26:15PM +0530, Nikunj A. Dadhania wrote: + +/* Set memory tunables for the domain*/ +int virDomainSetMemoryParameters(virDomainPtr domain, +virMemoryParameterPtr params, +int nparams); +/* Get memory tunables for the domain, caller allocates the params if nparams + * is zero and params is NULL, the domain returns back number of parameters + * supported by the HV. This could be used by the caller to allocate the + * memory and call with params structure allocated. + */ +int virDomainGetMemoryParameters(virDomainPtr domain, +virMemoryParameterPtr params, +int *nparams); We should add an 'unsigned int flags' parameter to both of these, so we can extend their semantics in the future. I have added this and mentioned it as unused at present. The comment here can be moved to the libvirt.c file so it gets picked up in the API docs. I have already put a detailed comment in libvirt.c for API docs. I am getting rid of this for now. Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 04/13] XML parsing for memory tunables
On Fri, 8 Oct 2010 14:10:53 +0530, Balbir Singh bal...@linux.vnet.ibm.com wrote: * Nikunj A. Dadhania nik...@linux.vnet.ibm.com [2010-10-08 12:00:44]: On Thu, 7 Oct 2010 12:49:29 +0100, Daniel P. Berrange berra...@redhat.com wrote: On Mon, Oct 04, 2010 at 12:47:22PM +0530, Nikunj A. Dadhania wrote: On Mon, 4 Oct 2010 12:16:42 +0530, Balbir Singh bal...@linux.vnet.ibm.com wrote: * Nikunj A. Dadhania nik...@linux.vnet.ibm.com [2010-09-28 15:26:30]: snip +unsigned long hard_limit; +unsigned long soft_limit; +unsigned long min_guarantee; +unsigned long swap_hard_limit; The hard_limit, soft_limit, swap_hard_limit are s64 and the value is in bytes. What is the unit supported in this implementation? Actually if libvirt is built on 32bit these aren't big enough - make them into 'unsigned long long' data types I reckon. I was thinking that as we are having the unit of KB, we would be able to represent 2^42 bytes of memory limit, ie. 4 Terabytes. Won't this suffice in case of 32bit? How would you represent -1 (2^63 -1) as unlimited or max limit we use today? I think I have answered this question in the thread: this is specific to cgroup that -1 means unlimited, this may not be true for other HVs. Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v4 00/13] Implement memory control api
Changelog from v3: * Add unsigned int flags to the public api and make corresponding changes further down till the drivers(qemu, lxc and remote) * Move exporting of the api's to patch two * Added memtune test in tests/qemuxml2xmltest.c * Fix: src/conf/domain_conf.c - print memtune element only if tunable is present * Fix: src/qemu/qemu_driver.c - call cgroup apis only if nonzero * Fix: src/lxc/lxc_controller.c - call cgroup apis only if nonzero Changelog from v2: * Implement virDomainGetMemoryParameters api * Add virDomainGetMemoryParameters to memtune command in virsh * Provide domainGetMemoryParameters implementation for remote, QEmu and LXC drivers * Auto-generate code using rpcgen and remote_generate_stubs.pl * Squash all the changes related to remote driver and remote protocol into one single patch. * Patch re-ordering Changelog from v1: * Patch re-ordering for compilation * Folded python bindings changes to patch 01 * Added defines for string constants for memory tunables * Typo fix: min_guarantee * Moved initialization of function pointers in driver.h patch This patch series implement public api for controlling various memory tunables exported by the OS. This is based on the following RFC[1]. * Implement virDomainSetMemoryParameters api * Provide implementation for remote, QEmu and LXC drivers * Enable memory controller support fro QEmu * virsh command for runtime changes to the memory parameters * Domain configuration parsing for memory control parameters * Cgroup memory controller code for memory hard_limit/soft_limit, swap hard_limit To Do * Python bindings is just a place holder, need to implement 1. https://www.redhat.com/archives/libvir-list/2010-August/msg00607.html 2. https://www.redhat.com/archives/libvir-list/2010-August/msg00699.html --- Nikunj A. Dadhania (13): Adding structure and defines for virDomainSet/GetMemoryParameters Adding virDomainSetMemoryParameters and virDomainGetMemoryParameters API Adds xml entries for memory tunables XML parsing for memory tunables Implement cgroup memory controller tunables Implement driver interface domainSetMemoryParamters for QEmu Implement driver interface domainGetMemoryParamters for QEmu Adding memtunables to qemuSetupCgroup Adding memtunables to libvirt-lxc command Implement driver interface domainSetMemoryParamters for LXC Implement driver interface domainGetMemoryParamters for LXC Adding memtune command to virsh tool Remote protocol changes and implements virDomainSet/GetMemoryParameters daemon/remote.c | 162 + daemon/remote_dispatch_args.h|2 daemon/remote_dispatch_prototypes.h | 16 + daemon/remote_dispatch_ret.h |1 daemon/remote_dispatch_table.h | 10 + docs/schemas/domain.rng | 31 +++ include/libvirt/libvirt.h.in | 63 + python/generator.py |2 python/libvirt-override-api.xml | 12 + python/libvirt-override.c| 14 + src/conf/domain_conf.c | 54 src/conf/domain_conf.h | 12 + src/driver.h | 14 + src/esx/esx_driver.c |2 src/esx/esx_vmx.c| 30 +- src/libvirt.c| 104 + src/libvirt_private.syms |6 src/libvirt_public.syms |6 src/lxc/lxc_controller.c | 32 +++ src/lxc/lxc_driver.c | 215 +- src/openvz/openvz_driver.c | 10 - src/phyp/phyp_driver.c |2 src/qemu/qemu.conf |4 src/qemu/qemu_conf.c | 11 - src/qemu/qemu_driver.c | 265 +- src/remote/remote_driver.c | 151 + src/remote/remote_protocol.c | 88 +++ src/remote/remote_protocol.h | 58 + src/remote/remote_protocol.x | 44 src/test/test_driver.c | 14 + src/uml/uml_conf.c |2 src/uml/uml_driver.c | 16 + src/util/cgroup.c| 106 + src/util/cgroup.h|7 + src/xen/xen_driver.c |2 tests/qemuxml2argvdata/qemuxml2argv-memtune.args |1 tests/qemuxml2argvdata/qemuxml2argv-memtune.xml | 30 ++ tests/qemuxml2xmltest.c |1 tools/virsh.c
[libvirt] [PATCH v4 01/13] Adding structure and defines for virDomainSet/GetMemoryParameters
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com This patch adds a structure virMemoryParameter, it contains the name of the parameter and the type of the parameter along with a union. v4: + Add unsigned int flags to the public api for future extensions v3: + Protoype for virDomainGetMemoryParameters and dummy python binding. v2: + Includes dummy python bindings for the library to build cleanly. + Define string constants like hard_limit, etc. + re-order this patch. Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- include/libvirt/libvirt.h.in| 63 +++ python/generator.py |2 + python/libvirt-override-api.xml | 12 +++ python/libvirt-override.c | 14 + 4 files changed, 91 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index b45f7ec..75a84fb 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -674,6 +674,69 @@ int virDomainGetInfo (virDomainPtr domain, char * virDomainGetSchedulerType(virDomainPtr domain, int *nparams); +/** + * virDomainMemoryParameterType: + * + * A memory parameter field type + */ +typedef enum { +VIR_DOMAIN_MEMORY_FIELD_INT = 1, /* integer case */ +VIR_DOMAIN_MEMORY_FIELD_UINT= 2, /* unsigned integer case */ +VIR_DOMAIN_MEMORY_FIELD_LLONG = 3, /* long long case */ +VIR_DOMAIN_MEMORY_FIELD_ULLONG = 4, /* unsigned long long case */ +VIR_DOMAIN_MEMORY_FIELD_DOUBLE = 5, /* double case */ +VIR_DOMAIN_MEMORY_FIELD_BOOLEAN = 6 /* boolean(character) case */ +} virMemoryParameterType; + +/** + * VIR_DOMAIN_MEMORY_FIELD_LENGTH: + * + * Macro providing the field length of virMemoryParameter + */ + +#define VIR_DOMAIN_MEMORY_FIELD_LENGTH 80 +#define VIR_DOMAIN_MEMORY_HARD_LIMIT hard_limit +#define VIR_DOMAIN_MEMORY_SOFT_LIMIT soft_limit +#define VIR_DOMAIN_MEMORY_MIN_GUARANTEE min_guarantee +#define VIR_DOMAIN_SWAP_HARD_LIMIT swap_hard_limit + +/** + * virDomainMemoryParameter: + * + * a virDomainMemoryParameter is the set of scheduler parameters + */ + +typedef struct _virMemoryParameter virMemoryParameter; + +struct _virMemoryParameter { +char field[VIR_DOMAIN_MEMORY_FIELD_LENGTH]; /* parameter name */ +int type; /* parameter type */ +union { +int i; /* data for integer case */ +unsigned int ui;/* data for unsigned integer case */ +long long int l;/* data for long long integer case */ +unsigned long long int ul; /* data for unsigned long long integer case */ +double d; /* data for double case */ +char b; /* data for char case */ +} value; /* parameter value */ +}; + +/** + * virMemoryParameterPtr: + * + * a virMemoryParameterPtr is a pointer to a virMemoryParameter structure. + */ + +typedef virMemoryParameter *virMemoryParameterPtr; + +/* Set memory tunables for the domain*/ +int virDomainSetMemoryParameters(virDomainPtr domain, +virMemoryParameterPtr params, +int nparams, unsigned int flags); +int virDomainGetMemoryParameters(virDomainPtr domain, +virMemoryParameterPtr params, +int *nparams, unsigned int flags); + /* * Dynamic control of domains */ diff --git a/python/generator.py b/python/generator.py index d876df6..68009b9 100755 --- a/python/generator.py +++ b/python/generator.py @@ -306,6 +306,8 @@ skip_impl = ( 'virDomainGetSchedulerType', 'virDomainGetSchedulerParameters', 'virDomainSetSchedulerParameters', +'virDomainSetMemoryParameters', +'virDomainGetMemoryParameters', 'virDomainGetVcpus', 'virDomainPinVcpu', 'virSecretGetValue', diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml index ca16993..f209608 100644 --- a/python/libvirt-override-api.xml +++ b/python/libvirt-override-api.xml @@ -162,6 +162,18 @@ arg name='domain' type='virDomainPtr' info='pointer to domain object'/ arg name='params' type='virSchedParameterPtr' info='pointer to scheduler parameter objects'/ /function +function name='virDomainSetMemoryParameters' file='python' + infoChange the memory tunables/info + return type='int' info='-1 in case of error, 0 in case of success.'/ + arg name='domain' type='virDomainPtr' info='pointer to domain object'/ + arg name='params' type='virMemoryParameterPtr' info='pointer to memory tunable objects'/ +/function +function name='virDomainGetMemoryParameters' file='python' + infoGet the memory parameters, the @params array will be filled with the values./info + return type='int' info='-1 in case of error, 0 in case of success.'/ + arg name='domain' type
[libvirt] [PATCH v4 04/13] XML parsing for memory tunables
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Adding parsing code for memory tunables in the domain xml file v4: * Add memtune in tests/qemuxml2xmltest.c * Fix: insert memtune element only when any of them is set v2: + Fix typo min_guarantee Acked-by: Daniel P. Berrange berra...@redhat.com Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/conf/domain_conf.c | 54 +++--- src/conf/domain_conf.h | 12 - src/esx/esx_vmx.c| 30 ++-- src/lxc/lxc_controller.c |2 - src/lxc/lxc_driver.c | 12 ++--- src/openvz/openvz_driver.c |8 ++- src/qemu/qemu_conf.c |8 ++- src/qemu/qemu_driver.c | 18 --- src/test/test_driver.c | 12 ++--- src/uml/uml_conf.c |2 - src/uml/uml_driver.c | 14 +++--- tests/qemuxml2argvdata/qemuxml2argv-memtune.args |1 tests/qemuxml2argvdata/qemuxml2argv-memtune.xml | 30 tests/qemuxml2xmltest.c |1 14 files changed, 140 insertions(+), 64 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memtune.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memtune.xml diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 539d443..146e7a7 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4235,19 +4235,38 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, def-description = virXPathString(string(./description[1]), ctxt); /* Extract domain memory */ -if (virXPathULong(string(./memory[1]), ctxt, def-maxmem) 0) { +if (virXPathULong(string(./memory[1]), ctxt, + def-mem.max_balloon) 0) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, %s, _(missing memory element)); goto error; } -if (virXPathULong(string(./currentMemory[1]), ctxt, def-memory) 0) -def-memory = def-maxmem; +if (virXPathULong(string(./currentMemory[1]), ctxt, + def-mem.cur_balloon) 0) +def-mem.cur_balloon = def-mem.max_balloon; node = virXPathNode(./memoryBacking/hugepages, ctxt); if (node) -def-hugepage_backed = 1; - +def-mem.hugepage_backed = 1; + +/* Extract other memory tunables */ +if (virXPathULong(string(./memtune/hard_limit), ctxt, + def-mem.hard_limit) 0) +def-mem.hard_limit = 0; + +if (virXPathULong(string(./memtune/soft_limit[1]), ctxt, + def-mem.soft_limit) 0) +def-mem.soft_limit = 0; + +if (virXPathULong(string(./memtune/min_guarantee[1]), ctxt, + def-mem.min_guarantee) 0) +def-mem.min_guarantee = 0; + +if (virXPathULong(string(./memtune/swap_hard_limit[1]), ctxt, + def-mem.swap_hard_limit) 0) +def-mem.swap_hard_limit = 0; + if (virXPathULong(string(./vcpu[1]), ctxt, def-vcpus) 0) def-vcpus = 1; @@ -6384,10 +6403,29 @@ char *virDomainDefFormat(virDomainDefPtr def, virBufferEscapeString(buf, description%s/description\n, def-description); -virBufferVSprintf(buf, memory%lu/memory\n, def-maxmem); +virBufferVSprintf(buf, memory%lu/memory\n, def-mem.max_balloon); virBufferVSprintf(buf, currentMemory%lu/currentMemory\n, - def-memory); -if (def-hugepage_backed) { + def-mem.cur_balloon); + +/* add memtune only if there are any */ +if(def-mem.hard_limit || def-mem.hard_limit || def-mem.hard_limit) +virBufferVSprintf(buf, memtune\n); +if (def-mem.hard_limit) { +virBufferVSprintf(buf, hard_limit%lu/hard_limit\n, + def-mem.hard_limit); +} +if (def-mem.soft_limit) { +virBufferVSprintf(buf, soft_limit%lu/soft_limit\n, + def-mem.soft_limit); +} +if (def-mem.swap_hard_limit) { +virBufferVSprintf(buf, swap_hard_limit%lu/swap_hard_limit\n, + def-mem.swap_hard_limit); +} +if(def-mem.hard_limit || def-mem.hard_limit || def-mem.hard_limit) +virBufferVSprintf(buf, /memtune\n); + +if (def-mem.hugepage_backed) { virBufferAddLit(buf, memoryBacking\n); virBufferAddLit(buf, hugepages/\n); virBufferAddLit(buf, /memoryBacking\n); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 9bf13d8..7c5215f 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -866,9 +866,15 @@ struct _virDomainDef { char *name; char *description; -unsigned long memory; -unsigned long maxmem
[libvirt] [PATCH v4 02/13] Adding virDomainSetMemoryParameters and virDomainGetMemoryParameters API
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Public api to set/get memory tunables supported by the hypervisors. RFC: https://www.redhat.com/archives/libvir-list/2010-August/msg00607.html v4: * Move exporting public API to this patch * Add unsigned int flags to the public api for future extensions v3: * Add domainGetMemoryParamters and NULL in all the driver interface v2: * Initialize domainSetMemoryParameters to NULL in all the driver interface structure. Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/driver.h | 14 ++ src/esx/esx_driver.c |2 + src/libvirt.c | 104 src/libvirt_public.syms|6 +++ src/lxc/lxc_driver.c |2 + src/openvz/openvz_driver.c |2 + src/phyp/phyp_driver.c |2 + src/qemu/qemu_driver.c |2 + src/remote/remote_driver.c |2 + src/test/test_driver.c |2 + src/uml/uml_driver.c |2 + src/xen/xen_driver.c |2 + 12 files changed, 142 insertions(+), 0 deletions(-) diff --git a/src/driver.h b/src/driver.h index e443c1c..32aeb04 100644 --- a/src/driver.h +++ b/src/driver.h @@ -128,6 +128,18 @@ typedef int (*virDrvDomainSetMemory) (virDomainPtr domain, unsigned long memory); typedef int +(*virDrvDomainSetMemoryParameters) +(virDomainPtr domain, + virMemoryParameterPtr params, + int nparams, + unsigned int flags); +typedef int +(*virDrvDomainGetMemoryParameters) +(virDomainPtr domain, + virMemoryParameterPtr params, + int *nparams, + unsigned int flags); +typedef int (*virDrvDomainGetInfo) (virDomainPtr domain, virDomainInfoPtr info); typedef int @@ -575,6 +587,8 @@ struct _virDriver { virDrvDomainRevertToSnapshot domainRevertToSnapshot; virDrvDomainSnapshotDelete domainSnapshotDelete; virDrvQemuDomainMonitorCommand qemuDomainMonitorCommand; +virDrvDomainSetMemoryParameters domainSetMemoryParameters; +virDrvDomainGetMemoryParameters domainGetMemoryParameters; }; typedef int diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index e382950..e959be2 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4217,6 +4217,8 @@ static virDriver esxDriver = { esxDomainRevertToSnapshot, /* domainRevertToSnapshot */ esxDomainSnapshotDelete, /* domainSnapshotDelete */ NULL,/* qemuDomainMonitorCommand */ +NULL,/* domainSetMemoryParameters */ +NULL,/* domainGetMemoryParameters */ }; diff --git a/src/libvirt.c b/src/libvirt.c index ca383ba..d964a44 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -3000,6 +3000,110 @@ error: } /** + * virDomainSetMemoryParameters: + * @domain: pointer to domain object + * @params: pointer to memory parameter objects + * @nparams: number of memory parameter (this value should be same or + * less than the number of parameters supported) + * @flags: currently unused, for future extension + * + * Change the memory tunables + * This function requires privileged access to the hypervisor. + * + * Returns -1 in case of error, 0 in case of success. + */ +int +virDomainSetMemoryParameters(virDomainPtr domain, +virMemoryParameterPtr params, +int nparams, unsigned int flags) +{ +virConnectPtr conn; +DEBUG(domain=%p, params=%p, nparams=%d, flags=%u, domain, params, nparams, flags); + +virResetLastError(); + +if (!VIR_IS_CONNECTED_DOMAIN(domain)) { +virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); +virDispatchError(NULL); +return -1; +} +if (domain-conn-flags VIR_CONNECT_RO) { +virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); +goto error; +} +conn = domain-conn; + +if (conn-driver-domainSetMemoryParameters) { +int ret; +ret = conn-driver-domainSetMemoryParameters (domain, params, nparams, flags); +if (ret 0) +goto error; +return ret; +} + +virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: +virDispatchError(domain-conn); +return -1; +} + +/** + * virDomainGetMemoryParameters: + * @domain: pointer to domain object + * @params: pointer to memory parameter object + * (return value, allocated by the caller) + * @nparams: pointer to number of memory parameters + * @flags: currently unused, for future extension + * + * Get
[libvirt] [PATCH v4 05/13] Implement cgroup memory controller tunables
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Provides interfaces for setting/getting memory tunables like hard_limit, soft_limit and swap_hard_limit Acked-by: Balbir Singh bal...@linux.vnet.ibm.com Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/libvirt_private.syms |6 +++ src/util/cgroup.c| 106 ++ src/util/cgroup.h|7 +++ 3 files changed, 119 insertions(+), 0 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 301b0ef..09b108c 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -77,6 +77,12 @@ virCgroupControllerTypeFromString; virCgroupGetCpuacctUsage; virCgroupGetFreezerState; virCgroupSetFreezerState; +virCgroupSetMemoryHardLimit; +virCgroupGetMemoryHardLimit; +virCgroupSetMemorySoftLimit; +virCgroupGetMemorySoftLimit; +virCgroupSetSwapHardLimit; +virCgroupGetSwapHardLimit; # cpu.h diff --git a/src/util/cgroup.c b/src/util/cgroup.c index 024036a..f94db12 100644 --- a/src/util/cgroup.c +++ b/src/util/cgroup.c @@ -874,6 +874,112 @@ int virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb) } /** + * virCgroupSetMemoryHardLimit: + * + * @group: The cgroup to change memory hard limit for + * @kb: The memory amount in kilobytes + * + * Returns: 0 on success + */ +int virCgroupSetMemoryHardLimit(virCgroupPtr group, unsigned long kb) +{ +return virCgroupSetMemory(group, kb); +} + +/** + * virCgroupGetMemoryHardLimit: + * + * @group: The cgroup to get the memory hard limit for + * @kb: The memory amount in kilobytes + * + * Returns: 0 on success + */ +int virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long *kb) +{ +long long unsigned int limit_in_bytes; +int ret; +ret = virCgroupGetValueU64(group, + VIR_CGROUP_CONTROLLER_MEMORY, + memory.limit_in_bytes, limit_in_bytes); +if (ret == 0) +*kb = (unsigned long) limit_in_bytes 10; +return ret; +} + +/** + * virCgroupSetMemorySoftLimit: + * + * @group: The cgroup to change memory soft limit for + * @kb: The memory amount in kilobytes + * + * Returns: 0 on success + */ +int virCgroupSetMemorySoftLimit(virCgroupPtr group, unsigned long kb) +{ +return virCgroupSetValueU64(group, +VIR_CGROUP_CONTROLLER_MEMORY, +memory.soft_limit_in_bytes, +kb 10); +} + + +/** + * virCgroupGetMemorySoftLimit: + * + * @group: The cgroup to get the memory soft limit for + * @kb: The memory amount in kilobytes + * + * Returns: 0 on success + */ +int virCgroupGetMemorySoftLimit(virCgroupPtr group, unsigned long *kb) +{ +long long unsigned int limit_in_bytes; +int ret; +ret = virCgroupGetValueU64(group, + VIR_CGROUP_CONTROLLER_MEMORY, + memory.soft_limit_in_bytes, limit_in_bytes); +if (ret == 0) +*kb = (unsigned long) limit_in_bytes 10; +return ret; +} + +/** + * virCgroupSetSwapHardLimit: + * + * @group: The cgroup to change swap hard limit for + * @kb: The swap amount in kilobytes + * + * Returns: 0 on success + */ +int virCgroupSetSwapHardLimit(virCgroupPtr group, unsigned long kb) +{ +return virCgroupSetValueU64(group, +VIR_CGROUP_CONTROLLER_MEMORY, +memory.memsw.limit_in_bytes, +kb 10); +} + +/** + * virCgroupGetSwapHardLimit: + * + * @group: The cgroup to get swap hard limit for + * @kb: The swap amount in kilobytes + * + * Returns: 0 on success + */ +int virCgroupGetSwapHardLimit(virCgroupPtr group, unsigned long *kb) +{ +long long unsigned int limit_in_bytes; +int ret; +ret = virCgroupGetValueU64(group, + VIR_CGROUP_CONTROLLER_MEMORY, + memory.memsw.limit_in_bytes, limit_in_bytes); +if (ret == 0) +*kb = (unsigned long) limit_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 2bea49f..b8f2d08 100644 --- a/src/util/cgroup.h +++ b/src/util/cgroup.h @@ -43,6 +43,13 @@ int virCgroupAddTask(virCgroupPtr group, pid_t pid); int virCgroupSetMemory(virCgroupPtr group, unsigned long kb); int virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb); +int virCgroupSetMemoryHardLimit(virCgroupPtr group, unsigned long kb); +int virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long *kb); +int virCgroupSetMemorySoftLimit(virCgroupPtr group, unsigned long kb); +int virCgroupGetMemorySoftLimit(virCgroupPtr group, unsigned long *kb); +int virCgroupSetSwapHardLimit(virCgroupPtr group, unsigned long kb); +int virCgroupGetSwapHardLimit(virCgroupPtr group, unsigned long *kb); + int virCgroupDenyAllDevices(virCgroupPtr group
[libvirt] [PATCH v4 03/13] Adds xml entries for memory tunables
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com The patch adds xml entries to the domain.rng file. v2: + Fix typo min_guarantee Acked-by: Daniel P. Berrange berra...@redhat.com Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- docs/schemas/domain.rng | 31 +++ 1 files changed, 31 insertions(+), 0 deletions(-) diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index 2e0457b..6cbace0 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -299,6 +299,37 @@ /optional /element /optional + + !-- All the memory/swap related tunables would go in the memtune -- + optional + element name=memtune + !-- Maximum memory the VM can use -- + optional + element name=hard_limit + ref name=memoryKB/ + /element + /optional + !-- Minimum memory ascertained for the VM during contention -- + optional + element name=soft_limit + ref name=memoryKB/ + /element + /optional + !-- Minimum amount of memory required to start the VM -- + optional + element name=min_guarantee + ref name=memoryKB/ + /element + /optional + !-- Maximum swap area the VM can use -- + optional + element name=swap_hard_limit + ref name=memoryKB/ + /element + /optional + /element + /optional + optional element name=vcpu optional -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v4 09/13] Adding memtunables to libvirt-lxc command
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com v4: * Fix: call cgroup apis only if tunables are non zero v1: libvirt-lxc now configures the hardlimit, softlimit and swaplimit, if specified in the domain xml file or picks up the defaults. Acked-by: Daniel P. Berrange berra...@redhat.com Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/lxc/lxc_controller.c | 30 ++ 1 files changed, 30 insertions(+), 0 deletions(-) diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 82ecce0..258130d 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -109,6 +109,36 @@ static int lxcSetContainerResources(virDomainDefPtr def) def-name); goto cleanup; } + +if(def-mem.hard_limit) { +rc = virCgroupSetMemoryHardLimit(cgroup, def-mem.hard_limit); +if (rc != 0) { +virReportSystemError(-rc, + _(Unable to set memory hard limit for domain %s), + def-name); +goto cleanup; +} +} + +if(def-mem.soft_limit) { +rc = virCgroupSetMemorySoftLimit(cgroup, def-mem.soft_limit); +if (rc != 0) { +virReportSystemError(-rc, + _(Unable to set memory soft limit for domain %s), + def-name); +goto cleanup; +} +} + +if(def-mem.swap_hard_limit) { +rc = virCgroupSetSwapHardLimit(cgroup, def-mem.swap_hard_limit); +if (rc != 0) { +virReportSystemError(-rc, + _(Unable to set swap hard limit for domain %s), + def-name); +goto cleanup; +} +} rc = virCgroupDenyAllDevices(cgroup); if (rc != 0) { -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v4 10/13] Implement driver interface domainSetMemoryParamters for LXC
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Add support in the lxc driver for various memory controllable parameters v4: + prototype change: add unsigned int flags v2: + Use #define string constants for hard_limit, etc + fix typo: min_guarantee Acked-by: Daniel P. Berrange berra...@redhat.com Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/lxc/lxc_driver.c | 91 +- 1 files changed, 90 insertions(+), 1 deletions(-) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 8977835..984a5fa 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -677,6 +677,95 @@ cleanup: return ret; } +static int lxcDomainSetMemoryParameters(virDomainPtr dom, +virMemoryParameterPtr params, +int nparams, +unsigned int flags ATTRIBUTE_UNUSED) +{ +lxc_driver_t *driver = dom-conn-privateData; +int i; +virCgroupPtr cgroup = NULL; +virDomainObjPtr vm = NULL; +int ret = -1; + +lxcDriverLock(driver); +vm = virDomainFindByUUID(driver-domains, dom-uuid); + +if (vm == NULL) { +char uuidstr[VIR_UUID_STRING_BUFLEN]; +virUUIDFormat(dom-uuid, uuidstr); +lxcError(VIR_ERR_NO_DOMAIN, + _(No domain with matching uuid '%s'), uuidstr); +goto cleanup; +} + +if (virCgroupForDomain(driver-cgroup, vm-def-name, cgroup, 0) != 0) { +lxcError(VIR_ERR_INTERNAL_ERROR, + _(Unable to get cgroup for %s), vm-def-name); +goto cleanup; +} + +for (i = 0; i nparams; i++) { +virMemoryParameterPtr param = params[i]; + +if (STREQ(param-field, VIR_DOMAIN_MEMORY_HARD_LIMIT)) { +int rc; +if (param-type != VIR_DOMAIN_MEMORY_FIELD_ULLONG) { +lxcError(VIR_ERR_INVALID_ARG, %s, + _(invalid type for memory hard_limit tunable, expected a 'ullong')); +continue; +} + +rc = virCgroupSetMemoryHardLimit(cgroup, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set memory hard_limit tunable)); +} +} else if (STREQ(param-field, VIR_DOMAIN_MEMORY_SOFT_LIMIT)) { +int rc; +if (param-type != VIR_DOMAIN_MEMORY_FIELD_ULLONG) { +lxcError(VIR_ERR_INVALID_ARG, %s, + _(invalid type for memory soft_limit tunable, expected a 'ullong')); +continue; +} + +rc = virCgroupSetMemorySoftLimit(cgroup, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set memory soft_limit tunable)); +} +} else if (STREQ(param-field, VIR_DOMAIN_SWAP_HARD_LIMIT)) { +int rc; +if (param-type != VIR_DOMAIN_MEMORY_FIELD_ULLONG) { +lxcError(VIR_ERR_INVALID_ARG, %s, + _(invalid type for swap_hard_limit tunable, expected a 'ullong')); +continue; +} + +rc = virCgroupSetSwapHardLimit(cgroup, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set swap_hard_limit tunable)); +} +} else if (STREQ(param-field, VIR_DOMAIN_MEMORY_MIN_GUARANTEE)) { +lxcError(VIR_ERR_INVALID_ARG, + _(Memory tunable `%s' not implemented), param-field); +} else { +lxcError(VIR_ERR_INVALID_ARG, + _(Parameter `%s' not supported), param-field); +} +} +ret = 0; + +cleanup: +if (cgroup) +virCgroupFree(cgroup); +if (vm) +virDomainObjUnlock(vm); +lxcDriverUnlock(driver); +return ret; +} + static char *lxcDomainDumpXML(virDomainPtr dom, int flags) { @@ -2620,7 +2709,7 @@ static virDriver lxcDriver = { NULL, /* domainRevertToSnapshot */ NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ -NULL, /* domainSetMemoryParameters */ +lxcDomainSetMemoryParameters, /* domainSetMemoryParameters */ NULL, /* domainGetMemoryParameters */ }; -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v4 11/13] Implement driver interface domainGetMemoryParamters for LXC
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com v4: * prototype change: add unsigned int flags Driver interface for getting memory parameters, eg. hard_limit, soft_limit and swap_hard_limit. Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/lxc/lxc_driver.c | 114 ++ 1 files changed, 113 insertions(+), 1 deletions(-) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 984a5fa..036dedf 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -766,6 +766,118 @@ cleanup: return ret; } +static int lxcDomainGetMemoryParameters(virDomainPtr dom, +virMemoryParameterPtr params, +int *nparams, +unsigned int flags ATTRIBUTE_UNUSED) +{ +lxc_driver_t *driver = dom-conn-privateData; +int i; +virCgroupPtr cgroup = NULL; +virDomainObjPtr vm = NULL; +unsigned long val; +int ret = -1; +int rc; + +lxcDriverLock(driver); +vm = virDomainFindByUUID(driver-domains, dom-uuid); + +if (vm == NULL) { +char uuidstr[VIR_UUID_STRING_BUFLEN]; +virUUIDFormat(dom-uuid, uuidstr); +lxcError(VIR_ERR_NO_DOMAIN, + _(No domain with matching uuid '%s'), uuidstr); +goto cleanup; +} + +if ((*nparams) == 0) { +/* Current number of memory parameters supported by cgroups is 3 + * FIXME: Magic number, need to see where should this go + */ +*nparams = 3; +ret = 0; +goto cleanup; +} +if ((*nparams) != 3) { +lxcError(VIR_ERR_INVALID_ARG, + %s, _(Invalid parameter count)); +goto cleanup; +} + +if (virCgroupForDomain(driver-cgroup, vm-def-name, cgroup, 0) != 0) { +lxcError(VIR_ERR_INTERNAL_ERROR, + _(Unable to get cgroup for %s), vm-def-name); +goto cleanup; +} + +for (i = 0; i *nparams; i++) { +virMemoryParameterPtr param = params[i]; +val = 0; +param-value.ul = 0; +param-type = VIR_DOMAIN_MEMORY_FIELD_ULLONG; + +switch(i) { +case 0: /* fill memory hard limit here */ +rc = virCgroupGetMemoryHardLimit(cgroup, val); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to get memory hard limit)); +continue; +} +if (virStrcpyStatic(param-field, VIR_DOMAIN_MEMORY_HARD_LIMIT) == NULL) { +lxcError(VIR_ERR_INTERNAL_ERROR, + %s, _(Field memory hard limit too long for destination)); +continue; +} +param-value.ul = val; +break; + +case 1: /* fill memory soft limit here */ +rc = virCgroupGetMemorySoftLimit(cgroup, val); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to get memory soft limit)); +continue; +} +if (virStrcpyStatic(param-field, VIR_DOMAIN_MEMORY_SOFT_LIMIT) == NULL) { +lxcError(VIR_ERR_INTERNAL_ERROR, + %s, _(Field memory soft limit too long for destination)); +continue; +} +param-value.ul = val; +break; + +case 2: /* fill swap hard limit here */ +rc = virCgroupGetSwapHardLimit(cgroup, val); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to get swap hard limit)); +continue; +} +if (virStrcpyStatic(param-field, VIR_DOMAIN_SWAP_HARD_LIMIT) == NULL) { +lxcError(VIR_ERR_INTERNAL_ERROR, + %s, _(Field swap hard limit too long for destination)); +continue; +} +param-value.ul = val; +break; + +default: +break; +/* should not hit here */ +} +} +ret = 0; + +cleanup: +if (cgroup) +virCgroupFree(cgroup); +if (vm) +virDomainObjUnlock(vm); +lxcDriverUnlock(driver); +return ret; +} + static char *lxcDomainDumpXML(virDomainPtr dom, int flags) { @@ -2710,7 +2822,7 @@ static virDriver lxcDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ lxcDomainSetMemoryParameters, /* domainSetMemoryParameters */ -NULL, /* domainGetMemoryParameters */ +lxcDomainGetMemoryParameters, /* domainGetMemoryParameters */ }; static virStateDriver lxcStateDriver = { -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v4 12/13] Adding memtune command to virsh tool
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com The command helps to control the memory/swap parameters for the system, for eg. hard_limit (max memory the vm can use), soft_limit (limit during memory contention), swap_hard_limit(max swap the vm can use) v4: + virDomainSet/GetMemoryParameters prototype change + Move exporting of the symbol to patch 2 v3: + Added call to virDomainGetMemoryParameters and print them. + Added virDomainGetMemoryParameters and virDomainSetMemoryParamters to libvirt_public.syms v2: + Use #define string constants for hard_limit, etc Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- tools/virsh.c | 130 + 1 files changed, 130 insertions(+), 0 deletions(-) diff --git a/tools/virsh.c b/tools/virsh.c index 85014f2..a9fcc28 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2614,6 +2614,135 @@ cmdSetmaxmem(vshControl *ctl, const vshCmd *cmd) } /* + * memtune command + */ +static const vshCmdInfo info_memtune[] = { +{help, N_(Get/Set memory paramters)}, +{desc, N_(Get/Set the current memory paramters for the guest domain.\n \ +To get the memory parameters use following command: \n\n \ +virsh # memtune domain)}, +{NULL, NULL} +}; + +static const vshCmdOptDef opts_memtune[] = { +{domain, VSH_OT_DATA, VSH_OFLAG_REQ, N_(domain name, id or uuid)}, +{VIR_DOMAIN_MEMORY_HARD_LIMIT, VSH_OT_STRING, VSH_OFLAG_NONE, N_(Max memory in kilobytes)}, +{VIR_DOMAIN_MEMORY_SOFT_LIMIT, VSH_OT_STRING, VSH_OFLAG_NONE, N_(Memory during contention in kilobytes)}, +{VIR_DOMAIN_SWAP_HARD_LIMIT, VSH_OT_STRING, VSH_OFLAG_NONE, N_(Max swap in kilobytes)}, +{NULL, 0, 0, NULL} +}; + +static int +cmdMemtune(vshControl *ctl, const vshCmd *cmd) +{ +virDomainPtr dom; +int hard_limit, soft_limit, swap_hard_limit; +int nparams = 0; +unsigned int i = 0; +virMemoryParameterPtr params = NULL, temp = NULL; +int ret = FALSE; + +if (!vshConnectionUsability(ctl, ctl-conn)) +return FALSE; + +if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) +return FALSE; + +hard_limit = vshCommandOptInt(cmd, VIR_DOMAIN_MEMORY_HARD_LIMIT, hard_limit); +if (hard_limit) +nparams++; + +soft_limit = vshCommandOptInt(cmd, VIR_DOMAIN_MEMORY_SOFT_LIMIT, soft_limit); +if (soft_limit) +nparams++; + +swap_hard_limit = vshCommandOptInt(cmd, VIR_DOMAIN_SWAP_HARD_LIMIT, swap_hard_limit); +if (swap_hard_limit) +nparams++; + +if(nparams == 0) { +/* get the number of memory parameters */ +if (virDomainGetMemoryParameters(dom, NULL, nparams, 0) != 0 (nparams != 0)) { +vshError(ctl, %s, _(Unable to get number of memory parameters)); +goto cleanup; +} + +/* now go get all the memory parameters */ +params = vshMalloc(ctl, sizeof(virMemoryParameter)* nparams); +memset(params, 0, sizeof(virMemoryParameter)* nparams); +if (virDomainGetMemoryParameters(dom, params, nparams, 0)) { +vshError(ctl, %s, _(Unable to get memory parameters)); +goto cleanup; +} + +for (i = 0; i nparams; i++){ +switch (params[i].type) { +case VIR_DOMAIN_MEMORY_FIELD_INT: +vshPrint(ctl, %-15s: %d\n, params[i].field, params[i].value.i); +break; +case VIR_DOMAIN_MEMORY_FIELD_UINT: +vshPrint(ctl, %-15s: %u\n, params[i].field, params[i].value.ui); +break; +case VIR_DOMAIN_MEMORY_FIELD_LLONG: +vshPrint(ctl, %-15s: %lld\n, params[i].field, params[i].value.l); +break; +case VIR_DOMAIN_MEMORY_FIELD_ULLONG: +vshPrint(ctl, %-15s: %llu\n, params[i].field, params[i].value.ul); +break; +case VIR_DOMAIN_MEMORY_FIELD_DOUBLE: +vshPrint(ctl, %-15s: %f\n, params[i].field, params[i].value.d); +break; +case VIR_DOMAIN_MEMORY_FIELD_BOOLEAN: +vshPrint(ctl, %-15s: %d\n, params[i].field, params[i].value.b); +break; +default: +vshPrint(ctl, not implemented scheduler parameter type\n); +} +} + +ret = TRUE; +} else { +/* set the memory parameters */ +params = vshMalloc(ctl, sizeof(virMemoryParameter)* nparams); + +memset(params, 0, sizeof(virMemoryParameter)* nparams); +for(i = 0; i nparams; i++) +{ +temp = params[i]; +temp-type = VIR_DOMAIN_MEMORY_FIELD_ULLONG; + +/* + * Some magic here, this is used to fill the params structure with + * the valid arguments passed, after filling the particular + * argument we purposely make them 0, so on the next pass it goes
[libvirt] [PATCH v4 08/13] Adding memtunables to qemuSetupCgroup
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com v4: * Fix: call cgroup apis only if tunables are non zero QEmu startup would pick up the memory tunables specified in the domain configuration file. Acked-by: Daniel P. Berrange berra...@redhat.com Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/qemu/qemu.conf |4 ++-- src/qemu/qemu_conf.c |3 ++- src/qemu/qemu_driver.c | 34 ++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf index dc8eb83..bfb9f6a 100644 --- a/src/qemu/qemu.conf +++ b/src/qemu/qemu.conf @@ -111,13 +111,13 @@ # the adminsitrator has mounted cgroups. eg # # mkdir /dev/cgroup -# mount -t cgroup -o devices,cpu none /dev/cgroup +# mount -t cgroup -o devices,cpu,memory none /dev/cgroup # # They can be mounted anywhere, and different controlers # can be mounted in different locations. libvirt will detect # where they are located. # -# cgroup_controllers = [ cpu, devices ] +# cgroup_controllers = [ cpu, devices, memory ] # This is the basic set of devices allowed / required by # all virtual machines. diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 731c554..3f5c1ac 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -275,7 +275,8 @@ int qemudLoadDriverConfig(struct qemud_driver *driver, } else { driver-cgroupControllers = (1 VIR_CGROUP_CONTROLLER_CPU) | -(1 VIR_CGROUP_CONTROLLER_DEVICES); +(1 VIR_CGROUP_CONTROLLER_DEVICES) | +(1 VIR_CGROUP_CONTROLLER_MEMORY); } for (i = 0 ; i VIR_CGROUP_CONTROLLER_LAST ; i++) { if (driver-cgroupControllers (1 i)) { diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 8eaa762..70b9bac 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3495,6 +3495,40 @@ static int qemuSetupCgroup(struct qemud_driver *driver, goto cleanup; } +if ((rc = qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_MEMORY))) { +if (vm-def-mem.hard_limit != 0) { +rc = virCgroupSetMemoryHardLimit(cgroup, vm-def-mem.hard_limit); +if (rc != 0) { +virReportSystemError(-rc, + _(Unable to set memory hard limit for domain %s), + vm-def-name); +goto cleanup; +} +} +if (vm-def-mem.soft_limit != 0) { +rc = virCgroupSetMemorySoftLimit(cgroup, vm-def-mem.soft_limit); +if (rc != 0) { +virReportSystemError(-rc, + _(Unable to set memory soft limit for domain %s), + vm-def-name); +goto cleanup; +} +} + +if (vm-def-mem.swap_hard_limit != 0) { +rc = virCgroupSetSwapHardLimit(cgroup, vm-def-mem.swap_hard_limit); +if (rc != 0) { +virReportSystemError(-rc, + _(Unable to set swap hard limit for domain %s), + vm-def-name); +goto cleanup; +} +} +} else { +VIR_WARN(Memory cgroup is disabled in qemu configuration file: %s, + vm-def-name); +} + done: virCgroupFree(cgroup); return 0; -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v4 07/13] Implement driver interface domainGetMemoryParamters for QEmu
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com V4: * prototype change: add unsigned int flags Driver interface for getting memory parameters, eg. hard_limit, soft_limit and swap_hard_limit. Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/qemu/qemu_driver.c | 120 1 files changed, 119 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 471db39..8eaa762 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -9458,6 +9458,124 @@ cleanup: return ret; } +static int qemuDomainGetMemoryParameters(virDomainPtr dom, + virMemoryParameterPtr params, + int *nparams, + unsigned int flags ATTRIBUTE_UNUSED) +{ +struct qemud_driver *driver = dom-conn-privateData; +int i; +virCgroupPtr group = NULL; +virDomainObjPtr vm = NULL; +unsigned long val; +int ret = -1; +int rc; + +qemuDriverLock(driver); + +if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_MEMORY)) { +qemuReportError(VIR_ERR_NO_SUPPORT, +__FUNCTION__); +goto cleanup; +} + +vm = virDomainFindByUUID(driver-domains, dom-uuid); + +if (vm == NULL) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +_(No such domain %s), dom-uuid); +goto cleanup; +} + +if ((*nparams) == 0) { +/* Current number of memory parameters supported by cgroups is 3 + * FIXME: Magic number, need to see where should this go + */ +*nparams = 3; +ret = 0; +goto cleanup; +} + +if ((*nparams) != 3) { +qemuReportError(VIR_ERR_INVALID_ARG, +%s, _(Invalid parameter count)); +goto cleanup; +} + +if (virCgroupForDomain(driver-cgroup, vm-def-name, group, 0) != 0) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +_(cannot find cgroup for domain %s), vm-def-name); +goto cleanup; +} + +for (i = 0; i *nparams; i++) { +virMemoryParameterPtr param = params[i]; +val = 0; +param-value.ul = 0; +param-type = VIR_DOMAIN_MEMORY_FIELD_ULLONG; + +switch(i) { +case 0: /* fill memory hard limit here */ +rc = virCgroupGetMemoryHardLimit(group, val); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to get memory hard limit)); +continue; +} +if (virStrcpyStatic(param-field, VIR_DOMAIN_MEMORY_HARD_LIMIT) == NULL) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(Field memory hard limit too long for destination)); +continue; +} +param-value.ul = val; +break; + +case 1: /* fill memory soft limit here */ +rc = virCgroupGetMemorySoftLimit(group, val); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to get memory soft limit)); +continue; +} +if (virStrcpyStatic(param-field, VIR_DOMAIN_MEMORY_SOFT_LIMIT) == NULL) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(Field memory soft limit too long for destination)); +continue; +} +param-value.ul = val; +break; + +case 2: /* fill swap hard limit here */ +rc = virCgroupGetSwapHardLimit(group, val); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to get swap hard limit)); +continue; +} +if (virStrcpyStatic(param-field, VIR_DOMAIN_SWAP_HARD_LIMIT) == NULL) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +%s, _(Field swap hard limit too long for destination)); +continue; +} +param-value.ul = val; +break; + +default: +break; +/* should not hit here */ +} +} +ret = 0; + +cleanup: +if (group) +virCgroupFree(group); +if (vm) +virDomainObjUnlock(vm); +qemuDriverUnlock(driver); +return ret; +} + static int qemuSetSchedulerParameters(virDomainPtr dom, virSchedParameterPtr params, int nparams) @@ -12804,7 +12922,7 @@ static virDriver qemuDriver = { qemuDomainSnapshotDelete, /* domainSnapshotDelete */ qemuDomainMonitorCommand, /* qemuDomainMonitorCommand */ qemuDomainSetMemoryParameters, /* domainSetMemoryParameters */ -NULL
[libvirt] [PATCH v4 13/13] Remote protocol changes and implements virDomainSet/GetMemoryParameters
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com v4: * prototype change: add unsigned int flags, regenerate files v3: * Squased all the remote driver changes to one single big patch and auto-generated is around 40% * Implements domainSetMemoryParameters and domainGetMemoryParameters for remote driver daemon/remote.c src/remote/remote_driver.c * Auto generate the files using rpcgen and helper scripts in daemon/ directory src/remote/remote_protocol.x daemon/remote_dispatch_args.h daemon/remote_dispatch_prototypes.h daemon/remote_dispatch_ret.h daemon/remote_dispatch_table.h src/remote/remote_protocol.c src/remote/remote_protocol.h Acked-by: Daniel P. Berrange berra...@redhat.com Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- daemon/remote.c | 162 +++ daemon/remote_dispatch_args.h |2 daemon/remote_dispatch_prototypes.h | 16 +++ daemon/remote_dispatch_ret.h|1 daemon/remote_dispatch_table.h | 10 ++ src/remote/remote_driver.c | 153 + src/remote/remote_protocol.c| 88 +++ src/remote/remote_protocol.h| 58 + src/remote/remote_protocol.x| 44 +- 9 files changed, 531 insertions(+), 3 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 6b67678..d5a8a9c 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -2332,6 +2332,168 @@ remoteDispatchDomainSetMemory (struct qemud_server *server ATTRIBUTE_UNUSED, } static int +remoteDispatchDomainSetMemoryParameters (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_set_memory_parameters_args *args, + void *ret ATTRIBUTE_UNUSED) +{ +virDomainPtr dom; +int i, r, nparams; +virMemoryParameterPtr params; +unsigned int flags; + +nparams = args-params.params_len; +nparams = args-flags; + +if (nparams REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX) { +remoteDispatchFormatError (rerr, %s, _(nparams too large)); +return -1; +} +if (VIR_ALLOC_N(params, nparams) 0) { +remoteDispatchOOMError(rerr); +return -1; +} + +/* Deserialise parameters. */ +for (i = 0; i nparams; ++i) { +if (virStrcpyStatic(params[i].field, args-params.params_val[i].field) == NULL) { +remoteDispatchFormatError(rerr, _(Field %s too big for destination), + args-params.params_val[i].field); +return -1; +} +params[i].type = args-params.params_val[i].value.type; +switch (params[i].type) { +case VIR_DOMAIN_MEMORY_FIELD_INT: +params[i].value.i = args-params.params_val[i].value.remote_memory_param_value_u.i; break; +case VIR_DOMAIN_MEMORY_FIELD_UINT: +params[i].value.ui = args-params.params_val[i].value.remote_memory_param_value_u.ui; break; +case VIR_DOMAIN_MEMORY_FIELD_LLONG: +params[i].value.l = args-params.params_val[i].value.remote_memory_param_value_u.l; break; +case VIR_DOMAIN_MEMORY_FIELD_ULLONG: +params[i].value.ul = args-params.params_val[i].value.remote_memory_param_value_u.ul; break; +case VIR_DOMAIN_MEMORY_FIELD_DOUBLE: +params[i].value.d = args-params.params_val[i].value.remote_memory_param_value_u.d; break; +case VIR_DOMAIN_MEMORY_FIELD_BOOLEAN: +params[i].value.b = args-params.params_val[i].value.remote_memory_param_value_u.b; break; +} +} + +dom = get_nonnull_domain (conn, args-dom); +if (dom == NULL) { +VIR_FREE(params); +remoteDispatchConnError(rerr, conn); +return -1; +} + +r = virDomainSetMemoryParameters (dom, params, nparams, flags); +virDomainFree(dom); +VIR_FREE(params); +if (r == -1) { +remoteDispatchConnError(rerr, conn); +return -1; +} + +return 0; +} + +static int remoteDispatchDomainGetMemoryParameters (struct qemud_server *server, +struct qemud_client *client, +virConnectPtr conn, +remote_message_header *hdr, +remote_error *rerr, + remote_domain_get_memory_parameters_args *args
[libvirt] [PATCH v4 06/13] Implement driver interface domainSetMemoryParamters for QEmu
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Driver interface for setting memory hard_limit, soft_limit and swap hard_limit. v4: + prototype change: include unsigned int flags arg v2: + Use #define string constants for hard_limit, etc. + fix typo: min_guarantee Acked-by: Daniel P. Berrange berra...@redhat.com Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/qemu/qemu_driver.c | 95 +++- 1 files changed, 94 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index bf4373a..471db39 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -9365,6 +9365,99 @@ cleanup: return ret; } + +static int qemuDomainSetMemoryParameters(virDomainPtr dom, + virMemoryParameterPtr params, + int nparams, + unsigned int flags ATTRIBUTE_UNUSED) +{ +struct qemud_driver *driver = dom-conn-privateData; +int i; +virCgroupPtr group = NULL; +virDomainObjPtr vm = NULL; +int ret = -1; + +qemuDriverLock(driver); +if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_MEMORY)) { +qemuReportError(VIR_ERR_NO_SUPPORT, +__FUNCTION__); +goto cleanup; +} + +vm = virDomainFindByUUID(driver-domains, dom-uuid); + +if (vm == NULL) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +_(No such domain %s), dom-uuid); +goto cleanup; +} + +if (virCgroupForDomain(driver-cgroup, vm-def-name, group, 0) != 0) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +_(cannot find cgroup for domain %s), vm-def-name); +goto cleanup; +} + +for (i = 0; i nparams; i++) { +virMemoryParameterPtr param = params[i]; + +if (STREQ(param-field, VIR_DOMAIN_MEMORY_HARD_LIMIT)) { +int rc; +if (param-type != VIR_DOMAIN_MEMORY_FIELD_ULLONG) { +qemuReportError(VIR_ERR_INVALID_ARG, %s, +_(invalid type for memory hard_limit tunable, expected a 'ullong')); +continue; +} + +rc = virCgroupSetMemoryHardLimit(group, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set memory hard_limit tunable)); +} +} else if (STREQ(param-field, VIR_DOMAIN_MEMORY_SOFT_LIMIT)) { +int rc; +if (param-type != VIR_DOMAIN_MEMORY_FIELD_ULLONG) { +qemuReportError(VIR_ERR_INVALID_ARG, %s, +_(invalid type for memory soft_limit tunable, expected a 'ullong')); +continue; +} + +rc = virCgroupSetMemorySoftLimit(group, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set memory soft_limit tunable)); +} +} else if (STREQ(param-field, VIR_DOMAIN_SWAP_HARD_LIMIT)) { +int rc; +if (param-type != VIR_DOMAIN_MEMORY_FIELD_ULLONG) { +qemuReportError(VIR_ERR_INVALID_ARG, %s, +_(invalid type for swap_hard_limit tunable, expected a 'ullong')); +continue; +} + +rc = virCgroupSetSwapHardLimit(group, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set swap_hard_limit tunable)); +} +} else if (STREQ(param-field, VIR_DOMAIN_MEMORY_MIN_GUARANTEE)) { +qemuReportError(VIR_ERR_INVALID_ARG, +_(Memory tunable `%s' not implemented), param-field); +} else { +qemuReportError(VIR_ERR_INVALID_ARG, +_(Parameter `%s' not supported), param-field); +} +} +ret = 0; + +cleanup: +virCgroupFree(group); +if (vm) +virDomainObjUnlock(vm); +qemuDriverUnlock(driver); +return ret; +} + static int qemuSetSchedulerParameters(virDomainPtr dom, virSchedParameterPtr params, int nparams) @@ -12710,7 +12803,7 @@ static virDriver qemuDriver = { qemuDomainRevertToSnapshot, /* domainRevertToSnapshot */ qemuDomainSnapshotDelete, /* domainSnapshotDelete */ qemuDomainMonitorCommand, /* qemuDomainMonitorCommand */ -NULL, /* domainSetMemoryParameters */ +qemuDomainSetMemoryParameters, /* domainSetMemoryParameters */ NULL, /* domainGetMemoryParameters */ }; -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v3 04/13] XML parsing for memory tunables
On Mon, 4 Oct 2010 12:16:42 +0530, Balbir Singh bal...@linux.vnet.ibm.com wrote: * Nikunj A. Dadhania nik...@linux.vnet.ibm.com [2010-09-28 15:26:30]: snip +/* Extract other memory tunables */ +if (virXPathULong(string(./memtune/hard_limit), ctxt, + def-mem.hard_limit) 0) +def-mem.hard_limit = 0; + +if (virXPathULong(string(./memtune/soft_limit[1]), ctxt, + def-mem.soft_limit) 0) +def-mem.soft_limit = 0; + +if (virXPathULong(string(./memtune/min_guarantee[1]), ctxt, + def-mem.min_guarantee) 0) +def-mem.min_guarantee = 0; + +if (virXPathULong(string(./memtune/swap_hard_limit[1]), ctxt, + def-mem.swap_hard_limit) 0) +def-mem.swap_hard_limit = 0; + Quick question, does 0 represent invalid values? If configuration file does not provide any value, we set this to 0, we do not call the lower layer calls in this case. I'd presume you'd want to use something like -1. We support unsigned long long for the values to be set (64 bit signed), unlimited translates to 2^63 - 1, is ULong sufficient to represent that value? The unit here is KB, so we can have till 2^42 bytes. So to answer you question, no it does not represent 64 bit signed. I guess this should not be an issue to support if needed. I understand that in case of cgroup unlimited is (-1), but again that would be cgroup specific at this level. I need to think of some way to address this independent of the lower layer. +unsigned long hard_limit; +unsigned long soft_limit; +unsigned long min_guarantee; +unsigned long swap_hard_limit; The hard_limit, soft_limit, swap_hard_limit are s64 and the value is in bytes. What is the unit supported in this implementation? KB Thanks for reviewing. Regard Nikunj -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 03/13] Adds xml entries for memory tunables
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com The patch adds xml entries to the domain.rng file. v2: + Fix typo min_guarantee Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- docs/schemas/domain.rng | 31 +++ 1 files changed, 31 insertions(+), 0 deletions(-) diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index ccb8cf3..d75254c 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -299,6 +299,37 @@ /optional /element /optional + + !-- All the memory/swap related tunables would go in the memtune -- + optional + element name=memtune + !-- Maximum memory the VM can use -- + optional + element name=hard_limit + ref name=memoryKB/ + /element + /optional + !-- Minimum memory ascertained for the VM during contention -- + optional + element name=soft_limit + ref name=memoryKB/ + /element + /optional + !-- Minimum amount of memory required to start the VM -- + optional + element name=min_guarantee + ref name=memoryKB/ + /element + /optional + !-- Maximum swap area the VM can use -- + optional + element name=swap_hard_limit + ref name=memoryKB/ + /element + /optional + /element + /optional + optional element name=vcpu optional -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 01/13] Adding structure and defines for virDomainSet/GetMemoryParameters
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com This patch adds a structure virMemoryParameter, it contains the name of the parameter and the type of the parameter along with a union. v3: + Protoype for virDomainGetMemoryParameters and dummy python binding. v2: + Includes dummy python bindings for the library to build cleanly. + Define string constants like hard_limit, etc. + re-order this patch. Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- include/libvirt/libvirt.h.in| 68 +++ python/generator.py |2 + python/libvirt-override-api.xml | 12 +++ python/libvirt-override.c | 14 4 files changed, 96 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index b45f7ec..a528f67 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -674,6 +674,74 @@ int virDomainGetInfo (virDomainPtr domain, char * virDomainGetSchedulerType(virDomainPtr domain, int *nparams); +/** + * virDomainMemoryParameterType: + * + * A memory parameter field type + */ +typedef enum { +VIR_DOMAIN_MEMORY_FIELD_INT = 1, /* integer case */ +VIR_DOMAIN_MEMORY_FIELD_UINT= 2, /* unsigned integer case */ +VIR_DOMAIN_MEMORY_FIELD_LLONG = 3, /* long long case */ +VIR_DOMAIN_MEMORY_FIELD_ULLONG = 4, /* unsigned long long case */ +VIR_DOMAIN_MEMORY_FIELD_DOUBLE = 5, /* double case */ +VIR_DOMAIN_MEMORY_FIELD_BOOLEAN = 6 /* boolean(character) case */ +} virMemoryParameterType; + +/** + * VIR_DOMAIN_MEMORY_FIELD_LENGTH: + * + * Macro providing the field length of virMemoryParameter + */ + +#define VIR_DOMAIN_MEMORY_FIELD_LENGTH 80 +#define VIR_DOMAIN_MEMORY_HARD_LIMIT hard_limit +#define VIR_DOMAIN_MEMORY_SOFT_LIMIT soft_limit +#define VIR_DOMAIN_MEMORY_MIN_GUARANTEE min_guarantee +#define VIR_DOMAIN_SWAP_HARD_LIMIT swap_hard_limit + +/** + * virDomainMemoryParameter: + * + * a virDomainMemoryParameter is the set of scheduler parameters + */ + +typedef struct _virMemoryParameter virMemoryParameter; + +struct _virMemoryParameter { +char field[VIR_DOMAIN_MEMORY_FIELD_LENGTH]; /* parameter name */ +int type; /* parameter type */ +union { +int i; /* data for integer case */ +unsigned int ui;/* data for unsigned integer case */ +long long int l;/* data for long long integer case */ +unsigned long long int ul; /* data for unsigned long long integer case */ +double d; /* data for double case */ +char b; /* data for char case */ +} value; /* parameter value */ +}; + +/** + * virMemoryParameterPtr: + * + * a virMemoryParameterPtr is a pointer to a virMemoryParameter structure. + */ + +typedef virMemoryParameter *virMemoryParameterPtr; + +/* Set memory tunables for the domain*/ +int virDomainSetMemoryParameters(virDomainPtr domain, +virMemoryParameterPtr params, +int nparams); +/* Get memory tunables for the domain, caller allocates the params if nparams + * is zero and params is NULL, the domain returns back number of parameters + * supported by the HV. This could be used by the caller to allocate the + * memory and call with params structure allocated. + */ +int virDomainGetMemoryParameters(virDomainPtr domain, +virMemoryParameterPtr params, +int *nparams); + /* * Dynamic control of domains */ diff --git a/python/generator.py b/python/generator.py index d876df6..68009b9 100755 --- a/python/generator.py +++ b/python/generator.py @@ -306,6 +306,8 @@ skip_impl = ( 'virDomainGetSchedulerType', 'virDomainGetSchedulerParameters', 'virDomainSetSchedulerParameters', +'virDomainSetMemoryParameters', +'virDomainGetMemoryParameters', 'virDomainGetVcpus', 'virDomainPinVcpu', 'virSecretGetValue', diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml index ca16993..f209608 100644 --- a/python/libvirt-override-api.xml +++ b/python/libvirt-override-api.xml @@ -162,6 +162,18 @@ arg name='domain' type='virDomainPtr' info='pointer to domain object'/ arg name='params' type='virSchedParameterPtr' info='pointer to scheduler parameter objects'/ /function +function name='virDomainSetMemoryParameters' file='python' + infoChange the memory tunables/info + return type='int' info='-1 in case of error, 0 in case of success.'/ + arg name='domain' type='virDomainPtr' info='pointer to domain object'/ + arg name='params' type='virMemoryParameterPtr' info='pointer to memory tunable objects'/ +/function +function name='virDomainGetMemoryParameters' file='python' + infoGet the memory
[libvirt] [PATCH v3 00/13] Implement memory control api
Changelog from v2: * Implement virDomainGetMemoryParameters api * Add virDomainGetMemoryParameters to memtune command in virsh * Provide domainGetMemoryParameters implementation for remote, QEmu and LXC drivers * Auto-generate code using rpcgen and remote_generate_stubs.pl * Squash all the changes related to remote driver and remote protocol into one single patch. * Patch re-ordering Changelog from v1: * Patch re-ordering for compilation * Folded python bindings changes to patch 01 * Added defines for string constants for memory tunables * Typo fix: min_guarantee * Moved initialization of function pointers in driver.h patch This patch series implement public api for controlling various memory tunables exported by the OS. This is based on the following RFC[1]. * Implement virDomainSetMemoryParameters api * Provide implementation for remote, QEmu and LXC drivers * Enable memory controller support fro QEmu * virsh command for runtime changes to the memory parameters * Domain configuration parsing for memory control parameters * Cgroup memory controller code for memory hard_limit/soft_limit, swap hard_limit To Do * Python bindings is just a place holder, need to implement 1. https://www.redhat.com/archives/libvir-list/2010-August/msg00607.html 2. https://www.redhat.com/archives/libvir-list/2010-August/msg00699.html --- Nikunj A. Dadhania (13): Adding structure and defines for virDomainSet/GetMemoryParameters Adding virDomainSetMemoryParameters and virDomainGetMemoryParameters API Adds xml entries for memory tunables XML parsing for memory tunables Implement cgroup memory controller tunables Implement driver interface domainSetMemoryParamters for QEmu Implement driver interface domainGetMemoryParamters for QEmu Adding memtunables to qemuSetupCgroup Adding memtunables to libvirt-lxc command Implement driver interface domainSetMemoryParamters for LXC Implement driver interface domainGetMemoryParamters for LXC Adding memtune command to virsh tool Remote protocol changes and implements virDomainSet/GetMemoryParameters daemon/remote.c | 158 ++ daemon/remote_dispatch_args.h |2 daemon/remote_dispatch_prototypes.h | 16 ++ daemon/remote_dispatch_ret.h|1 daemon/remote_dispatch_table.h | 10 + docs/schemas/domain.rng | 31 include/libvirt/libvirt.h.in| 68 + python/generator.py |2 python/libvirt-override-api.xml | 12 ++ python/libvirt-override.c | 14 ++ src/conf/domain_conf.c | 50 ++- src/conf/domain_conf.h | 12 +- src/driver.h| 12 ++ src/esx/esx_driver.c|2 src/esx/esx_vmx.c | 30 ++-- src/libvirt.c | 103 ++ src/libvirt_private.syms|6 + src/libvirt_public.syms |6 + src/lxc/lxc_controller.c| 24 +++ src/lxc/lxc_driver.c| 213 - src/openvz/openvz_driver.c | 10 + src/phyp/phyp_driver.c |2 src/qemu/qemu.conf |4 - src/qemu/qemu_conf.c| 11 +- src/qemu/qemu_driver.c | 256 ++- src/remote/remote_driver.c | 146 src/remote/remote_protocol.c| 84 +++ src/remote/remote_protocol.h| 56 src/remote/remote_protocol.x| 42 ++ src/test/test_driver.c | 14 +- src/uml/uml_conf.c |2 src/uml/uml_driver.c| 16 +- src/util/cgroup.c | 106 ++ src/util/cgroup.h |7 + src/xen/xen_driver.c|2 tools/virsh.c | 130 ++ 36 files changed, 1592 insertions(+), 68 deletions(-) -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 09/13] Adding memtunables to libvirt-lxc command
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com libvirt-lxc now configures the hardlimit, softlimit and swaplimit, if specified in the domain xml file or picks up the defaults. Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/lxc/lxc_controller.c | 22 ++ 1 files changed, 22 insertions(+), 0 deletions(-) diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 82ecce0..dee99b7 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -109,6 +109,28 @@ static int lxcSetContainerResources(virDomainDefPtr def) def-name); goto cleanup; } + +rc = virCgroupSetMemoryHardLimit(cgroup, def-mem.hard_limit); +if (rc != 0) { +virReportSystemError(-rc, + _(Unable to set memory hard limit for domain %s), + def-name); +goto cleanup; +} +rc = virCgroupSetMemorySoftLimit(cgroup, def-mem.soft_limit); +if (rc != 0) { +virReportSystemError(-rc, + _(Unable to set memory soft limit for domain %s), + def-name); +goto cleanup; +} +rc = virCgroupSetSwapHardLimit(cgroup, def-mem.swap_hard_limit); +if (rc != 0) { +virReportSystemError(-rc, + _(Unable to set swap hard limit for domain %s), + def-name); +goto cleanup; +} rc = virCgroupDenyAllDevices(cgroup); if (rc != 0) { -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 05/13] Implement cgroup memory controller tunables
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Provides interfaces for setting/getting memory tunables like hard_limit, soft_limit and swap_hard_limit Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/libvirt_private.syms |6 +++ src/util/cgroup.c| 106 ++ src/util/cgroup.h|7 +++ 3 files changed, 119 insertions(+), 0 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index c2905ba..038dd77 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -77,6 +77,12 @@ virCgroupControllerTypeFromString; virCgroupGetCpuacctUsage; virCgroupGetFreezerState; virCgroupSetFreezerState; +virCgroupSetMemoryHardLimit; +virCgroupGetMemoryHardLimit; +virCgroupSetMemorySoftLimit; +virCgroupGetMemorySoftLimit; +virCgroupSetSwapHardLimit; +virCgroupGetSwapHardLimit; # cpu.h diff --git a/src/util/cgroup.c b/src/util/cgroup.c index 024036a..f94db12 100644 --- a/src/util/cgroup.c +++ b/src/util/cgroup.c @@ -874,6 +874,112 @@ int virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb) } /** + * virCgroupSetMemoryHardLimit: + * + * @group: The cgroup to change memory hard limit for + * @kb: The memory amount in kilobytes + * + * Returns: 0 on success + */ +int virCgroupSetMemoryHardLimit(virCgroupPtr group, unsigned long kb) +{ +return virCgroupSetMemory(group, kb); +} + +/** + * virCgroupGetMemoryHardLimit: + * + * @group: The cgroup to get the memory hard limit for + * @kb: The memory amount in kilobytes + * + * Returns: 0 on success + */ +int virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long *kb) +{ +long long unsigned int limit_in_bytes; +int ret; +ret = virCgroupGetValueU64(group, + VIR_CGROUP_CONTROLLER_MEMORY, + memory.limit_in_bytes, limit_in_bytes); +if (ret == 0) +*kb = (unsigned long) limit_in_bytes 10; +return ret; +} + +/** + * virCgroupSetMemorySoftLimit: + * + * @group: The cgroup to change memory soft limit for + * @kb: The memory amount in kilobytes + * + * Returns: 0 on success + */ +int virCgroupSetMemorySoftLimit(virCgroupPtr group, unsigned long kb) +{ +return virCgroupSetValueU64(group, +VIR_CGROUP_CONTROLLER_MEMORY, +memory.soft_limit_in_bytes, +kb 10); +} + + +/** + * virCgroupGetMemorySoftLimit: + * + * @group: The cgroup to get the memory soft limit for + * @kb: The memory amount in kilobytes + * + * Returns: 0 on success + */ +int virCgroupGetMemorySoftLimit(virCgroupPtr group, unsigned long *kb) +{ +long long unsigned int limit_in_bytes; +int ret; +ret = virCgroupGetValueU64(group, + VIR_CGROUP_CONTROLLER_MEMORY, + memory.soft_limit_in_bytes, limit_in_bytes); +if (ret == 0) +*kb = (unsigned long) limit_in_bytes 10; +return ret; +} + +/** + * virCgroupSetSwapHardLimit: + * + * @group: The cgroup to change swap hard limit for + * @kb: The swap amount in kilobytes + * + * Returns: 0 on success + */ +int virCgroupSetSwapHardLimit(virCgroupPtr group, unsigned long kb) +{ +return virCgroupSetValueU64(group, +VIR_CGROUP_CONTROLLER_MEMORY, +memory.memsw.limit_in_bytes, +kb 10); +} + +/** + * virCgroupGetSwapHardLimit: + * + * @group: The cgroup to get swap hard limit for + * @kb: The swap amount in kilobytes + * + * Returns: 0 on success + */ +int virCgroupGetSwapHardLimit(virCgroupPtr group, unsigned long *kb) +{ +long long unsigned int limit_in_bytes; +int ret; +ret = virCgroupGetValueU64(group, + VIR_CGROUP_CONTROLLER_MEMORY, + memory.memsw.limit_in_bytes, limit_in_bytes); +if (ret == 0) +*kb = (unsigned long) limit_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 2bea49f..b8f2d08 100644 --- a/src/util/cgroup.h +++ b/src/util/cgroup.h @@ -43,6 +43,13 @@ int virCgroupAddTask(virCgroupPtr group, pid_t pid); int virCgroupSetMemory(virCgroupPtr group, unsigned long kb); int virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb); +int virCgroupSetMemoryHardLimit(virCgroupPtr group, unsigned long kb); +int virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long *kb); +int virCgroupSetMemorySoftLimit(virCgroupPtr group, unsigned long kb); +int virCgroupGetMemorySoftLimit(virCgroupPtr group, unsigned long *kb); +int virCgroupSetSwapHardLimit(virCgroupPtr group, unsigned long kb); +int virCgroupGetSwapHardLimit(virCgroupPtr group, unsigned long *kb); + int virCgroupDenyAllDevices(virCgroupPtr group); int virCgroupAllowDevice(virCgroupPtr group
[libvirt] [PATCH v3 06/13] Implement driver interface domainSetMemoryParamters for QEmu
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Driver interface for setting memory hard_limit, soft_limit and swap hard_limit. v2: + Use #define string constants for hard_limit, etc. + fix typo: min_guarantee Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/qemu/qemu_driver.c | 94 +++- 1 files changed, 93 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index bf4373a..b6be343 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -9365,6 +9365,98 @@ cleanup: return ret; } + +static int qemuDomainSetMemoryParameters(virDomainPtr dom, + virMemoryParameterPtr params, + int nparams) +{ +struct qemud_driver *driver = dom-conn-privateData; +int i; +virCgroupPtr group = NULL; +virDomainObjPtr vm = NULL; +int ret = -1; + +qemuDriverLock(driver); +if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_MEMORY)) { +qemuReportError(VIR_ERR_NO_SUPPORT, +__FUNCTION__); +goto cleanup; +} + +vm = virDomainFindByUUID(driver-domains, dom-uuid); + +if (vm == NULL) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +_(No such domain %s), dom-uuid); +goto cleanup; +} + +if (virCgroupForDomain(driver-cgroup, vm-def-name, group, 0) != 0) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +_(cannot find cgroup for domain %s), vm-def-name); +goto cleanup; +} + +for (i = 0; i nparams; i++) { +virMemoryParameterPtr param = params[i]; + +if (STREQ(param-field, VIR_DOMAIN_MEMORY_HARD_LIMIT)) { +int rc; +if (param-type != VIR_DOMAIN_MEMORY_FIELD_ULLONG) { +qemuReportError(VIR_ERR_INVALID_ARG, %s, +_(invalid type for memory hard_limit tunable, expected a 'ullong')); +continue; +} + +rc = virCgroupSetMemoryHardLimit(group, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set memory hard_limit tunable)); +} +} else if (STREQ(param-field, VIR_DOMAIN_MEMORY_SOFT_LIMIT)) { +int rc; +if (param-type != VIR_DOMAIN_MEMORY_FIELD_ULLONG) { +qemuReportError(VIR_ERR_INVALID_ARG, %s, +_(invalid type for memory soft_limit tunable, expected a 'ullong')); +continue; +} + +rc = virCgroupSetMemorySoftLimit(group, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set memory soft_limit tunable)); +} +} else if (STREQ(param-field, VIR_DOMAIN_SWAP_HARD_LIMIT)) { +int rc; +if (param-type != VIR_DOMAIN_MEMORY_FIELD_ULLONG) { +qemuReportError(VIR_ERR_INVALID_ARG, %s, +_(invalid type for swap_hard_limit tunable, expected a 'ullong')); +continue; +} + +rc = virCgroupSetSwapHardLimit(group, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set swap_hard_limit tunable)); +} +} else if (STREQ(param-field, VIR_DOMAIN_MEMORY_MIN_GUARANTEE)) { +qemuReportError(VIR_ERR_INVALID_ARG, +_(Memory tunable `%s' not implemented), param-field); +} else { +qemuReportError(VIR_ERR_INVALID_ARG, +_(Parameter `%s' not supported), param-field); +} +} +ret = 0; + +cleanup: +virCgroupFree(group); +if (vm) +virDomainObjUnlock(vm); +qemuDriverUnlock(driver); +return ret; +} + static int qemuSetSchedulerParameters(virDomainPtr dom, virSchedParameterPtr params, int nparams) @@ -12710,7 +12802,7 @@ static virDriver qemuDriver = { qemuDomainRevertToSnapshot, /* domainRevertToSnapshot */ qemuDomainSnapshotDelete, /* domainSnapshotDelete */ qemuDomainMonitorCommand, /* qemuDomainMonitorCommand */ -NULL, /* domainSetMemoryParameters */ +qemuDomainSetMemoryParameters, /* domainSetMemoryParameters */ NULL, /* domainGetMemoryParameters */ }; -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 12/13] Adding memtune command to virsh tool
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com The command helps to control the memory/swap parameters for the system, for eg. hard_limit (max memory the vm can use), soft_limit (limit during memory contention), swap_hard_limit(max swap the vm can use) v3: + Added call to virDomainGetMemoryParameters and print them. + Added virDomainGetMemoryParameters and virDomainSetMemoryParamters to libvirt_public.syms v2: + Use #define string constants for hard_limit, etc Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/libvirt_public.syms |6 ++ tools/virsh.c | 130 +++ 2 files changed, 136 insertions(+), 0 deletions(-) diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 849c163..fceb516 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -405,4 +405,10 @@ LIBVIRT_0.8.2 { virDomainCreateWithFlags; } LIBVIRT_0.8.1; +LIBVIRT_0.8.5 { +global: +virDomainSetMemoryParameters; +virDomainGetMemoryParameters; +} LIBVIRT_0.8.2; + # define new API here using predicted next version number diff --git a/tools/virsh.c b/tools/virsh.c index 85014f2..0500cb5 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2614,6 +2614,135 @@ cmdSetmaxmem(vshControl *ctl, const vshCmd *cmd) } /* + * memtune command + */ +static const vshCmdInfo info_memtune[] = { +{help, N_(Get/Set memory paramters)}, +{desc, N_(Get/Set the current memory paramters for the guest domain.\n \ +To get the memory parameters use following command: \n\n \ +virsh # memtune domain)}, +{NULL, NULL} +}; + +static const vshCmdOptDef opts_memtune[] = { +{domain, VSH_OT_DATA, VSH_OFLAG_REQ, N_(domain name, id or uuid)}, +{VIR_DOMAIN_MEMORY_HARD_LIMIT, VSH_OT_STRING, VSH_OFLAG_NONE, N_(Max memory in kilobytes)}, +{VIR_DOMAIN_MEMORY_SOFT_LIMIT, VSH_OT_STRING, VSH_OFLAG_NONE, N_(Memory during contention in kilobytes)}, +{VIR_DOMAIN_SWAP_HARD_LIMIT, VSH_OT_STRING, VSH_OFLAG_NONE, N_(Max swap in kilobytes)}, +{NULL, 0, 0, NULL} +}; + +static int +cmdMemtune(vshControl *ctl, const vshCmd *cmd) +{ +virDomainPtr dom; +int hard_limit, soft_limit, swap_hard_limit; +int nparams = 0; +unsigned int i = 0; +virMemoryParameterPtr params = NULL, temp = NULL; +int ret = FALSE; + +if (!vshConnectionUsability(ctl, ctl-conn)) +return FALSE; + +if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) +return FALSE; + +hard_limit = vshCommandOptInt(cmd, VIR_DOMAIN_MEMORY_HARD_LIMIT, hard_limit); +if (hard_limit) +nparams++; + +soft_limit = vshCommandOptInt(cmd, VIR_DOMAIN_MEMORY_SOFT_LIMIT, soft_limit); +if (soft_limit) +nparams++; + +swap_hard_limit = vshCommandOptInt(cmd, VIR_DOMAIN_SWAP_HARD_LIMIT, swap_hard_limit); +if (swap_hard_limit) +nparams++; + +if(nparams == 0) { +/* get the number of memory parameters */ +if (virDomainGetMemoryParameters(dom, NULL, nparams) != 0 (nparams != 0)) { +vshError(ctl, %s, _(Unable to get number of memory parameters)); +goto cleanup; +} + +/* now go get all the memory parameters */ +params = vshMalloc(ctl, sizeof(virMemoryParameter)* nparams); +memset(params, 0, sizeof(virMemoryParameter)* nparams); +if (virDomainGetMemoryParameters(dom, params, nparams)) { +vshError(ctl, %s, _(Unable to get memory parameters)); +goto cleanup; +} + +for (i = 0; i nparams; i++){ +switch (params[i].type) { +case VIR_DOMAIN_MEMORY_FIELD_INT: +vshPrint(ctl, %-15s: %d\n, params[i].field, params[i].value.i); +break; +case VIR_DOMAIN_MEMORY_FIELD_UINT: +vshPrint(ctl, %-15s: %u\n, params[i].field, params[i].value.ui); +break; +case VIR_DOMAIN_MEMORY_FIELD_LLONG: +vshPrint(ctl, %-15s: %lld\n, params[i].field, params[i].value.l); +break; +case VIR_DOMAIN_MEMORY_FIELD_ULLONG: +vshPrint(ctl, %-15s: %llu\n, params[i].field, params[i].value.ul); +break; +case VIR_DOMAIN_MEMORY_FIELD_DOUBLE: +vshPrint(ctl, %-15s: %f\n, params[i].field, params[i].value.d); +break; +case VIR_DOMAIN_MEMORY_FIELD_BOOLEAN: +vshPrint(ctl, %-15s: %d\n, params[i].field, params[i].value.b); +break; +default: +vshPrint(ctl, not implemented scheduler parameter type\n); +} +} + +ret = TRUE; +} else { +/* set the memory parameters */ +params = vshMalloc(ctl, sizeof(virMemoryParameter)* nparams); + +memset(params, 0, sizeof(virMemoryParameter)* nparams); +for(i = 0; i
[libvirt] [PATCH v3 02/13] Adding virDomainSetMemoryParameters and virDomainGetMemoryParameters API
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Public api to set/get memory tunables supported by the hypervisors. RFC: https://www.redhat.com/archives/libvir-list/2010-August/msg00607.html v3: * Add domainGetMemoryParamters and NULL in all the driver interface v2: * Initialize domainSetMemoryParameters to NULL in all the driver interface structure. Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/driver.h | 12 + src/esx/esx_driver.c |2 + src/libvirt.c | 103 src/lxc/lxc_driver.c |2 + src/openvz/openvz_driver.c |2 + src/phyp/phyp_driver.c |2 + src/qemu/qemu_driver.c |2 + src/remote/remote_driver.c |2 + src/test/test_driver.c |2 + src/uml/uml_driver.c |2 + src/xen/xen_driver.c |2 + 11 files changed, 133 insertions(+), 0 deletions(-) diff --git a/src/driver.h b/src/driver.h index e443c1c..0580bee 100644 --- a/src/driver.h +++ b/src/driver.h @@ -128,6 +128,16 @@ typedef int (*virDrvDomainSetMemory) (virDomainPtr domain, unsigned long memory); typedef int +(*virDrvDomainSetMemoryParameters) +(virDomainPtr domain, + virMemoryParameterPtr params, + int nparams); +typedef int +(*virDrvDomainGetMemoryParameters) +(virDomainPtr domain, + virMemoryParameterPtr params, + int *nparams); +typedef int (*virDrvDomainGetInfo) (virDomainPtr domain, virDomainInfoPtr info); typedef int @@ -575,6 +585,8 @@ struct _virDriver { virDrvDomainRevertToSnapshot domainRevertToSnapshot; virDrvDomainSnapshotDelete domainSnapshotDelete; virDrvQemuDomainMonitorCommand qemuDomainMonitorCommand; +virDrvDomainSetMemoryParameters domainSetMemoryParameters; +virDrvDomainGetMemoryParameters domainGetMemoryParameters; }; typedef int diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index e382950..e959be2 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4217,6 +4217,8 @@ static virDriver esxDriver = { esxDomainRevertToSnapshot, /* domainRevertToSnapshot */ esxDomainSnapshotDelete, /* domainSnapshotDelete */ NULL,/* qemuDomainMonitorCommand */ +NULL,/* domainSetMemoryParameters */ +NULL,/* domainGetMemoryParameters */ }; diff --git a/src/libvirt.c b/src/libvirt.c index ca383ba..0708e36 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -3000,6 +3000,109 @@ error: } /** + * virDomainSetMemoryParameters: + * @domain: pointer to domain object + * @params: pointer to memory parameter objects + * @nparams: number of memory parameter (this value should be same or + * less than the number of parameters supported) + * + * Change the memory tunables + * This function requires privileged access to the hypervisor. + * FIXME: Should we make changes to the domain configuration file as well? + * + * Returns -1 in case of error, 0 in case of success. + */ +int +virDomainSetMemoryParameters(virDomainPtr domain, +virMemoryParameterPtr params, +int nparams) +{ +virConnectPtr conn; +DEBUG(domain=%p, params=%p, nparams=%d, domain, params, nparams); + +virResetLastError(); + +if (!VIR_IS_CONNECTED_DOMAIN(domain)) { +virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); +virDispatchError(NULL); +return -1; +} +if (domain-conn-flags VIR_CONNECT_RO) { +virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); +goto error; +} +conn = domain-conn; + +if (conn-driver-domainSetMemoryParameters) { +int ret; +ret = conn-driver-domainSetMemoryParameters (domain, params, nparams); +if (ret 0) +goto error; +return ret; +} + +virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: +virDispatchError(domain-conn); +return -1; +} + +/** + * virDomainGetMemoryParameters: + * @domain: pointer to domain object + * @params: pointer to memory parameter object + * (return value, allocated by the caller) + * @nparams: pointer to number of memory parameters + * + * Get the memory parameters, the @params array will be filled with the values + * equal to the number of parameters suggested by @nparams + * + * As a special case, if @nparams is zero and @params is NULL, the API will + * set the number of parameters supported by the HV in @nparams and return + * SUCCESS. + * + * This function requires privileged access
[libvirt] [PATCH v3 10/13] Implement driver interface domainSetMemoryParamters for LXC
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Add support in the lxc driver for various memory controllable parameters v2: + Use #define string constants for hard_limit, etc + fix typo: min_guarantee Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/lxc/lxc_driver.c | 90 +- 1 files changed, 89 insertions(+), 1 deletions(-) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 8977835..6912bb8 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -677,6 +677,94 @@ cleanup: return ret; } +static int lxcDomainSetMemoryParameters(virDomainPtr dom, +virMemoryParameterPtr params, +int nparams) +{ +lxc_driver_t *driver = dom-conn-privateData; +int i; +virCgroupPtr cgroup = NULL; +virDomainObjPtr vm = NULL; +int ret = -1; + +lxcDriverLock(driver); +vm = virDomainFindByUUID(driver-domains, dom-uuid); + +if (vm == NULL) { +char uuidstr[VIR_UUID_STRING_BUFLEN]; +virUUIDFormat(dom-uuid, uuidstr); +lxcError(VIR_ERR_NO_DOMAIN, + _(No domain with matching uuid '%s'), uuidstr); +goto cleanup; +} + +if (virCgroupForDomain(driver-cgroup, vm-def-name, cgroup, 0) != 0) { +lxcError(VIR_ERR_INTERNAL_ERROR, + _(Unable to get cgroup for %s), vm-def-name); +goto cleanup; +} + +for (i = 0; i nparams; i++) { +virMemoryParameterPtr param = params[i]; + +if (STREQ(param-field, VIR_DOMAIN_MEMORY_HARD_LIMIT)) { +int rc; +if (param-type != VIR_DOMAIN_MEMORY_FIELD_ULLONG) { +lxcError(VIR_ERR_INVALID_ARG, %s, + _(invalid type for memory hard_limit tunable, expected a 'ullong')); +continue; +} + +rc = virCgroupSetMemoryHardLimit(cgroup, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set memory hard_limit tunable)); +} +} else if (STREQ(param-field, VIR_DOMAIN_MEMORY_SOFT_LIMIT)) { +int rc; +if (param-type != VIR_DOMAIN_MEMORY_FIELD_ULLONG) { +lxcError(VIR_ERR_INVALID_ARG, %s, + _(invalid type for memory soft_limit tunable, expected a 'ullong')); +continue; +} + +rc = virCgroupSetMemorySoftLimit(cgroup, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set memory soft_limit tunable)); +} +} else if (STREQ(param-field, VIR_DOMAIN_SWAP_HARD_LIMIT)) { +int rc; +if (param-type != VIR_DOMAIN_MEMORY_FIELD_ULLONG) { +lxcError(VIR_ERR_INVALID_ARG, %s, + _(invalid type for swap_hard_limit tunable, expected a 'ullong')); +continue; +} + +rc = virCgroupSetSwapHardLimit(cgroup, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set swap_hard_limit tunable)); +} +} else if (STREQ(param-field, VIR_DOMAIN_MEMORY_MIN_GUARANTEE)) { +lxcError(VIR_ERR_INVALID_ARG, + _(Memory tunable `%s' not implemented), param-field); +} else { +lxcError(VIR_ERR_INVALID_ARG, + _(Parameter `%s' not supported), param-field); +} +} +ret = 0; + +cleanup: +if (cgroup) +virCgroupFree(cgroup); +if (vm) +virDomainObjUnlock(vm); +lxcDriverUnlock(driver); +return ret; +} + static char *lxcDomainDumpXML(virDomainPtr dom, int flags) { @@ -2620,7 +2708,7 @@ static virDriver lxcDriver = { NULL, /* domainRevertToSnapshot */ NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ -NULL, /* domainSetMemoryParameters */ +lxcDomainSetMemoryParameters, /* domainSetMemoryParameters */ NULL, /* domainGetMemoryParameters */ }; -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 08/13] Adding memtunables to qemuSetupCgroup
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com QEmu startup would pick up the memory tunables specified in the domain configuration file. Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/qemu/qemu.conf |4 ++-- src/qemu/qemu_conf.c |3 ++- src/qemu/qemu_driver.c | 27 +++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf index dc8eb83..bfb9f6a 100644 --- a/src/qemu/qemu.conf +++ b/src/qemu/qemu.conf @@ -111,13 +111,13 @@ # the adminsitrator has mounted cgroups. eg # # mkdir /dev/cgroup -# mount -t cgroup -o devices,cpu none /dev/cgroup +# mount -t cgroup -o devices,cpu,memory none /dev/cgroup # # They can be mounted anywhere, and different controlers # can be mounted in different locations. libvirt will detect # where they are located. # -# cgroup_controllers = [ cpu, devices ] +# cgroup_controllers = [ cpu, devices, memory ] # This is the basic set of devices allowed / required by # all virtual machines. diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 731c554..3f5c1ac 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -275,7 +275,8 @@ int qemudLoadDriverConfig(struct qemud_driver *driver, } else { driver-cgroupControllers = (1 VIR_CGROUP_CONTROLLER_CPU) | -(1 VIR_CGROUP_CONTROLLER_DEVICES); +(1 VIR_CGROUP_CONTROLLER_DEVICES) | +(1 VIR_CGROUP_CONTROLLER_MEMORY); } for (i = 0 ; i VIR_CGROUP_CONTROLLER_LAST ; i++) { if (driver-cgroupControllers (1 i)) { diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index fcb7f9d..6d05bf8 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3495,6 +3495,33 @@ static int qemuSetupCgroup(struct qemud_driver *driver, goto cleanup; } +if ((rc = qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_MEMORY))) { +rc = virCgroupSetMemoryHardLimit(cgroup, vm-def-mem.hard_limit); +if (rc != 0) { +virReportSystemError(-rc, + _(Unable to set memory hard limit for domain %s), + vm-def-name); +goto cleanup; +} +rc = virCgroupSetMemorySoftLimit(cgroup, vm-def-mem.soft_limit); +if (rc != 0) { +virReportSystemError(-rc, + _(Unable to set memory soft limit for domain %s), + vm-def-name); +goto cleanup; +} +rc = virCgroupSetSwapHardLimit(cgroup, vm-def-mem.swap_hard_limit); +if (rc != 0) { +virReportSystemError(-rc, + _(Unable to set swap hard limit for domain %s), + vm-def-name); +goto cleanup; +} +} else { +VIR_WARN(Memory cgroup is disabled in qemu configuration file: %s, + vm-def-name); +} + done: virCgroupFree(cgroup); return 0; -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v3 13/13] Remote protocol changes and implements virDomainSet/GetMemoryParameters
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com v3: * Squased all the remote driver changes to one single big patch and auto-generated is around 40% * Implements domainSetMemoryParameters and domainGetMemoryParameters for remote driver daemon/remote.c src/remote/remote_driver.c * Auto generate the files using rpcgen and helper scripts in daemon/ directory src/remote/remote_protocol.x daemon/remote_dispatch_args.h daemon/remote_dispatch_prototypes.h daemon/remote_dispatch_ret.h daemon/remote_dispatch_table.h src/remote/remote_protocol.c src/remote/remote_protocol.h Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- daemon/remote.c | 158 +++ daemon/remote_dispatch_args.h |2 daemon/remote_dispatch_prototypes.h | 16 daemon/remote_dispatch_ret.h|1 daemon/remote_dispatch_table.h | 10 ++ src/remote/remote_driver.c | 148 - src/remote/remote_protocol.c| 84 +++ src/remote/remote_protocol.h| 56 src/remote/remote_protocol.x| 42 + 9 files changed, 514 insertions(+), 3 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 118654c..c8977d8 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -2332,6 +2332,164 @@ remoteDispatchDomainSetMemory (struct qemud_server *server ATTRIBUTE_UNUSED, } static int +remoteDispatchDomainSetMemoryParameters (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_message_header *hdr ATTRIBUTE_UNUSED, + remote_error *rerr, + remote_domain_set_memory_parameters_args *args, + void *ret ATTRIBUTE_UNUSED) +{ +virDomainPtr dom; +int i, r, nparams; +virMemoryParameterPtr params; + +nparams = args-params.params_len; + +if (nparams REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX) { +remoteDispatchFormatError (rerr, %s, _(nparams too large)); +return -1; +} +if (VIR_ALLOC_N(params, nparams) 0) { +remoteDispatchOOMError(rerr); +return -1; +} + +/* Deserialise parameters. */ +for (i = 0; i nparams; ++i) { +if (virStrcpyStatic(params[i].field, args-params.params_val[i].field) == NULL) { +remoteDispatchFormatError(rerr, _(Field %s too big for destination), + args-params.params_val[i].field); +return -1; +} +params[i].type = args-params.params_val[i].value.type; +switch (params[i].type) { +case VIR_DOMAIN_MEMORY_FIELD_INT: +params[i].value.i = args-params.params_val[i].value.remote_memory_param_value_u.i; break; +case VIR_DOMAIN_MEMORY_FIELD_UINT: +params[i].value.ui = args-params.params_val[i].value.remote_memory_param_value_u.ui; break; +case VIR_DOMAIN_MEMORY_FIELD_LLONG: +params[i].value.l = args-params.params_val[i].value.remote_memory_param_value_u.l; break; +case VIR_DOMAIN_MEMORY_FIELD_ULLONG: +params[i].value.ul = args-params.params_val[i].value.remote_memory_param_value_u.ul; break; +case VIR_DOMAIN_MEMORY_FIELD_DOUBLE: +params[i].value.d = args-params.params_val[i].value.remote_memory_param_value_u.d; break; +case VIR_DOMAIN_MEMORY_FIELD_BOOLEAN: +params[i].value.b = args-params.params_val[i].value.remote_memory_param_value_u.b; break; +} +} + +dom = get_nonnull_domain (conn, args-dom); +if (dom == NULL) { +VIR_FREE(params); +remoteDispatchConnError(rerr, conn); +return -1; +} + +r = virDomainSetMemoryParameters (dom, params, nparams); +virDomainFree(dom); +VIR_FREE(params); +if (r == -1) { +remoteDispatchConnError(rerr, conn); +return -1; +} + +return 0; +} + +static int remoteDispatchDomainGetMemoryParameters (struct qemud_server *server, +struct qemud_client *client, +virConnectPtr conn, +remote_message_header *hdr, +remote_error *rerr, + remote_domain_get_memory_parameters_args *args, + remote_domain_get_memory_parameters_ret *ret) +{ +virDomainPtr dom; +virMemoryParameterPtr params; +int i, r, nparams; + +nparams = args-nparams; + +if (nparams
[libvirt] [PATCH v3 04/13] XML parsing for memory tunables
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Adding parsing code for memory tunables in the domain xml file v2: + Fix typo min_guarantee Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/conf/domain_conf.c | 50 +--- src/conf/domain_conf.h | 12 --- src/esx/esx_vmx.c | 30 +- src/lxc/lxc_controller.c |2 +- src/lxc/lxc_driver.c | 12 +-- src/openvz/openvz_driver.c |8 --- src/qemu/qemu_conf.c |8 --- src/qemu/qemu_driver.c | 18 src/test/test_driver.c | 12 +-- src/uml/uml_conf.c |2 +- src/uml/uml_driver.c | 14 ++-- 11 files changed, 104 insertions(+), 64 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index e05d5d7..0dd74e4 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4231,19 +4231,38 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, def-description = virXPathString(string(./description[1]), ctxt); /* Extract domain memory */ -if (virXPathULong(string(./memory[1]), ctxt, def-maxmem) 0) { +if (virXPathULong(string(./memory[1]), ctxt, + def-mem.max_balloon) 0) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, %s, _(missing memory element)); goto error; } -if (virXPathULong(string(./currentMemory[1]), ctxt, def-memory) 0) -def-memory = def-maxmem; +if (virXPathULong(string(./currentMemory[1]), ctxt, + def-mem.cur_balloon) 0) +def-mem.cur_balloon = def-mem.max_balloon; node = virXPathNode(./memoryBacking/hugepages, ctxt); if (node) -def-hugepage_backed = 1; - +def-mem.hugepage_backed = 1; + +/* Extract other memory tunables */ +if (virXPathULong(string(./memtune/hard_limit), ctxt, + def-mem.hard_limit) 0) +def-mem.hard_limit = 0; + +if (virXPathULong(string(./memtune/soft_limit[1]), ctxt, + def-mem.soft_limit) 0) +def-mem.soft_limit = 0; + +if (virXPathULong(string(./memtune/min_guarantee[1]), ctxt, + def-mem.min_guarantee) 0) +def-mem.min_guarantee = 0; + +if (virXPathULong(string(./memtune/swap_hard_limit[1]), ctxt, + def-mem.swap_hard_limit) 0) +def-mem.swap_hard_limit = 0; + if (virXPathULong(string(./vcpu[1]), ctxt, def-vcpus) 0) def-vcpus = 1; @@ -6382,10 +6401,25 @@ char *virDomainDefFormat(virDomainDefPtr def, virBufferEscapeString(buf, description%s/description\n, def-description); -virBufferVSprintf(buf, memory%lu/memory\n, def-maxmem); +virBufferVSprintf(buf, memory%lu/memory\n, def-mem.max_balloon); virBufferVSprintf(buf, currentMemory%lu/currentMemory\n, - def-memory); -if (def-hugepage_backed) { + def-mem.cur_balloon); +virBufferVSprintf(buf, memtune\n); +if (def-mem.hard_limit) { +virBufferVSprintf(buf, hard_limit%lu/hard_limit\n, + def-mem.hard_limit); +} +if (def-mem.soft_limit) { +virBufferVSprintf(buf, soft_limit%lu/soft_limit\n, + def-mem.soft_limit); +} +if (def-mem.swap_hard_limit) { +virBufferVSprintf(buf, swap_hard_limit%lu/swap_hard_limit\n, + def-mem.swap_hard_limit); +} +virBufferVSprintf(buf, /memtune\n); + +if (def-mem.hugepage_backed) { virBufferAddLit(buf, memoryBacking\n); virBufferAddLit(buf, hugepages/\n); virBufferAddLit(buf, /memoryBacking\n); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 7195c04..2ecc2af 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -864,9 +864,15 @@ struct _virDomainDef { char *name; char *description; -unsigned long memory; -unsigned long maxmem; -unsigned char hugepage_backed; +struct { +unsigned long max_balloon; +unsigned long cur_balloon; +unsigned long hugepage_backed; +unsigned long hard_limit; +unsigned long soft_limit; +unsigned long min_guarantee; +unsigned long swap_hard_limit; +} mem; unsigned long vcpus; int cpumasklen; char *cpumask; diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c index 59eb3b2..6f1eb17 100644 --- a/src/esx/esx_vmx.c +++ b/src/esx/esx_vmx.c @@ -48,8 +48,8 @@ domain-xml= vmx def-id = value = ??? # not representable def-uuid = value = uuid.bios = value def-name = value = displayName = value -def-maxmem = value kilobyte= memsize = value
[libvirt] [PATCH v3 11/13] Implement driver interface domainGetMemoryParamters for LXC
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Driver interface for getting memory parameters, eg. hard_limit, soft_limit and swap_hard_limit. Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/lxc/lxc_driver.c | 113 ++ 1 files changed, 112 insertions(+), 1 deletions(-) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 6912bb8..e60a569 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -765,6 +765,117 @@ cleanup: return ret; } +static int lxcDomainGetMemoryParameters(virDomainPtr dom, +virMemoryParameterPtr params, +int *nparams) +{ +lxc_driver_t *driver = dom-conn-privateData; +int i; +virCgroupPtr cgroup = NULL; +virDomainObjPtr vm = NULL; +unsigned long val; +int ret = -1; +int rc; + +lxcDriverLock(driver); +vm = virDomainFindByUUID(driver-domains, dom-uuid); + +if (vm == NULL) { +char uuidstr[VIR_UUID_STRING_BUFLEN]; +virUUIDFormat(dom-uuid, uuidstr); +lxcError(VIR_ERR_NO_DOMAIN, + _(No domain with matching uuid '%s'), uuidstr); +goto cleanup; +} + +if ((*nparams) == 0) { +/* Current number of memory parameters supported by cgroups is 3 + * FIXME: Magic number, need to see where should this go + */ +*nparams = 3; +ret = 0; +goto cleanup; +} +if ((*nparams) != 3) { +lxcError(VIR_ERR_INVALID_ARG, + %s, _(Invalid parameter count)); +goto cleanup; +} + +if (virCgroupForDomain(driver-cgroup, vm-def-name, cgroup, 0) != 0) { +lxcError(VIR_ERR_INTERNAL_ERROR, + _(Unable to get cgroup for %s), vm-def-name); +goto cleanup; +} + +for (i = 0; i *nparams; i++) { +virMemoryParameterPtr param = params[i]; +val = 0; +param-value.ul = 0; +param-type = VIR_DOMAIN_MEMORY_FIELD_ULLONG; + +switch(i) { +case 0: /* fill memory hard limit here */ +rc = virCgroupGetMemoryHardLimit(cgroup, val); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to get memory hard limit)); +continue; +} +if (virStrcpyStatic(param-field, VIR_DOMAIN_MEMORY_HARD_LIMIT) == NULL) { +lxcError(VIR_ERR_INTERNAL_ERROR, + %s, _(Field memory hard limit too long for destination)); +continue; +} +param-value.ul = val; +break; + +case 1: /* fill memory soft limit here */ +rc = virCgroupGetMemorySoftLimit(cgroup, val); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to get memory soft limit)); +continue; +} +if (virStrcpyStatic(param-field, VIR_DOMAIN_MEMORY_SOFT_LIMIT) == NULL) { +lxcError(VIR_ERR_INTERNAL_ERROR, + %s, _(Field memory soft limit too long for destination)); +continue; +} +param-value.ul = val; +break; + +case 2: /* fill swap hard limit here */ +rc = virCgroupGetSwapHardLimit(cgroup, val); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to get swap hard limit)); +continue; +} +if (virStrcpyStatic(param-field, VIR_DOMAIN_SWAP_HARD_LIMIT) == NULL) { +lxcError(VIR_ERR_INTERNAL_ERROR, + %s, _(Field swap hard limit too long for destination)); +continue; +} +param-value.ul = val; +break; + +default: +break; +/* should not hit here */ +} +} +ret = 0; + +cleanup: +if (cgroup) +virCgroupFree(cgroup); +if (vm) +virDomainObjUnlock(vm); +lxcDriverUnlock(driver); +return ret; +} + static char *lxcDomainDumpXML(virDomainPtr dom, int flags) { @@ -2709,7 +2820,7 @@ static virDriver lxcDriver = { NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ lxcDomainSetMemoryParameters, /* domainSetMemoryParameters */ -NULL, /* domainGetMemoryParameters */ +lxcDomainGetMemoryParameters, /* domainGetMemoryParameters */ }; static virStateDriver lxcStateDriver = { -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2 00/11] Implement memory control api
Changelog from v1: * Patch re-ordering for compilation * Folded python bindings changes to patch 01 * Added defines for string constants for memory tunables * Typo fix: min_guarantee * Moved initialization of function pointers in driver.h patch This patch series implement public api for controlling various memory tunables exported by the OS. This is based on the following RFC[1]. * Implement virDomainSetMemoryParameters api * Provide implementation for remote, QEmu and LXC drivers * Enable memory controller support fro QEmu * virsh command for runtime changes to the memory parameters * Domain configuration parsing for memory control parameters * Cgroup memory controller code for memory hard_limit/soft_limit, swap hard_limit To Do * Python bindings is just a place holder, need to implement * virDomainGetMemoryParameters 1. https://www.redhat.com/archives/libvir-list/2010-August/msg00607.html 2. https://www.redhat.com/archives/libvir-list/2010-August/msg00699.html --- Nikunj A. Dadhania (11): Adding structure and defines for virDomainSetMemoryParameter Adding virDomainSetMemoryParameters API Adds xml entries for memory tunables XML parsing for memory tunables Implement cgroup memory controller tunables Implement driver interface domainSetMemoryParamters for QEmu Adding memtunables to libvirt-lxc command Adding memtunables to qemuSetupCgroup Adding memtune command to virsh tool Implements virDomainSetMemoryParameters for the remote driver Implement domainSetMemoryParameters function daemon/remote.c | 66 + daemon/remote_dispatch_prototypes.h |8 ++ daemon/remote_dispatch_table.h |5 + docs/schemas/domain.rng | 31 include/libvirt/libvirt.h.in| 60 +++ python/generator.py |1 python/libvirt-override-api.xml |6 ++ python/libvirt-override.c |7 ++ src/conf/domain_conf.c | 50 +++-- src/conf/domain_conf.h | 12 ++- src/driver.h|6 ++ src/esx/esx_driver.c|1 src/esx/esx_vmx.c | 30 src/libvirt.c | 48 src/libvirt_private.syms|6 ++ src/libvirt_public.syms |5 + src/lxc/lxc_controller.c| 24 ++ src/lxc/lxc_driver.c| 101 -- src/openvz/openvz_driver.c |9 +- src/phyp/phyp_driver.c |1 src/qemu/qemu.conf |4 + src/qemu/qemu_conf.c| 11 ++- src/qemu/qemu_driver.c | 138 +-- src/remote/remote_driver.c | 66 + src/remote/remote_protocol.c| 62 +++- src/remote/remote_protocol.h| 36 + src/test/test_driver.c | 13 ++- src/uml/uml_conf.c |2 - src/uml/uml_driver.c| 15 ++-- src/util/cgroup.c | 106 +++ src/util/cgroup.h |7 ++ src/xen/xen_driver.c|1 tools/virsh.c | 89 +++ 33 files changed, 959 insertions(+), 68 deletions(-) -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2 08/11] Adding memtunables to qemuSetupCgroup
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com QEmu startup would pick up the memory tunables specified in the domain configuration file. Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/qemu/qemu.conf |4 ++-- src/qemu/qemu_conf.c |3 ++- src/qemu/qemu_driver.c | 27 +++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf index dc8eb83..bfb9f6a 100644 --- a/src/qemu/qemu.conf +++ b/src/qemu/qemu.conf @@ -111,13 +111,13 @@ # the adminsitrator has mounted cgroups. eg # # mkdir /dev/cgroup -# mount -t cgroup -o devices,cpu none /dev/cgroup +# mount -t cgroup -o devices,cpu,memory none /dev/cgroup # # They can be mounted anywhere, and different controlers # can be mounted in different locations. libvirt will detect # where they are located. # -# cgroup_controllers = [ cpu, devices ] +# cgroup_controllers = [ cpu, devices, memory ] # This is the basic set of devices allowed / required by # all virtual machines. diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 731c554..3f5c1ac 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -275,7 +275,8 @@ int qemudLoadDriverConfig(struct qemud_driver *driver, } else { driver-cgroupControllers = (1 VIR_CGROUP_CONTROLLER_CPU) | -(1 VIR_CGROUP_CONTROLLER_DEVICES); +(1 VIR_CGROUP_CONTROLLER_DEVICES) | +(1 VIR_CGROUP_CONTROLLER_MEMORY); } for (i = 0 ; i VIR_CGROUP_CONTROLLER_LAST ; i++) { if (driver-cgroupControllers (1 i)) { diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index adf5f16..714ff21 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -3495,6 +3495,33 @@ static int qemuSetupCgroup(struct qemud_driver *driver, goto cleanup; } +if ((rc = qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_MEMORY))) { +rc = virCgroupSetMemoryHardLimit(cgroup, vm-def-mem.hard_limit); +if (rc != 0) { +virReportSystemError(-rc, + _(Unable to set memory hard limit for domain %s), + vm-def-name); +goto cleanup; +} +rc = virCgroupSetMemorySoftLimit(cgroup, vm-def-mem.soft_limit); +if (rc != 0) { +virReportSystemError(-rc, + _(Unable to set memory soft limit for domain %s), + vm-def-name); +goto cleanup; +} +rc = virCgroupSetSwapHardLimit(cgroup, vm-def-mem.swap_hard_limit); +if (rc != 0) { +virReportSystemError(-rc, + _(Unable to set swap hard limit for domain %s), + vm-def-name); +goto cleanup; +} +} else { +VIR_WARN(Memory cgroup is disabled in qemu configuration file: %s, + vm-def-name); +} + done: virCgroupFree(cgroup); return 0; -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2 01/11] Adding structure and defines for virDomainSetMemoryParameter
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com This patch adds a structure virMemoryParameter, it contains the name of the parameter and the type of the parameter along with a union. v2: + Includes dummy python bindings for the library to build cleanly. + Define string constants like hard_limit, etc. + re-order this patch. Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- include/libvirt/libvirt.h.in| 60 +++ python/generator.py |1 + python/libvirt-override-api.xml |6 python/libvirt-override.c |7 + 4 files changed, 74 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index b45f7ec..8f5d75d 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -674,6 +674,66 @@ int virDomainGetInfo (virDomainPtr domain, char * virDomainGetSchedulerType(virDomainPtr domain, int *nparams); +/** + * virDomainMemoryParameterType: + * + * A memory parameter field type + */ +typedef enum { +VIR_DOMAIN_MEMORY_FIELD_INT = 1, /* integer case */ +VIR_DOMAIN_MEMORY_FIELD_UINT= 2, /* unsigned integer case */ +VIR_DOMAIN_MEMORY_FIELD_LLONG = 3, /* long long case */ +VIR_DOMAIN_MEMORY_FIELD_ULLONG = 4, /* unsigned long long case */ +VIR_DOMAIN_MEMORY_FIELD_DOUBLE = 5, /* double case */ +VIR_DOMAIN_MEMORY_FIELD_BOOLEAN = 6 /* boolean(character) case */ +} virMemoryParameterType; + +/** + * VIR_DOMAIN_MEMORY_FIELD_LENGTH: + * + * Macro providing the field length of virMemoryParameter + */ + +#define VIR_DOMAIN_MEMORY_FIELD_LENGTH 80 +#define VIR_DOMAIN_MEMORY_HARD_LIMIT hard_limit +#define VIR_DOMAIN_MEMORY_SOFT_LIMIT soft_limit +#define VIR_DOMAIN_MEMORY_MIN_GUARANTEE min_guarantee +#define VIR_DOMAIN_SWAP_HARD_LIMIT swap_hard_limit + +/** + * virDomainMemoryParameter: + * + * a virDomainMemoryParameter is the set of scheduler parameters + */ + +typedef struct _virMemoryParameter virMemoryParameter; + +struct _virMemoryParameter { +char field[VIR_DOMAIN_MEMORY_FIELD_LENGTH]; /* parameter name */ +int type; /* parameter type */ +union { +int i; /* data for integer case */ +unsigned int ui;/* data for unsigned integer case */ +long long int l;/* data for long long integer case */ +unsigned long long int ul; /* data for unsigned long long integer case */ +double d; /* data for double case */ +char b; /* data for char case */ +} value; /* parameter value */ +}; + +/** + * virMemoryParameterPtr: + * + * a virMemoryParameterPtr is a pointer to a virMemoryParameter structure. + */ + +typedef virMemoryParameter *virMemoryParameterPtr; + +/* Set memory tunables for the domain*/ +int virDomainSetMemoryParameters(virDomainPtr domain, +virMemoryParameterPtr params, +int nparams); + /* * Dynamic control of domains */ diff --git a/python/generator.py b/python/generator.py index d876df6..8ae13d9 100755 --- a/python/generator.py +++ b/python/generator.py @@ -306,6 +306,7 @@ skip_impl = ( 'virDomainGetSchedulerType', 'virDomainGetSchedulerParameters', 'virDomainSetSchedulerParameters', +'virDomainSetMemoryParameters', 'virDomainGetVcpus', 'virDomainPinVcpu', 'virSecretGetValue', diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml index ca16993..6bef208 100644 --- a/python/libvirt-override-api.xml +++ b/python/libvirt-override-api.xml @@ -162,6 +162,12 @@ arg name='domain' type='virDomainPtr' info='pointer to domain object'/ arg name='params' type='virSchedParameterPtr' info='pointer to scheduler parameter objects'/ /function +function name='virDomainSetMemoryParameters' file='python' + infoChange the memory tunables/info + return type='int' info='-1 in case of error, 0 in case of success.'/ + arg name='domain' type='virDomainPtr' info='pointer to domain object'/ + arg name='params' type='virMemoryParameterPtr' info='pointer to memory tunable objects'/ +/function function name='virConnectListStoragePools' file='python' infolist the storage pools, stores the pointers to the names in @names/info arg name='conn' type='virConnectPtr' info='pointer to the hypervisor connection'/ diff --git a/python/libvirt-override.c b/python/libvirt-override.c index 54a84c2..c6cedcf 100644 --- a/python/libvirt-override.c +++ b/python/libvirt-override.c @@ -371,6 +371,13 @@ libvirt_virDomainSetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED, return VIR_PY_INT_SUCCESS; } +/* FIXME: This is a place holder for the implementation. */ +static PyObject * +libvirt_virDomainSetMemoryParameters(PyObject *self
[libvirt] [PATCH v2 06/11] Implement driver interface domainSetMemoryParamters for QEmu
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Driver interface for setting memory hard_limit, soft_limit and swap hard_limit. v2: + Use #define string constants for hard_limit, etc. + fix typo: min_guarantee Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/qemu/qemu_driver.c | 94 +++- 1 files changed, 93 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 17d4fbe..adf5f16 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -9365,6 +9365,98 @@ cleanup: return ret; } + +static int qemuDomainSetMemoryParameters(virDomainPtr dom, + virMemoryParameterPtr params, + int nparams) +{ +struct qemud_driver *driver = dom-conn-privateData; +int i; +virCgroupPtr group = NULL; +virDomainObjPtr vm = NULL; +int ret = -1; + +qemuDriverLock(driver); +if (!qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_MEMORY)) { +qemuReportError(VIR_ERR_NO_SUPPORT, +__FUNCTION__); +goto cleanup; +} + +vm = virDomainFindByUUID(driver-domains, dom-uuid); + +if (vm == NULL) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +_(No such domain %s), dom-uuid); +goto cleanup; +} + +if (virCgroupForDomain(driver-cgroup, vm-def-name, group, 0) != 0) { +qemuReportError(VIR_ERR_INTERNAL_ERROR, +_(cannot find cgroup for domain %s), vm-def-name); +goto cleanup; +} + +for (i = 0; i nparams; i++) { +virMemoryParameterPtr param = params[i]; + +if (STREQ(param-field, VIR_DOMAIN_MEMORY_HARD_LIMIT)) { +int rc; +if (param-type != VIR_DOMAIN_MEMORY_FIELD_ULLONG) { +qemuReportError(VIR_ERR_INVALID_ARG, %s, +_(invalid type for memory hard_limit tunable, expected a 'ullong')); +continue; +} + +rc = virCgroupSetMemoryHardLimit(group, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set memory hard_limit tunable)); +} +} else if (STREQ(param-field, VIR_DOMAIN_MEMORY_SOFT_LIMIT)) { +int rc; +if (param-type != VIR_DOMAIN_MEMORY_FIELD_ULLONG) { +qemuReportError(VIR_ERR_INVALID_ARG, %s, +_(invalid type for memory soft_limit tunable, expected a 'ullong')); +continue; +} + +rc = virCgroupSetMemorySoftLimit(group, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set memory soft_limit tunable)); +} +} else if (STREQ(param-field, VIR_DOMAIN_SWAP_HARD_LIMIT)) { +int rc; +if (param-type != VIR_DOMAIN_MEMORY_FIELD_ULLONG) { +qemuReportError(VIR_ERR_INVALID_ARG, %s, +_(invalid type for swap_hard_limit tunable, expected a 'ullong')); +continue; +} + +rc = virCgroupSetSwapHardLimit(group, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set swap_hard_limit tunable)); +} +} else if (STREQ(param-field, VIR_DOMAIN_MEMORY_MIN_GUARANTEE)) { +qemuReportError(VIR_ERR_INVALID_ARG, +_(Memory tunable `%s' not implemented), param-field); +} else { +qemuReportError(VIR_ERR_INVALID_ARG, +_(Parameter `%s' not supported), param-field); +} +} +ret = 0; + +cleanup: +virCgroupFree(group); +if (vm) +virDomainObjUnlock(vm); +qemuDriverUnlock(driver); +return ret; +} + static int qemuSetSchedulerParameters(virDomainPtr dom, virSchedParameterPtr params, int nparams) @@ -12710,7 +12802,7 @@ static virDriver qemuDriver = { qemuDomainRevertToSnapshot, /* domainRevertToSnapshot */ qemuDomainSnapshotDelete, /* domainSnapshotDelete */ qemuDomainMonitorCommand, /* qemuDomainMonitorCommand */ -NULL, /* domainSetMemoryParameters */ +qemuDomainSetMemoryParameters, /* domainSetMemoryParameters */ }; -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2 02/11] Adding virDomainSetMemoryParameters API
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Public api to set memory tunables supported by the hypervisors. RFC: https://www.redhat.com/archives/libvir-list/2010-August/msg00607.html v2: Initialize domainSetMemoryParameters to NULL in all the driver interface structure. Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/driver.h |6 + src/esx/esx_driver.c |1 + src/libvirt.c | 49 src/lxc/lxc_driver.c |1 + src/openvz/openvz_driver.c |1 + src/phyp/phyp_driver.c |1 + src/qemu/qemu_driver.c |1 + src/remote/remote_driver.c |1 + src/test/test_driver.c |1 + src/uml/uml_driver.c |1 + src/xen/xen_driver.c |1 + 11 files changed, 64 insertions(+), 0 deletions(-) diff --git a/src/driver.h b/src/driver.h index e443c1c..01004e3 100644 --- a/src/driver.h +++ b/src/driver.h @@ -128,6 +128,11 @@ typedef int (*virDrvDomainSetMemory) (virDomainPtr domain, unsigned long memory); typedef int +(*virDrvDomainSetMemoryParameters) +(virDomainPtr domain, + virMemoryParameterPtr params, + int nparams); +typedef int (*virDrvDomainGetInfo) (virDomainPtr domain, virDomainInfoPtr info); typedef int @@ -575,6 +580,7 @@ struct _virDriver { virDrvDomainRevertToSnapshot domainRevertToSnapshot; virDrvDomainSnapshotDelete domainSnapshotDelete; virDrvQemuDomainMonitorCommand qemuDomainMonitorCommand; +virDrvDomainSetMemoryParameters domainSetMemoryParameters; }; typedef int diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index e382950..be55796 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -4217,6 +4217,7 @@ static virDriver esxDriver = { esxDomainRevertToSnapshot, /* domainRevertToSnapshot */ esxDomainSnapshotDelete, /* domainSnapshotDelete */ NULL,/* qemuDomainMonitorCommand */ +NULL,/* domainSetMemoryParameters */ }; diff --git a/src/libvirt.c b/src/libvirt.c index ca383ba..64daaa3 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -3000,6 +3000,55 @@ error: } /** + * virDomainSetMemoryParameters: + * @domain: pointer to domain object + * @params: pointer to memory parameter objects + * @nparams: number of memory parameter (this value should be same or + * less than the number of parameters supported) + * + * Change the memory tunables + * This function requires privileged access to the hypervisor. + * FIXME: Should we make changes to the domain configuration file as well? + * + * Returns -1 in case of error, 0 in case of success. + */ +int +virDomainSetMemoryParameters(virDomainPtr domain, +virMemoryParameterPtr params, +int nparams) +{ +virConnectPtr conn; +DEBUG(domain=%p, params=%p, nparams=%d, domain, params, nparams); + +virResetLastError(); + +if (!VIR_IS_CONNECTED_DOMAIN(domain)) { +virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); +virDispatchError(NULL); +return -1; +} +if (domain-conn-flags VIR_CONNECT_RO) { +virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); +goto error; +} +conn = domain-conn; + +if (conn-driver-domainSetMemoryParameters) { +int ret; +ret = conn-driver-domainSetMemoryParameters (domain, params, nparams); +if (ret 0) +goto error; +return ret; +} + +virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: +virDispatchError(domain-conn); +return -1; +} + +/** * virDomainGetInfo: * @domain: a domain object * @info: pointer to a virDomainInfo structure allocated by the user diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 326fee6..9a4843d 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -2620,6 +2620,7 @@ static virDriver lxcDriver = { NULL, /* domainRevertToSnapshot */ NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ +NULL, /* domainSetMemoryParameters */ }; static virStateDriver lxcStateDriver = { diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c index 1ad93d9..edef080 100644 --- a/src/openvz/openvz_driver.c +++ b/src/openvz/openvz_driver.c @@ -1657,6 +1657,7 @@ static virDriver openvzDriver = { NULL, /* domainRevertToSnapshot */ NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ +NULL, /* domainSetMemoryParameters */ }; int openvzRegister(void) { diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c index 8eeba73..fce451c 100644 --- a/src/phyp
[libvirt] [PATCH v2 11/11] Implement domainSetMemoryParameters function
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Add support in the lxc driver for various memory controllable parameters v2: + Use #define string constants for hard_limit, etc + fix typo: min_guarantee Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/lxc/lxc_driver.c | 90 +- 1 files changed, 89 insertions(+), 1 deletions(-) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 9e37906..6ffcd39 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -677,6 +677,94 @@ cleanup: return ret; } +static int lxcDomainSetMemoryParameters(virDomainPtr dom, +virMemoryParameterPtr params, +int nparams) +{ +lxc_driver_t *driver = dom-conn-privateData; +int i; +virCgroupPtr cgroup = NULL; +virDomainObjPtr vm = NULL; +int ret = -1; + +lxcDriverLock(driver); +vm = virDomainFindByUUID(driver-domains, dom-uuid); + +if (vm == NULL) { +char uuidstr[VIR_UUID_STRING_BUFLEN]; +virUUIDFormat(dom-uuid, uuidstr); +lxcError(VIR_ERR_NO_DOMAIN, + _(No domain with matching uuid '%s'), uuidstr); +goto cleanup; +} + +if (virCgroupForDomain(driver-cgroup, vm-def-name, cgroup, 0) != 0) { +lxcError(VIR_ERR_INTERNAL_ERROR, + _(Unable to get cgroup for %s), vm-def-name); +goto cleanup; +} + +for (i = 0; i nparams; i++) { +virMemoryParameterPtr param = params[i]; + +if (STREQ(param-field, VIR_DOMAIN_MEMORY_HARD_LIMIT)) { +int rc; +if (param-type != VIR_DOMAIN_MEMORY_FIELD_ULLONG) { +lxcError(VIR_ERR_INVALID_ARG, %s, + _(invalid type for memory hard_limit tunable, expected a 'ullong')); +continue; +} + +rc = virCgroupSetMemoryHardLimit(cgroup, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set memory hard_limit tunable)); +} +} else if (STREQ(param-field, VIR_DOMAIN_MEMORY_SOFT_LIMIT)) { +int rc; +if (param-type != VIR_DOMAIN_MEMORY_FIELD_ULLONG) { +lxcError(VIR_ERR_INVALID_ARG, %s, + _(invalid type for memory soft_limit tunable, expected a 'ullong')); +continue; +} + +rc = virCgroupSetMemorySoftLimit(cgroup, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set memory soft_limit tunable)); +} +} else if (STREQ(param-field, VIR_DOMAIN_SWAP_HARD_LIMIT)) { +int rc; +if (param-type != VIR_DOMAIN_MEMORY_FIELD_ULLONG) { +lxcError(VIR_ERR_INVALID_ARG, %s, + _(invalid type for swap_hard_limit tunable, expected a 'ullong')); +continue; +} + +rc = virCgroupSetSwapHardLimit(cgroup, params[i].value.ul); +if (rc != 0) { +virReportSystemError(-rc, %s, + _(unable to set swap_hard_limit tunable)); +} +} else if (STREQ(param-field, VIR_DOMAIN_MEMORY_MIN_GUARANTEE)) { +lxcError(VIR_ERR_INVALID_ARG, + _(Memory tunable `%s' not implemented), param-field); +} else { +lxcError(VIR_ERR_INVALID_ARG, + _(Parameter `%s' not supported), param-field); +} +} +ret = 0; + +cleanup: +if (cgroup) +virCgroupFree(cgroup); +if (vm) +virDomainObjUnlock(vm); +lxcDriverUnlock(driver); +return ret; +} + static char *lxcDomainDumpXML(virDomainPtr dom, int flags) { @@ -2620,7 +2708,7 @@ static virDriver lxcDriver = { NULL, /* domainRevertToSnapshot */ NULL, /* domainSnapshotDelete */ NULL, /* qemuDomainMonitorCommand */ -NULL, /* domainSetMemoryParameters */ +lxcDomainSetMemoryParameters, /* domainSetMemoryParameters */ }; static virStateDriver lxcStateDriver = { -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2 03/11] Adds xml entries for memory tunables
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com The patch adds xml entries to the domain.rng file. v2: + Fix typo min_guarantee Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- docs/schemas/domain.rng | 31 +++ 1 files changed, 31 insertions(+), 0 deletions(-) diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index ccb8cf3..d75254c 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -299,6 +299,37 @@ /optional /element /optional + + !-- All the memory/swap related tunables would go in the memtune -- + optional + element name=memtune + !-- Maximum memory the VM can use -- + optional + element name=hard_limit + ref name=memoryKB/ + /element + /optional + !-- Minimum memory ascertained for the VM during contention -- + optional + element name=soft_limit + ref name=memoryKB/ + /element + /optional + !-- Minimum amount of memory required to start the VM -- + optional + element name=min_guarantee + ref name=memoryKB/ + /element + /optional + !-- Maximum swap area the VM can use -- + optional + element name=swap_hard_limit + ref name=memoryKB/ + /element + /optional + /element + /optional + optional element name=vcpu optional -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
[libvirt] [PATCH v2 04/11] XML parsing for memory tunables
From: Nikunj A. Dadhania nik...@linux.vnet.ibm.com Adding parsing code for memory tunables in the domain xml file v2: + Fix typo min_guarantee Signed-off-by: Nikunj A. Dadhania nik...@linux.vnet.ibm.com --- src/conf/domain_conf.c | 50 +--- src/conf/domain_conf.h | 12 --- src/esx/esx_vmx.c | 30 +- src/lxc/lxc_controller.c |2 +- src/lxc/lxc_driver.c | 12 +-- src/openvz/openvz_driver.c |8 --- src/qemu/qemu_conf.c |8 --- src/qemu/qemu_driver.c | 18 src/test/test_driver.c | 12 +-- src/uml/uml_conf.c |2 +- src/uml/uml_driver.c | 14 ++-- 11 files changed, 104 insertions(+), 64 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index e05d5d7..0dd74e4 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4231,19 +4231,38 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, def-description = virXPathString(string(./description[1]), ctxt); /* Extract domain memory */ -if (virXPathULong(string(./memory[1]), ctxt, def-maxmem) 0) { +if (virXPathULong(string(./memory[1]), ctxt, + def-mem.max_balloon) 0) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, %s, _(missing memory element)); goto error; } -if (virXPathULong(string(./currentMemory[1]), ctxt, def-memory) 0) -def-memory = def-maxmem; +if (virXPathULong(string(./currentMemory[1]), ctxt, + def-mem.cur_balloon) 0) +def-mem.cur_balloon = def-mem.max_balloon; node = virXPathNode(./memoryBacking/hugepages, ctxt); if (node) -def-hugepage_backed = 1; - +def-mem.hugepage_backed = 1; + +/* Extract other memory tunables */ +if (virXPathULong(string(./memtune/hard_limit), ctxt, + def-mem.hard_limit) 0) +def-mem.hard_limit = 0; + +if (virXPathULong(string(./memtune/soft_limit[1]), ctxt, + def-mem.soft_limit) 0) +def-mem.soft_limit = 0; + +if (virXPathULong(string(./memtune/min_guarantee[1]), ctxt, + def-mem.min_guarantee) 0) +def-mem.min_guarantee = 0; + +if (virXPathULong(string(./memtune/swap_hard_limit[1]), ctxt, + def-mem.swap_hard_limit) 0) +def-mem.swap_hard_limit = 0; + if (virXPathULong(string(./vcpu[1]), ctxt, def-vcpus) 0) def-vcpus = 1; @@ -6382,10 +6401,25 @@ char *virDomainDefFormat(virDomainDefPtr def, virBufferEscapeString(buf, description%s/description\n, def-description); -virBufferVSprintf(buf, memory%lu/memory\n, def-maxmem); +virBufferVSprintf(buf, memory%lu/memory\n, def-mem.max_balloon); virBufferVSprintf(buf, currentMemory%lu/currentMemory\n, - def-memory); -if (def-hugepage_backed) { + def-mem.cur_balloon); +virBufferVSprintf(buf, memtune\n); +if (def-mem.hard_limit) { +virBufferVSprintf(buf, hard_limit%lu/hard_limit\n, + def-mem.hard_limit); +} +if (def-mem.soft_limit) { +virBufferVSprintf(buf, soft_limit%lu/soft_limit\n, + def-mem.soft_limit); +} +if (def-mem.swap_hard_limit) { +virBufferVSprintf(buf, swap_hard_limit%lu/swap_hard_limit\n, + def-mem.swap_hard_limit); +} +virBufferVSprintf(buf, /memtune\n); + +if (def-mem.hugepage_backed) { virBufferAddLit(buf, memoryBacking\n); virBufferAddLit(buf, hugepages/\n); virBufferAddLit(buf, /memoryBacking\n); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 7195c04..2ecc2af 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -864,9 +864,15 @@ struct _virDomainDef { char *name; char *description; -unsigned long memory; -unsigned long maxmem; -unsigned char hugepage_backed; +struct { +unsigned long max_balloon; +unsigned long cur_balloon; +unsigned long hugepage_backed; +unsigned long hard_limit; +unsigned long soft_limit; +unsigned long min_guarantee; +unsigned long swap_hard_limit; +} mem; unsigned long vcpus; int cpumasklen; char *cpumask; diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c index 59eb3b2..6f1eb17 100644 --- a/src/esx/esx_vmx.c +++ b/src/esx/esx_vmx.c @@ -48,8 +48,8 @@ domain-xml= vmx def-id = value = ??? # not representable def-uuid = value = uuid.bios = value def-name = value = displayName = value -def-maxmem = value kilobyte= memsize = value