[libvirt] [PATCH v2 0/3] configure inactive domains' maximum memory size

Hi all, This patchset enables us to configure inactive domain's maximum memory size. v1 -> v2: - recreate based on 0.9.0 - fix some typo *[PATCH 1/3] maxmem: introduces VIR_DOMAIN_MEM_MAXIMUM flag *[PATCH 2/3] maxmem: implement virDomainSetMaxMemory API of the qemu driver *[PATCH 3/3] setmaxmem: add the new options to "virsh setmaxmem" command Best regards, Taku Izumi

This patch introduces VIR_DOMAIN_MEM_MAXIMUM flag. Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com> --- include/libvirt/libvirt.h.in | 1 + src/libvirt.c | 2 ++ 2 files changed, 3 insertions(+) Index: libvirt/include/libvirt/libvirt.h.in =================================================================== --- libvirt.orig/include/libvirt/libvirt.h.in +++ libvirt/include/libvirt/libvirt.h.in @@ -857,6 +857,7 @@ typedef enum { VIR_DOMAIN_MEM_CURRENT = 0, /* affect current domain state */ VIR_DOMAIN_MEM_LIVE = (1 << 0), /* affect active domain */ VIR_DOMAIN_MEM_CONFIG = (1 << 1), /* affect next boot */ + VIR_DOMAIN_MEM_MAXIMUM = (1 << 2), /* affect Max rather than current */ } virDomainMemoryModFlags; Index: libvirt/src/libvirt.c =================================================================== --- libvirt.orig/src/libvirt.c +++ libvirt/src/libvirt.c @@ -2832,6 +2832,8 @@ error: * (that is, @flags is VIR_DOMAIN_MEM_CURRENT), then an inactive domain * modifies persistent setup, while an active domain is hypervisor-dependent * on whether just live or both live and persistent state is changed. + * If VIR_DOMAIN_MEM_MAXIMUM is set, the change affects domain's maximum memory + * size rather than current memory size. * Not all hypervisors can support all flag combinations. * * Returns 0 in case of success, -1 in case of failure.

On Fri, Apr 08, 2011 at 02:07:27PM +0900, Taku Izumi wrote:
This patch introduces VIR_DOMAIN_MEM_MAXIMUM flag.
Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com> --- include/libvirt/libvirt.h.in | 1 + src/libvirt.c | 2 ++ 2 files changed, 3 insertions(+)
Index: libvirt/include/libvirt/libvirt.h.in =================================================================== --- libvirt.orig/include/libvirt/libvirt.h.in +++ libvirt/include/libvirt/libvirt.h.in @@ -857,6 +857,7 @@ typedef enum { VIR_DOMAIN_MEM_CURRENT = 0, /* affect current domain state */
This patch doesn't apply, the file in my git tree doesn't have the above line. (I've double-checked and made sure I didn't make a mistake) Would you mind to have a check on your tree?
VIR_DOMAIN_MEM_LIVE = (1 << 0), /* affect active domain */ VIR_DOMAIN_MEM_CONFIG = (1 << 1), /* affect next boot */ + VIR_DOMAIN_MEM_MAXIMUM = (1 << 2), /* affect Max rather than current */ } virDomainMemoryModFlags;
Index: libvirt/src/libvirt.c =================================================================== --- libvirt.orig/src/libvirt.c +++ libvirt/src/libvirt.c @@ -2832,6 +2832,8 @@ error: * (that is, @flags is VIR_DOMAIN_MEM_CURRENT), then an inactive domain * modifies persistent setup, while an active domain is hypervisor-dependent * on whether just live or both live and persistent state is changed. + * If VIR_DOMAIN_MEM_MAXIMUM is set, the change affects domain's maximum memory + * size rather than current memory size. * Not all hypervisors can support all flag combinations. * * Returns 0 in case of success, -1 in case of failure.
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

On Fri, Apr 08, 2011 at 03:51:44PM +0800, Hu Tao wrote:
On Fri, Apr 08, 2011 at 02:07:27PM +0900, Taku Izumi wrote:
This patch introduces VIR_DOMAIN_MEM_MAXIMUM flag.
Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com> --- include/libvirt/libvirt.h.in | 1 + src/libvirt.c | 2 ++ 2 files changed, 3 insertions(+)
Index: libvirt/include/libvirt/libvirt.h.in =================================================================== --- libvirt.orig/include/libvirt/libvirt.h.in +++ libvirt/include/libvirt/libvirt.h.in @@ -857,6 +857,7 @@ typedef enum { VIR_DOMAIN_MEM_CURRENT = 0, /* affect current domain state */
This patch doesn't apply, the file in my git tree doesn't have the above line. (I've double-checked and made sure I didn't make a mistake) Would you mind to have a check on your tree?
Sorry, my problem here. There is lag on our git server.

On 04/07/2011 11:07 PM, Taku Izumi wrote:
This patch introduces VIR_DOMAIN_MEM_MAXIMUM flag.
Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com> --- include/libvirt/libvirt.h.in | 1 + src/libvirt.c | 2 ++ 2 files changed, 3 insertions(+)
Index: libvirt/include/libvirt/libvirt.h.in =================================================================== --- libvirt.orig/include/libvirt/libvirt.h.in +++ libvirt/include/libvirt/libvirt.h.in @@ -857,6 +857,7 @@ typedef enum { VIR_DOMAIN_MEM_CURRENT = 0, /* affect current domain state */ VIR_DOMAIN_MEM_LIVE = (1 << 0), /* affect active domain */ VIR_DOMAIN_MEM_CONFIG = (1 << 1), /* affect next boot */ + VIR_DOMAIN_MEM_MAXIMUM = (1 << 2), /* affect Max rather than current */ } virDomainMemoryModFlags;
ACK and pushed. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

This patch implements the code to support virDomainSetMaxMemory API, and to support VIR_DOMAIN_MEM_MAXIMUM flag in qemudDomainSetMemoryFlags function. As a result, we can change the maximum memory size of inactive QEMU guests. Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com> --- src/qemu/qemu_driver.c | 81 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 24 deletions(-) Index: libvirt/src/qemu/qemu_driver.c =================================================================== --- libvirt.orig/src/qemu/qemu_driver.c +++ libvirt/src/qemu/qemu_driver.c @@ -1580,7 +1580,8 @@ static int qemudDomainSetMemoryFlags(vir bool isActive; virCheckFlags(VIR_DOMAIN_MEM_LIVE | - VIR_DOMAIN_MEM_CONFIG, -1); + VIR_DOMAIN_MEM_CONFIG | + VIR_DOMAIN_MEM_MAXIMUM, -1); qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); @@ -1593,12 +1594,6 @@ static int qemudDomainSetMemoryFlags(vir goto cleanup; } - if (newmem > vm->def->mem.max_balloon) { - qemuReportError(VIR_ERR_INVALID_ARG, - "%s", _("cannot set memory higher than max memory")); - goto cleanup; - } - if (qemuDomainObjBeginJob(vm) < 0) goto cleanup; @@ -1610,6 +1605,12 @@ static int qemudDomainSetMemoryFlags(vir else flags = VIR_DOMAIN_MEM_CONFIG; } + if (flags == VIR_DOMAIN_MEM_MAXIMUM) { + if (isActive) + flags = VIR_DOMAIN_MEM_LIVE | VIR_DOMAIN_MEM_MAXIMUM; + else + flags = VIR_DOMAIN_MEM_CONFIG | VIR_DOMAIN_MEM_MAXIMUM; + } if (!isActive && (flags & VIR_DOMAIN_MEM_LIVE)) { qemuReportError(VIR_ERR_OPERATION_INVALID, @@ -1627,27 +1628,54 @@ static int qemudDomainSetMemoryFlags(vir goto endjob; } - if (flags & VIR_DOMAIN_MEM_LIVE) { - priv = vm->privateData; - qemuDomainObjEnterMonitor(vm); - r = qemuMonitorSetBalloon(priv->mon, newmem); - qemuDomainObjExitMonitor(vm); - qemuAuditMemory(vm, vm->def->mem.cur_balloon, newmem, "update", r == 1); - if (r < 0) - goto endjob; + if (flags & VIR_DOMAIN_MEM_MAXIMUM) { + /* resize the maximum memory */ - /* Lack of balloon support is a fatal error */ - if (r == 0) { + if (flags & VIR_DOMAIN_MEM_LIVE) { qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot set memory of an active domain")); + _("cannot resize the maximum memory on an active domain")); goto endjob; } - } - if (flags& VIR_DOMAIN_MEM_CONFIG) { - persistentDef->mem.cur_balloon = newmem; - ret = virDomainSaveConfig(driver->configDir, persistentDef); - goto endjob; + if (flags & VIR_DOMAIN_MEM_CONFIG) { + persistentDef->mem.max_balloon = newmem; + if (persistentDef->mem.cur_balloon > newmem) + persistentDef->mem.cur_balloon = newmem; + ret = virDomainSaveConfig(driver->configDir, persistentDef); + goto endjob; + } + + } else { + /* resize the current memory */ + + if (newmem > vm->def->mem.max_balloon) { + qemuReportError(VIR_ERR_INVALID_ARG, + "%s", _("cannot set memory higher than max memory")); + goto endjob; + } + + if (flags & VIR_DOMAIN_MEM_LIVE) { + priv = vm->privateData; + qemuDomainObjEnterMonitor(vm); + r = qemuMonitorSetBalloon(priv->mon, newmem); + qemuDomainObjExitMonitor(vm); + qemuAuditMemory(vm, vm->def->mem.cur_balloon, newmem, "update", r == 1); + if (r < 0) + goto endjob; + + /* Lack of balloon support is a fatal error */ + if (r == 0) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("cannot set memory of an active domain")); + goto endjob; + } + } + + if (flags & VIR_DOMAIN_MEM_CONFIG) { + persistentDef->mem.cur_balloon = newmem; + ret = virDomainSaveConfig(driver->configDir, persistentDef); + goto endjob; + } } ret = 0; @@ -1665,6 +1693,11 @@ static int qemudDomainSetMemory(virDomai return qemudDomainSetMemoryFlags(dom, newmem, VIR_DOMAIN_MEM_LIVE); } +static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long memory) { + return qemudDomainSetMemoryFlags(dom, memory, + VIR_DOMAIN_MEM_MAXIMUM | VIR_DOMAIN_MEM_LIVE); +} + static int qemudDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) { struct qemud_driver *driver = dom->conn->privateData; @@ -6849,7 +6882,7 @@ static virDriver qemuDriver = { qemudDomainDestroy, /* domainDestroy */ qemudDomainGetOSType, /* domainGetOSType */ qemudDomainGetMaxMemory, /* domainGetMaxMemory */ - NULL, /* domainSetMaxMemory */ + qemudDomainSetMaxMemory, /* domainSetMaxMemory */ qemudDomainSetMemory, /* domainSetMemory */ qemudDomainSetMemoryFlags, /* domainSetMemoryFlags */ qemuDomainSetMemoryParameters, /* domainSetMemoryParameters */

On 04/07/2011 11:08 PM, Taku Izumi wrote:
This patch implements the code to support virDomainSetMaxMemory API, and to support VIR_DOMAIN_MEM_MAXIMUM flag in qemudDomainSetMemoryFlags function. As a result, we can change the maximum memory size of inactive QEMU guests.
Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com> --- src/qemu/qemu_driver.c | 81 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 24 deletions(-)
@@ -1593,12 +1594,6 @@ static int qemudDomainSetMemoryFlags(vir goto cleanup; }
- if (newmem > vm->def->mem.max_balloon) { - qemuReportError(VIR_ERR_INVALID_ARG, - "%s", _("cannot set memory higher than max memory")); - goto cleanup; - } -
Why are you dropping this check? Oh, I should read the whole patch first...
@@ -1610,6 +1605,12 @@ static int qemudDomainSetMemoryFlags(vir else flags = VIR_DOMAIN_MEM_CONFIG; } + if (flags == VIR_DOMAIN_MEM_MAXIMUM) { + if (isActive) + flags = VIR_DOMAIN_MEM_LIVE | VIR_DOMAIN_MEM_MAXIMUM;
qemu can't change the maximum memory allocation of an active domain. Oh, but I see you catch that later...
+ else + flags = VIR_DOMAIN_MEM_CONFIG | VIR_DOMAIN_MEM_MAXIMUM; + }
if (!isActive && (flags & VIR_DOMAIN_MEM_LIVE)) { qemuReportError(VIR_ERR_OPERATION_INVALID, @@ -1627,27 +1628,54 @@ static int qemudDomainSetMemoryFlags(vir goto endjob; }
- if (flags & VIR_DOMAIN_MEM_LIVE) { - priv = vm->privateData; - qemuDomainObjEnterMonitor(vm); - r = qemuMonitorSetBalloon(priv->mon, newmem); - qemuDomainObjExitMonitor(vm); - qemuAuditMemory(vm, vm->def->mem.cur_balloon, newmem, "update", r == 1); - if (r < 0) - goto endjob; + if (flags & VIR_DOMAIN_MEM_MAXIMUM) { + /* resize the maximum memory */
- /* Lack of balloon support is a fatal error */ - if (r == 0) { + if (flags & VIR_DOMAIN_MEM_LIVE) { qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot set memory of an active domain")); + _("cannot resize the maximum memory on an active domain"));
Needs a "%s" to keep compilation without gettext happy (that's the only case where gcc starts warning about a format string with no % in it). But this answers my second question.
goto endjob; } - }
- if (flags& VIR_DOMAIN_MEM_CONFIG) { - persistentDef->mem.cur_balloon = newmem; - ret = virDomainSaveConfig(driver->configDir, persistentDef); - goto endjob; + if (flags & VIR_DOMAIN_MEM_CONFIG) { + persistentDef->mem.max_balloon = newmem; + if (persistentDef->mem.cur_balloon > newmem) + persistentDef->mem.cur_balloon = newmem; + ret = virDomainSaveConfig(driver->configDir, persistentDef);
Good - you cap the current memory if the maximum dropped.
+ goto endjob; + } + + } else { + /* resize the current memory */ + + if (newmem > vm->def->mem.max_balloon) { + qemuReportError(VIR_ERR_INVALID_ARG, + "%s", _("cannot set memory higher than max memory"));
Ah, you moved it down lower, answering my first question.
+ goto endjob; + } + + if (flags & VIR_DOMAIN_MEM_LIVE) { + priv = vm->privateData; + qemuDomainObjEnterMonitor(vm); + r = qemuMonitorSetBalloon(priv->mon, newmem); + qemuDomainObjExitMonitor(vm); + qemuAuditMemory(vm, vm->def->mem.cur_balloon, newmem, "update", r == 1);
This indentation caused lines longer than 80 columns, so I tweaked that.
+ if (r < 0) + goto endjob; + + /* Lack of balloon support is a fatal error */ + if (r == 0) { + qemuReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("cannot set memory of an active domain")); + goto endjob; + } + } + + if (flags & VIR_DOMAIN_MEM_CONFIG) { + persistentDef->mem.cur_balloon = newmem; + ret = virDomainSaveConfig(driver->configDir, persistentDef); + goto endjob; + } }
ret = 0; @@ -1665,6 +1693,11 @@ static int qemudDomainSetMemory(virDomai return qemudDomainSetMemoryFlags(dom, newmem, VIR_DOMAIN_MEM_LIVE); }
+static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long memory) { + return qemudDomainSetMemoryFlags(dom, memory, + VIR_DOMAIN_MEM_MAXIMUM | VIR_DOMAIN_MEM_LIVE);
Hmm. Given the above implementation, this will _always_ fail. Then again, the failure message will be nicer (the function used to fail with "not implemented", now it fails with "cannot resize memory on an active domain"), so I guess it's okay to provide this stub. And given the documentation in libvirt.c, this is accurate (that documentation explicitly stated that it only works on live domains). But the real clincher is how xen behaves. I just tested, and my RHEL 5 machine with xen:/// was able to change persistent max memory of an inactive domain, so the documentation in libvirt.c is wrong. I then tried an active domain, which (surprisingly) changed the max cap, then promptly forgot the change when the domain went inactive again proving that it behaved like _LIVE and not _LIVE|_CONFIG. Qemu can't change max mem on a live domain (it's capped at qemu startup time) even if xen can, so if we tweak the libvirt.c wording to accommodate both xen and qemu behaviors (since it was already inaccurate for xen), then we can make this function succeed some of the time by defaulting to _CURRENT|_MAXIMUM instead of _LIVE|_MAXIMUM.
+} + static int qemudDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) { struct qemud_driver *driver = dom->conn->privateData; @@ -6849,7 +6882,7 @@ static virDriver qemuDriver = { qemudDomainDestroy, /* domainDestroy */ qemudDomainGetOSType, /* domainGetOSType */ qemudDomainGetMaxMemory, /* domainGetMaxMemory */ - NULL, /* domainSetMaxMemory */ + qemudDomainSetMaxMemory, /* domainSetMaxMemory */ qemudDomainSetMemory, /* domainSetMemory */ qemudDomainSetMemoryFlags, /* domainSetMemoryFlags */ qemuDomainSetMemoryParameters, /* domainSetMemoryParameters */
So, here's what I squashed in before pushing: diff --git i/src/libvirt.c w/src/libvirt.c index 4a39695..0da9885 100644 --- i/src/libvirt.c +++ w/src/libvirt.c @@ -2714,8 +2714,9 @@ error: * to Domain0 i.e. the domain where the application runs. * This function requires privileged access to the hypervisor. * - * This command only changes the runtime configuration of the domain, - * so can only be called on an active domain. + * This command is hypervisor-specific for whether active, persistent, + * or both configurations are changed; for more control, use + * virDomainSetMemoryFlags(). * * Returns 0 in case of success and -1 in case of failure. */ diff --git i/src/qemu/qemu_driver.c w/src/qemu/qemu_driver.c index a547faf..8a8b55d 100644 --- i/src/qemu/qemu_driver.c +++ w/src/qemu/qemu_driver.c @@ -1632,8 +1632,9 @@ static int qemudDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem, /* resize the maximum memory */ if (flags & VIR_DOMAIN_MEM_LIVE) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - _("cannot resize the maximum memory on an active domain")); + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot resize the maximum memory on an " + "active domain")); goto endjob; } @@ -1649,8 +1650,8 @@ static int qemudDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem, /* resize the current memory */ if (newmem > vm->def->mem.max_balloon) { - qemuReportError(VIR_ERR_INVALID_ARG, - "%s", _("cannot set memory higher than max memory")); + qemuReportError(VIR_ERR_INVALID_ARG, "%s", + _("cannot set memory higher than max memory")); goto endjob; } @@ -1659,14 +1660,15 @@ static int qemudDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem, qemuDomainObjEnterMonitor(vm); r = qemuMonitorSetBalloon(priv->mon, newmem); qemuDomainObjExitMonitor(vm); - qemuAuditMemory(vm, vm->def->mem.cur_balloon, newmem, "update", r == 1); + qemuAuditMemory(vm, vm->def->mem.cur_balloon, newmem, "update", + r == 1); if (r < 0) goto endjob; /* Lack of balloon support is a fatal error */ if (r == 0) { - qemuReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("cannot set memory of an active domain")); + qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("cannot set memory of an active domain")); goto endjob; } } @@ -1695,7 +1697,8 @@ static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) { static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long memory) { return qemudDomainSetMemoryFlags(dom, memory, - VIR_DOMAIN_MEM_MAXIMUM | VIR_DOMAIN_MEM_LIVE); + (VIR_DOMAIN_MEM_MAXIMUM | + VIR_DOMAIN_MEM_CURRENT)); } static int qemudDomainGetInfo(virDomainPtr dom, -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Fri, Apr 08, 2011 at 05:39:36PM -0600, Eric Blake wrote:
On 04/07/2011 11:08 PM, Taku Izumi wrote:
This patch implements the code to support virDomainSetMaxMemory API, and to support VIR_DOMAIN_MEM_MAXIMUM flag in qemudDomainSetMemoryFlags function. As a result, we can change the maximum memory size of inactive QEMU guests.
[...]
+static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long memory) { + return qemudDomainSetMemoryFlags(dom, memory, + VIR_DOMAIN_MEM_MAXIMUM | VIR_DOMAIN_MEM_LIVE);
Hmm. Given the above implementation, this will _always_ fail. Then again, the failure message will be nicer (the function used to fail with "not implemented", now it fails with "cannot resize memory on an active domain"), so I guess it's okay to provide this stub. And given the documentation in libvirt.c, this is accurate (that documentation explicitly stated that it only works on live domains).
But the real clincher is how xen behaves. I just tested, and my RHEL 5 machine with xen:/// was able to change persistent max memory of an inactive domain, so the documentation in libvirt.c is wrong. I then
Hum, how did you test this ? This sounds weird to me, maybe the xen code really improved, but basically the max memory information was used by the hypervisor (micro) kernel to allocate things like size of page tablesetc. for the gues and well that could not be changed dynamically, once the guest was started say with a max_memory of 4G you would not be able to "live" change the max_memory to 16GB and grow the guest memory to more than 4G.
tried an active domain, which (surprisingly) changed the max cap, then promptly forgot the change when the domain went inactive again proving that it behaved like _LIVE and not _LIVE|_CONFIG. Qemu can't change max mem on a live domain (it's capped at qemu startup time) even if xen can,
I'm still wondering about this :-)
so if we tweak the libvirt.c wording to accommodate both xen and qemu behaviors (since it was already inaccurate for xen), then we can make this function succeed some of the time by defaulting to _CURRENT|_MAXIMUM instead of _LIVE|_MAXIMUM.
Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

+static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long memory) { + return qemudDomainSetMemoryFlags(dom, memory, + VIR_DOMAIN_MEM_MAXIMUM | VIR_DOMAIN_MEM_LIVE);
Hmm. Given the above implementation, this will _always_ fail. Then again, the failure message will be nicer (the function used to fail with "not implemented", now it fails with "cannot resize memory on an active domain"), so I guess it's okay to provide this stub. And given the documentation in libvirt.c, this is accurate (that documentation explicitly stated that it only works on live domains).
But the real clincher is how xen behaves. I just tested, and my RHEL 5 machine with xen:/// was able to change persistent max memory of an inactive domain, so the documentation in libvirt.c is wrong. I then
Hum, how did you test this ? This sounds weird to me, maybe the xen code really improved, but basically the max memory information was used by the hypervisor (micro) kernel to allocate things like size of page tablesetc. for the gues and well that could not be changed dynamically, once the guest was started say with a max_memory of 4G you would not be able to "live" change the max_memory to 16GB and grow the guest memory to more than 4G.
I tested as follows. Note that libvirt was able to see that xen "claimed" to have a larger max memory, but that I did not actually try to balloon the guest to the larger memory, so it could be that the balloon attempt would still fail, in which case we could argue that xen has a bug for allowing the setmaxmem to "succeed" on an active domain. I tested with libvirt 0.8.2 built for RHEL 5.6: # virsh list --all Id Name State ------------------------- 0 Domain-0 running - dom shut off # virsh dumpxml dom | grep emory <memory>524288</memory> <currentMemory>524288</currentMemory> # virsh setmaxmem dom 600000 && echo $? 0 # virsh dumpxml dom | grep emory <memory>599040</memory> <currentMemory>524288</currentMemory> # virsh start dom Domain dom started # virsh setmaxmem dom 580000 && echo $? # virsh dumpxml dom | grep emory <memory>579584</memory> <currentMemory>524288</currentMemory> # virsh shutdown dom # # wait for shutdown to complete # virsh dumpxml dom | grep emory <memory>599040</memory> <currentMemory>524288</currentMemory> Thus, setmaxmem was able to affect config-only and live-only (at least in reported numbers), but not config|live, and certainly did not match the former documentation of being a live-only operation. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

This patch adds the new options (--live, --config, and --current) to "virsh setmaxmem" command. The behavior of above options is the same as that of "virsh setmem". When the --config option is specified, a modofication is effective for the persistent domain, while the --live option is specified, a modification is effective for an active domain. The --current option is specified, it affects a current domain. Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com> --- tools/virsh.c | 35 ++++++++++++++++++++++++++++++++--- tools/virsh.pod | 16 ++++++++++------ 2 files changed, 42 insertions(+), 9 deletions(-) Index: libvirt/tools/virsh.c =================================================================== --- libvirt.orig/tools/virsh.c +++ libvirt/tools/virsh.c @@ -3020,6 +3020,9 @@ static const vshCmdInfo info_setmaxmem[] static const vshCmdOptDef opts_setmaxmem[] = { {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, {"kilobytes", VSH_OT_INT, VSH_OFLAG_REQ, N_("maximum memory limit in kilobytes")}, + {"config", VSH_OT_BOOL, 0, N_("affect next boot")}, + {"live", VSH_OT_BOOL, 0, N_("affect running domain")}, + {"current", VSH_OT_BOOL, 0, N_("affect current domain")}, {NULL, 0, 0, NULL} }; @@ -3030,6 +3033,25 @@ cmdSetmaxmem(vshControl *ctl, const vshC virDomainInfo info; int kilobytes = 0; int ret = TRUE; + int config = vshCommandOptBool(cmd, "config"); + int live = vshCommandOptBool(cmd, "live"); + int current = vshCommandOptBool(cmd, "current"); + int flags = VIR_DOMAIN_MEM_MAXIMUM; + + if (current) { + if(live || config) { + vshError(ctl, "%s", _("--current must be specified exclusively")); + return FALSE; + } + } else { + if (config) + flags |= VIR_DOMAIN_MEM_CONFIG; + if (live) + flags |= VIR_DOMAIN_MEM_LIVE; + /* neither option is specified */ + if (!live && !config) + flags = -1; + } if (!vshConnectionUsability(ctl, ctl->conn)) return FALSE; @@ -3054,9 +3076,16 @@ cmdSetmaxmem(vshControl *ctl, const vshC return FALSE; } - if (virDomainSetMaxMemory(dom, kilobytes) != 0) { - vshError(ctl, "%s", _("Unable to change MaxMemorySize")); - ret = FALSE; + if (flags == -1) { + if (virDomainSetMaxMemory(dom, kilobytes) != 0) { + vshError(ctl, "%s", _("Unable to change MaxMemorySize")); + ret = FALSE; + } + } else { + if (virDomainSetMemoryFlags(dom, kilobytes, flags) < 0) { + vshError(ctl, "%s", _("Unable to change MaxMemorySize")); + ret = FALSE; + } } virDomainFree(dom); Index: libvirt/tools/virsh.pod =================================================================== --- libvirt.orig/tools/virsh.pod +++ libvirt/tools/virsh.pod @@ -601,12 +601,18 @@ rounds the parameter up unless the kB ar For Xen, you can only adjust the memory of a running domain if the domain is paravirtualized or running the PV balloon driver. -=item B<setmaxmem> I<domain-id> B<kilobytes> +=item B<setmaxmem> I<domain-id> B<kilobytes> optional I<--config> I<--live> +I<--current> -Change the maximum memory allocation limit for an inactive guest domain. +Change the maximum memory allocation limit for a guest domain. +If I<--live> is specified, affect a running guest. +If I<--config> is specified, affect the next boot of a persistent guest. +If I<--current> is specified, affect the current guest state. +Both I<--live> and I<--current> flags may be given, but I<--current> is +exclusive. If no flag is specified, behavior is different depending +on hypervisor. -This command works for at least the Xen and vSphere/ESX hypervisors, -but not for QEMU/KVM. +This command works for at least the Xen, QEMU/KVM and vSphere/ESX hypervisors. Some hypervisors require a larger granularity than kilobytes, rounding up requests that are not an even multiple of the desired amount. vSphere/ESX @@ -614,8 +620,6 @@ is one of these, requiring the parameter vSphere/ESX, 263168 (257MB) would be rounded up because it's not a multiple of 4MB, while 266240 (260MB) is valid without rounding. -Note, to change the maximum memory allocation for a QEMU/KVM guest domain, -use the virsh B<edit> command instead to update its XML <memory> element. =item B<memtune> I<domain-id> optional I<--hard-limit> B<kilobytes> optional I<--soft-limit> B<kilobytes> optional I<--swap-hard-limit>

On 04/07/2011 11:08 PM, Taku Izumi wrote:
This patch adds the new options (--live, --config, and --current) to "virsh setmaxmem" command. The behavior of above options is the same as that of "virsh setmem". When the --config option is specified, a modofication is effective for the
s/modofication/modification/
persistent domain, while the --live option is specified, a modification is effective for an active domain. The --current option is specified, it affects a current domain.
Long lines - 80 columns is nice, and for commit messages, I tend to be even more conservative at 70 columns (since git log indents the text).
+ + if (current) { + if(live || config) {
s/if(/if (/ ACK with that nit fixed, and pushed. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org
participants (4)
-
Daniel Veillard
-
Eric Blake
-
Hu Tao
-
Taku Izumi