On Fri, Feb 20, 2015 at 10:15:00 -0500, John Ferlan wrote:
On 02/18/2015 09:16 AM, Peter Krempa wrote:
> As there are two possible approaches to define a domain's memory size -
> one used with legacy, non-NUMA VMs configured in the <memory> element
> and per-node based approach on NUMA machines - the user needs to make
> sure that both are specified correctly in the NUMA case.
>
> To avoid this burden on the user I'd like to replace the NUMA case with
> automatic totaling of the memory size. To achieve this I need to replace
> direct access to the virDomainMemtune's 'max_balloon' field with
> two separate getters depending on the desired size.
>
> The two sizes are needed as:
> 1) Startup memory size doesn't include memory modules in some
> hypervisors.
> 2) After startup these count as the usable memory size.
>
> Note that the comments for the functions are future aware and document
> state that will be present after a few later patches.
> ---
> src/conf/domain_conf.c | 66 ++++++++++++++++++++++++++++++++++------
> src/conf/domain_conf.h | 4 +++
> src/hyperv/hyperv_driver.c | 2 +-
> src/libvirt_private.syms | 3 ++
> src/libxl/libxl_conf.c | 2 +-
> src/libxl/libxl_driver.c | 8 ++---
> src/lxc/lxc_cgroup.c | 2 +-
> src/lxc/lxc_driver.c | 10 +++---
> src/lxc/lxc_fuse.c | 4 +--
> src/lxc/lxc_native.c | 4 +--
> src/openvz/openvz_driver.c | 2 +-
> src/parallels/parallels_driver.c | 2 +-
> src/parallels/parallels_sdk.c | 12 ++++----
> src/phyp/phyp_driver.c | 11 ++++---
> src/qemu/qemu_command.c | 18 +++++++----
> src/qemu/qemu_driver.c | 19 ++++++------
> src/qemu/qemu_hotplug.c | 8 +++--
> src/qemu/qemu_process.c | 2 +-
> src/test/test_driver.c | 8 ++---
> src/uml/uml_driver.c | 8 ++---
> src/vbox/vbox_common.c | 4 +--
> src/vmware/vmware_driver.c | 2 +-
> src/vmx/vmx.c | 12 ++++----
> src/xen/xm_internal.c | 14 ++++-----
> src/xenapi/xenapi_driver.c | 2 +-
> src/xenapi/xenapi_utils.c | 4 +--
> src/xenconfig/xen_common.c | 8 +++--
> src/xenconfig/xen_sxpr.c | 9 +++---
> 28 files changed, 160 insertions(+), 90 deletions(-)
>
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 6ef499d..e95851a 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -3172,24 +3172,26 @@ virDomainDefPostParseInternal(virDomainDefPtr def,
> return -1;
> }
>
> - if (def->mem.cur_balloon > def->mem.max_balloon) {
> + if (def->mem.cur_balloon > virDomainDefGetMemoryCurrent(def)) {
> /* Older libvirt could get into this situation due to
> * rounding; if the discrepancy is less than 4MiB, we silently
> * round down, otherwise we flag the issue. */
> if (VIR_DIV_UP(def->mem.cur_balloon, 4096) >
> - VIR_DIV_UP(def->mem.max_balloon, 4096)) {
> + VIR_DIV_UP(virDomainDefGetMemoryCurrent(def), 4096)) {
> virReportError(VIR_ERR_XML_ERROR,
> _("current memory '%lluk' exceeds "
> "maximum '%lluk'"),
> - def->mem.cur_balloon, def->mem.max_balloon);
> + def->mem.cur_balloon,
> + virDomainDefGetMemoryCurrent(def));
> return -1;
> } else {
> VIR_DEBUG("Truncating current %lluk to maximum %lluk",
> - def->mem.cur_balloon, def->mem.max_balloon);
> - def->mem.cur_balloon = def->mem.max_balloon;
> + def->mem.cur_balloon,
> + virDomainDefGetMemoryCurrent(def));
> + def->mem.cur_balloon = virDomainDefGetMemoryCurrent(def);
> }
> } else if (def->mem.cur_balloon == 0) {
> - def->mem.cur_balloon = def->mem.max_balloon;
> + def->mem.cur_balloon = virDomainDefGetMemoryCurrent(def);
> }
>
> /*
> @@ -6882,6 +6884,51 @@ virDomainParseMemory(const char *xpath,
> }
>
>
> +/**
> + * virDomainDefGetMemoryInitial:
> + * @def: domain definition
> + *
> + * Returns the size of the initial amount of guest memory. The initial amount
> + * is the memory size is either the configured amount in the <memory>
element
> + * or the sum of memory sizes of NUMA nodes in case NUMA is enabled in @def.
> + */
> +unsigned long long
> +virDomainDefGetMemoryInitial(virDomainDefPtr def)
> +{
> + return def->mem.max_balloon;
> +}
> +
> +
> +/**
> + * virDomainDefSetMemoryInitial:
> + * @def: domain definition
> + * @size: size to set
> + *
> + * Sets the initial memory size in @def.
> + */
> +void
> +virDomainDefSetMemoryInitial(virDomainDefPtr def,
> + unsigned long long size)
> +{
> + def->mem.max_balloon = size;
> +}
Odd concept - changing Initial memory, but I don't have a better name in
mind...
> +
> +
> +/**
> + * virDomainDefGetMemoryCurrent:
> + * @def: domain definition
> + *
> + * Returns the current maximum memory size usable by the domain described by
> + * @def. This size is a sum of size returned by virDomainDefGetMemoryInitial
> + * and possible additional memory devices.
> + */
> +unsigned long long
> +virDomainDefGetMemoryCurrent(virDomainDefPtr def)
> +{
> + return virDomainDefGetMemoryInitial(def);
> +}
Ok - so part of me expect this one to return mem.cur_balloon - perhaps a
name change to GetMemoryUsable would help?
I'll try using GetMemoryAvailable for the next version.
and of course begs the question why not bite the bullet and return
mem.cur_balloon in a GetMemoryCurrent accessor...
I didn't need it currently. I'll look into it separately if I find it
necessary.
> +
> +
> static int
> virDomainControllerModelTypeFromString(const virDomainControllerDef *def,
> const char *model)
> @@ -15956,10 +16003,11 @@ virDomainDefCheckABIStability(virDomainDefPtr src,
> goto error;
> }
>
> - if (src->mem.max_balloon != dst->mem.max_balloon) {
> + if (virDomainDefGetMemoryInitial(src) != virDomainDefGetMemoryInitial(dst)) {
> virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> _("Target domain max memory %lld does not match source
%lld"),
> - dst->mem.max_balloon, src->mem.max_balloon);
> + virDomainDefGetMemoryInitial(dst),
> + virDomainDefGetMemoryInitial(src));
> goto error;
> }
Since the "future" (I assume) is that MemoryCurrent will include the hot
(un)plug memory - does it make sense to also compare src/dst
MemoryCurrent values even though for now it's essentially the same
value? Although I believe that gets done in your later series and it's
hard to keep them in my memory.
The memory modules will be compared individually so it doesn't matter
much.
Of the remaining uses of GetInitial and {Get|Set}Current the ones I was
wondering about are:
virLXCCgroupSetupMemTune
libxlMakeDomBuildInfo
phypBuildLpar
Wouldn't they be the corollary to qemuBuildCommandLine w/r/t using
Initial instead of Current in order to define the memory for the guest
as it starts up?
They are. I'll change them to use the Current/Available accessor
although it won't make a difference for now as memory hotplug is
explicitly forbidden for drivers other than qemu.
John
Peter