[PATCH 08/10] qemu: Recalculate balloon on MEMORY_DEVICE_SIZE_CHANGE event and reconnect

Michal Privoznik mprivozn at redhat.com
Wed Feb 3 16:27:10 UTC 2021


On 2/2/21 2:32 PM, Peter Krempa wrote:
> On Fri, Jan 22, 2021 at 13:50:30 +0100, Michal Privoznik wrote:
>> Just like we are recalculating the amount of guest memory on
>> BALLOON_CHANGE and on reconnect to the monitor, we should include
>> the actual size of virtio-mem too.
>>
>> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
>> ---
>>   src/qemu/qemu_driver.c  |  3 +++
>>   src/qemu/qemu_process.c | 57 +++++++++++++++++++++++++++++++++--------
>>   2 files changed, 50 insertions(+), 10 deletions(-)
>>
>> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
>> index d64eb4d399..2fd4429ba8 100644
>> --- a/src/qemu/qemu_driver.c
>> +++ b/src/qemu/qemu_driver.c
>> @@ -4298,6 +4298,9 @@ processMemoryDeviceSizeChange(virQEMUDriverPtr driver,
>>       mem = vm->def->mems[idx];
>>       mem->actualsize = VIR_DIV_UP(info->size, 1024);
>>   
>> +    /* fix the balloon size */
>> +    ignore_value(qemuProcessRefreshBalloonState(driver, vm, QEMU_ASYNC_JOB_NONE));
> 
> During VM lifetime, qemu is actively notifying us about balloon changes
> via an event, so explicit refresh is wrong here.
> 
> You probably want to do the calculation here depending on the old and
> new value instead.
> 
>> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
>> index 8d41f947af..01d261d538 100644
>> --- a/src/qemu/qemu_process.c
>> +++ b/src/qemu/qemu_process.c
>> @@ -1250,10 +1250,31 @@ 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_MEM:
>> +            actual += mem->actualsize;
>> +            break;
> 
> So this means that the balloon driver never counts the memory provided
> by any virtio-mem device? If that is so then this is okay, but in that
> case it would be worth explaining it here.
> 

No, balloon does not report virtio-mem memory.

> If it's not the case it's wrong to add the size of the additional
> devices here since you'd count them twice.
> 
> [...]
> 
>> @@ -2451,21 +2472,37 @@ 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);
> 
> So the following code is wrong at least in case when this branch is
> taken:
> 
> virDomainDefGetMemoryTotal:
> 
>   * Returns the current maximum memory size usable by the domain described by
>   * @def. This size includes possible additional memory devices.
> 
> The total_memory size is updated in virDomainDefPostParseMemory by
> adding up sizes of all 'mem' devices ...
> 
> 
>>       }
>>   
>> -    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_MEM:
>> +            balloon += mem->actualsize;
>> +            break;
> 
> ... and you then add the 'actualsize' component which is a fraction of
> the 'size' of a mem counted previously here.
> 
> Thus when reconnecting to a VM which doesn't have ballon, but uses
> virtio-mem, the virtio-mem is counted twice. (This doesn't happen on
> refresh when starting a new VM since no guest code executed yet)
> 

I've spent some time thinking about this patch. Do we really need it? I 
mean, if we did fake balloon size how do users learn the actual size of 
the balloon? On one hand I understand that <currentMemory/> (= 
def->mem.cur_balloon) should reflect the actual size that guest sees 
(balloon + actual size of virtio mem), but on the other - as Jing showed 
there might be quite a few places where we might report just balloon 
size (virsh dommemstat).

Somehow it suddenly feels wrong to mangle with reported balloon size.

Michal




More information about the libvir-list mailing list