On Thu, Dec 03, 2020 at 13:36:26 +0100, Michal Privoznik wrote:
As advertised in previous commit, this event is delivered to us
when virtio-mem module changes the allocation inside the guest.
It comes with one attribute - size - which holds the new size of
the virtio-mem (well, allocated size), in bytes.
Mind you, this is not necessarily the same number as 'requested
size'. It almost certainly will be when sizing the memory up, but
it might not be when sizing the memory down - the guest kernel
might be unable to free some blocks.
This actual size is reported in the domain XML as an output
element only.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
docs/formatdomain.rst | 7 +++
docs/schemas/domaincommon.rng | 5 ++
src/conf/domain_conf.c | 24 ++++++++-
src/conf/domain_conf.h | 7 +++
src/libvirt_private.syms | 1 +
src/qemu/qemu_domain.c | 3 ++
src/qemu/qemu_domain.h | 1 +
src/qemu/qemu_driver.c | 36 +++++++++++++
src/qemu/qemu_monitor.c | 24 +++++++++
src/qemu/qemu_monitor.h | 20 ++++++++
src/qemu/qemu_monitor_json.c | 24 +++++++++
src/qemu/qemu_process.c | 96 +++++++++++++++++++++++++++++++----
12 files changed, 236 insertions(+), 12 deletions(-)
[...]
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 8ea7e0df05..1fba9d8302 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1248,10 +1248,30 @@ qemuProcessHandleBalloonChange(qemuMonitorPtr mon G_GNUC_UNUSED,
virQEMUDriverPtr driver = opaque;
virObjectEventPtr event = NULL;
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
+ size_t i;
virObjectLock(vm);
event = virDomainEventBalloonChangeNewFromObj(vm, actual);
+ VIR_DEBUG("New balloon size before fixup: %lld", actual);
+
+ for (i = 0; i < vm->def->nmems; i++) {
+ virDomainMemoryDefPtr mem = vm->def->mems[i];
+
+ switch (mem->model) {
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO:
+ actual += mem->actualsize;
+ break;
+
+ case VIR_DOMAIN_MEMORY_MODEL_NONE:
+ case VIR_DOMAIN_MEMORY_MODEL_DIMM:
+ case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
+ case VIR_DOMAIN_MEMORY_MODEL_LAST:
+ /* nada */
+ break;
+ }
+ }
+
VIR_DEBUG("Updating balloon from %lld to %lld kb",
vm->def->mem.cur_balloon, actual);
vm->def->mem.cur_balloon = actual;
@@ -2405,21 +2466,36 @@
qemuProcessRefreshBalloonState(virQEMUDriverPtr driver,
int asyncJob)
{
unsigned long long balloon;
+ size_t i;
int rc;
- /* if no ballooning is available, the current size equals to the current
- * full memory size */
- if (!virDomainDefHasMemballoon(vm->def)) {
- vm->def->mem.cur_balloon = virDomainDefGetMemoryTotal(vm->def);
- return 0;
+ if (virDomainDefHasMemballoon(vm->def)) {
+ if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+ return -1;
+
+ rc = qemuMonitorGetBalloonInfo(qemuDomainGetMonitor(vm), &balloon);
+ if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
+ return -1;
+ } else {
+ balloon = virDomainDefGetMemoryTotal(vm->def);
}
- if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
- return -1;
+ for (i = 0; i < vm->def->nmems; i++) {
+ virDomainMemoryDefPtr mem = vm->def->mems[i];
+
+ switch (mem->model) {
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO:
+ balloon += mem->actualsize;
+ break;
- rc = qemuMonitorGetBalloonInfo(qemuDomainGetMonitor(vm), &balloon);
- if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
- return -1;
+ case VIR_DOMAIN_MEMORY_MODEL_NONE:
+ case VIR_DOMAIN_MEMORY_MODEL_DIMM:
+ case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
+ case VIR_DOMAIN_MEMORY_MODEL_LAST:
+ /* nada */
+ break;
+ }
+ }
vm->def->mem.cur_balloon = balloon;
I don't think we should count the size of virtio-pmem, virtio-mem
against the total VM memory size. The mechanism this is provided to the
VM is different compared to "traditional" dimms. The OS needs driver to
access the memory.
The open question is whether we should add a similar event to what we
have for memballoon change. For now I'd probably not do it since a guest
OS restart (driver unload) can't actually result in more memory consumed
than before.