memory: update: Update state using the memory removed.

If the memory is reduced , its cgroup in the VM was updated properly. But the
runtime assumed that the memory was also removed from the VM.

Then when it is added more memory again, more is added (but not needed).

Fixes: #801

Signed-off-by: Jose Carlos Venegas Munoz <jose.carlos.venegas.munoz@intel.com>
This commit is contained in:
Jose Carlos Venegas Munoz 2018-09-29 11:15:58 -05:00
parent 532e0bbf75
commit 4697cf3c79
2 changed files with 44 additions and 17 deletions

View File

@ -1301,9 +1301,13 @@ func (c *Container) memHotplugValid(mem uint32) (uint32, error) {
return uint32(math.Ceil(float64(mem)/float64(memorySectionSizeMB))) * memorySectionSizeMB, nil
}
func (c *Container) updateMemoryResources(oldResources, newResources ContainerResources) error {
func (c *Container) updateMemoryResources(oldResources ContainerResources, newResources *ContainerResources) error {
oldMemMB := oldResources.MemMB
newMemMB := newResources.MemMB
c.Logger().WithFields(logrus.Fields{
"old-mem": fmt.Sprintf("%dMB", oldMemMB),
"new-mem": fmt.Sprintf("%dMB", newMemMB),
}).Debug("Request update memory")
if oldMemMB == newMemMB {
c.Logger().WithFields(logrus.Fields{
@ -1325,16 +1329,37 @@ func (c *Container) updateMemoryResources(oldResources, newResources ContainerRe
addMemDevice := &memoryDevice{
sizeMB: int(memHotplugMB),
}
_, err = c.sandbox.hypervisor.hotplugAddDevice(addMemDevice, memoryDev)
data, err := c.sandbox.hypervisor.hotplugAddDevice(addMemDevice, memoryDev)
if err != nil {
return err
}
newResources.MemMB = newMemMB
memoryAdded, ok := data.(int)
if !ok {
return fmt.Errorf("Could not get the memory added, got %+v", data)
}
newResources.MemMB = oldMemMB + uint32(memoryAdded)
if err := c.sandbox.agent.onlineCPUMem(0, false); err != nil {
return err
}
}
// hot remove memory unsupported
if oldMemMB > newMemMB {
// Try to remove a memory device with the difference
// from new memory and old memory
removeMem := &memoryDevice{
sizeMB: int(oldMemMB - newMemMB),
}
data, err := c.sandbox.hypervisor.hotplugRemoveDevice(removeMem, memoryDev)
if err != nil {
return err
}
memoryRemoved, ok := data.(int)
if !ok {
return fmt.Errorf("Could not get the memory added, got %+v", data)
}
newResources.MemMB = oldMemMB - uint32(memoryRemoved)
newResources.MemMB = oldResources.MemMB
}
return nil
}
@ -1358,7 +1383,7 @@ func (c *Container) updateResources(oldResources, newResources ContainerResource
// Memory is not updated if memory limit not set
if newResources.MemMB != 0 {
if err := c.updateMemoryResources(oldResources, newResources); err != nil {
if err := c.updateMemoryResources(oldResources, &newResources); err != nil {
return err
}

View File

@ -7,7 +7,6 @@ package virtcontainers
import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
@ -913,7 +912,7 @@ func (q *qemu) hotplugDevice(devInfo interface{}, devType deviceType, op operati
return nil, q.hotplugVFIODevice(device, op)
case memoryDev:
memdev := devInfo.(*memoryDevice)
return nil, q.hotplugMemory(memdev, op)
return q.hotplugMemory(memdev, op)
case netDev:
device := devInfo.(*VirtualEndpoint)
return nil, q.hotplugNetDevice(device, op)
@ -1047,24 +1046,27 @@ func (q *qemu) hotplugRemoveCPUs(amount uint32) (uint32, error) {
return amount, q.storage.storeHypervisorState(q.id, q.state)
}
func (q *qemu) hotplugMemory(memDev *memoryDevice, op operation) error {
func (q *qemu) hotplugMemory(memDev *memoryDevice, op operation) (int, error) {
if memDev.sizeMB < 0 {
return fmt.Errorf("cannot hotplug negative size (%d) memory", memDev.sizeMB)
return 0, fmt.Errorf("cannot hotplug negative size (%d) memory", memDev.sizeMB)
}
// We do not support memory hot unplug.
if op == removeDevice {
return errors.New("cannot hot unplug memory device")
// Dont fail for now, until we fix it.
// We return that we only unplugged 0
q.Logger().Warn("hot-remove VM memory not supported")
return 0, nil
}
err := q.qmpSetup()
if err != nil {
return err
return 0, err
}
maxMem, err := q.hostMemMB()
if err != nil {
return err
return 0, err
}
// calculate current memory
@ -1072,13 +1074,13 @@ func (q *qemu) hotplugMemory(memDev *memoryDevice, op operation) error {
// Don't exceed the maximum amount of memory
if currentMemory+memDev.sizeMB > int(maxMem) {
return fmt.Errorf("Unable to hotplug %d MiB memory, the SB has %d MiB and the maximum amount is %d MiB",
return 0, fmt.Errorf("Unable to hotplug %d MiB memory, the SB has %d MiB and the maximum amount is %d MiB",
memDev.sizeMB, currentMemory, q.config.MemorySize)
}
memoryDevices, err := q.qmpMonitorCh.qmp.ExecQueryMemoryDevices(q.qmpMonitorCh.ctx)
if err != nil {
return fmt.Errorf("failed to query memory devices: %v", err)
return 0, fmt.Errorf("failed to query memory devices: %v", err)
}
if len(memoryDevices) != 0 {
@ -1088,15 +1090,15 @@ func (q *qemu) hotplugMemory(memDev *memoryDevice, op operation) error {
return q.hotplugAddMemory(memDev)
}
func (q *qemu) hotplugAddMemory(memDev *memoryDevice) error {
func (q *qemu) hotplugAddMemory(memDev *memoryDevice) (int, error) {
err := q.qmpMonitorCh.qmp.ExecHotplugMemory(q.qmpMonitorCh.ctx, "memory-backend-ram", "mem"+strconv.Itoa(memDev.slot), "", memDev.sizeMB)
if err != nil {
q.Logger().WithError(err).Error("hotplug memory")
return err
return 0, err
}
q.state.HotpluggedMemory += memDev.sizeMB
return q.storage.storeHypervisorState(q.id, q.state)
return memDev.sizeMB, q.storage.storeHypervisorState(q.id, q.state)
}
func (q *qemu) pauseSandbox() error {