[libvirt] [PATCHv2.5 08/10] qemu: conf: Add support for memory device cold(un)plug
John Ferlan
jferlan at redhat.com
Fri Mar 13 14:39:05 UTC 2015
On 03/04/2015 11:24 AM, Peter Krempa wrote:
> Add a few helpers that allow to operate with memory device definitions
> on the domain config and use them to implement memory device coldplug in
> the qemu driver.
> ---
> src/conf/domain_conf.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++
> src/conf/domain_conf.h | 10 +++++
> src/libvirt_private.syms | 4 ++
> src/qemu/qemu_driver.c | 15 ++++++-
> 4 files changed, 127 insertions(+), 2 deletions(-)
>
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 4f20aa6..0f6058b 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -12687,6 +12687,106 @@ virDomainRNGRemove(virDomainDefPtr def,
> }
>
>
> +static int
> +virDomainMemoryFindByDefInternal(virDomainDefPtr def,
> + virDomainMemoryDefPtr mem,
> + bool allowAddressFallback)
> +{
> + size_t i;
> +
> + for (i = 0; i < def->nmems; i++) {
> + virDomainMemoryDefPtr tmp = def->mems[i];
> +
> + /* address, if present */
> + if (allowAddressFallback) {
> + if (tmp->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
> + continue;
So this path says - we want address fallback and this device has either
DIMM or LAST (oy!) as a type, so go to the next one and ignore this one
> + } else {
> + if (mem->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
> + !virDomainDeviceInfoAddressIsEqual(&tmp->info, &mem->info))
> + continue;
This path says - we don't want address fallback and as long as we're
DIMM or LAST (oy!), then compare
What happens when we add a new address type? It would seem the more
straightforward way would be
if (type == DIMM && !Equal)
if (!allowAddressFallback)
continue'
Otherwise we're falling through to alias, target, etc. checks
> + }
> +
> + /* alias, if present */
> + if (mem->info.alias &&
> + STRNEQ_NULLABLE(tmp->info.alias, mem->info.alias))
> + continue;
I thought the NULLABLE checks both elems for NULL...
> +
> + /* target info -> always present */
> + if (tmp->model != mem->model ||
> + tmp->targetNode != mem->targetNode ||
> + tmp->size != mem->size)
> + continue;
> +
> + /* source stuff -> match with device */
> + if (tmp->pagesize != mem->pagesize)
> + continue;
> +
> + if (!virBitmapEqual(tmp->sourceNodes, mem->sourceNodes))
> + continue;
> +
> + break;
> + }
> +
> + if (i == def->nmems)
> + return -1;
> +
> + return i;
> +}
> +
> +
> +int
> +virDomainMemoryFindByDef(virDomainDefPtr def,
> + virDomainMemoryDefPtr mem)
> +{
> + return virDomainMemoryFindByDefInternal(def, mem, false);
> +}
> +
> +
> +int
> +virDomainMemoryFindInactiveByDef(virDomainDefPtr def,
> + virDomainMemoryDefPtr mem)
> +{
> + int ret;
> +
> + if ((ret = virDomainMemoryFindByDefInternal(def, mem, false)) < 0)
> + ret = virDomainMemoryFindByDefInternal(def, mem, true);
I would seem Inactive would probably not have the dimm address set, so
we're incurring a 2X penalty for perhaps no reason... Unless perhaps the
incoming mem def being checked has an address...
That is if my incoming has an address, then don't allow fallback;
otherwise, well best match.
> +
> + return ret;
> +}
> +
> +
> +int
> +virDomainMemoryInsert(virDomainDefPtr def,
> + virDomainMemoryDefPtr mem)
> +{
> + int id = def->nmems;
> +
> + if (mem->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
> + virDomainDefHasDeviceAddress(def, &mem->info)) {
Hmm... so if our incoming mem has an address defined - it could be
anything - we're just failing declaring that the domain already contains
a device with the same address? Doesn't seem right.
And again - we have this problem of TYPE_NONE, TYPE_DIMM, TYPE_LAST and
who knows what in the future.
> + virReportError(VIR_ERR_OPERATION_INVALID, "%s",
> + _("Domain already contains a device with the same "
> + "address"));
> + return -1;
> + }
> +
> + if (VIR_APPEND_ELEMENT(def->mems, def->nmems, mem) < 0)
> + return -1;
> +
> + return id;
> +}
> +
> +
> +virDomainMemoryDefPtr
> +virDomainMemoryRemove(virDomainDefPtr def,
> + int idx)
> +{
> + virDomainMemoryDefPtr ret = def->mems[idx];
> + VIR_DELETE_ELEMENT(def->mems, idx, def->nmems);
> + return ret;
> +}
> +
> +
> char *
> virDomainDefGetDefaultEmulator(virDomainDefPtr def,
> virCapsPtr caps)
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index 706040d..c38614d 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -2853,6 +2853,16 @@ virDomainChrDefGetSecurityLabelDef(virDomainChrDefPtr def, const char *model);
> typedef const char* (*virEventActionToStringFunc)(int type);
> typedef int (*virEventActionFromStringFunc)(const char *type);
>
> +int virDomainMemoryInsert(virDomainDefPtr def, virDomainMemoryDefPtr mem)
> + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
> +virDomainMemoryDefPtr virDomainMemoryRemove(virDomainDefPtr def, int idx)
> + ATTRIBUTE_NONNULL(1);
> +int virDomainMemoryFindByDef(virDomainDefPtr def, virDomainMemoryDefPtr mem)
> + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
> +int virDomainMemoryFindInactiveByDef(virDomainDefPtr def,
> + virDomainMemoryDefPtr mem)
> + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
> +
> VIR_ENUM_DECL(virDomainTaint)
> VIR_ENUM_DECL(virDomainVirt)
> VIR_ENUM_DECL(virDomainBoot)
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 2491d2d..1504c9a 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -334,6 +334,10 @@ virDomainLockFailureTypeToString;
> virDomainMemballoonModelTypeFromString;
> virDomainMemballoonModelTypeToString;
> virDomainMemoryDefFree;
> +virDomainMemoryFindByDef;
> +virDomainMemoryFindInactiveByDef;
> +virDomainMemoryInsert;
> +virDomainMemoryRemove;
> virDomainNetAppendIpAddress;
> virDomainNetDefFormat;
> virDomainNetDefFree;
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index d6935d9..6b10e96 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -7438,7 +7438,10 @@ qemuDomainAttachDeviceConfig(virQEMUCapsPtr qemuCaps,
> break;
>
> case VIR_DOMAIN_DEVICE_MEMORY:
> - /* TODO: implement later */
> + if (virDomainMemoryInsert(vmdef, dev->data.memory) < 0)
> + return -1;
> + dev->data.memory = NULL;
> + break;
>
> case VIR_DOMAIN_DEVICE_INPUT:
> case VIR_DOMAIN_DEVICE_SOUND:
> @@ -7566,7 +7569,15 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
> break;
>
> case VIR_DOMAIN_DEVICE_MEMORY:
> - /* TODO: implement later */
> + if ((idx = virDomainMemoryFindInactiveByDef(vmdef,
> + dev->data.memory)) < 0) {
> + virReportError(VIR_ERR_OPERATION_FAILED, "%s",
> + _("matching memory device was not found"));
> + return -1;
> + }
> +
> + virDomainMemoryDefFree(virDomainMemoryRemove(vmdef, idx));
Ug - tricked my eyes on calling the Remove inside the DefFree
ACK with some cleanups which I think are more or less simple
John
I have to run - I will finish 9 & 10 a bit later.
> + break;
>
> case VIR_DOMAIN_DEVICE_INPUT:
> case VIR_DOMAIN_DEVICE_SOUND:
>
More information about the libvir-list
mailing list