[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [libvirt] [PATCH v5 5/5] hyperv: Add support for virDomainSetMemory



2017-06-12 22:13 GMT+02:00 Sri Ramanujam <sramanujam datto com>:
> Introduces support for virDomainSetMemory. This also serves an an
> example for how to use the new method invocation API with a more
> complicated method, this time including an EPR and embedded param.
> ---
>  src/hyperv/hyperv_driver.c            | 105 ++++++++++++++++++++++++++++++++++
>  src/hyperv/hyperv_wmi.c               |  51 +++++++++++++++++
>  src/hyperv/hyperv_wmi.h               |  11 ++++
>  src/hyperv/hyperv_wmi_generator.input |  30 ++++++++++
>  4 files changed, 197 insertions(+)
>
> diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
> index 3f5b94e..f557408 100644
> --- a/src/hyperv/hyperv_driver.c
> +++ b/src/hyperv/hyperv_driver.c
> @@ -1497,6 +1497,109 @@ hypervDomainSendKey(virDomainPtr domain, unsigned int codeset,
>  }
>
>
> +static int
> +hypervDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory,
> +        unsigned int flags)
> +{
> +    int result = -1;
> +    char uuid_string[VIR_UUID_STRING_BUFLEN];
> +    hypervPrivate *priv = domain->conn->privateData;
> +    char *memory_str = NULL;
> +    hypervInvokeParamsListPtr params = NULL;
> +    unsigned long memory_mb = VIR_ROUND_UP(VIR_DIV_UP(memory, 1024), 2);
> +    Msvm_VirtualSystemSettingData *vssd = NULL;
> +    Msvm_MemorySettingData *memsd = NULL;
> +    virBuffer eprQuery = VIR_BUFFER_INITIALIZER;
> +    virHashTablePtr memResource = NULL;
> +
> +    virCheckFlags(0, -1);
> +
> +    if (virAsprintf(&memory_str, "%lu", memory_mb) < 0)
> +        goto cleanup;
> +
> +    virUUIDFormat(domain->uuid, uuid_string);
> +
> +    if (hypervGetMsvmVirtualSystemSettingDataFromUUID(priv, uuid_string, &vssd) < 0)
> +        goto cleanup;
> +
> +    if (hypervGetMsvmMemorySettingDataFromVSSD(priv, vssd->data.common->InstanceID,
> +                &memsd) < 0)
> +        goto cleanup;
> +
> +    if (priv->wmiVersion == HYPERV_WMI_VERSION_V1) {
> +        params = hypervCreateInvokeParamsList(priv, "ModifyVirtualSystemResources",
> +                MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_SELECTOR,
> +                Msvm_VirtualSystemManagementService_WmiInfo);
> +
> +        if (!params) {
> +            virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create params"));
> +            goto cleanup;
> +        }
> +
> +        virBufferAddLit(&eprQuery, MSVM_COMPUTERSYSTEM_WQL_SELECT);
> +        virBufferAsprintf(&eprQuery, "where Name = \"%s\"", uuid_string);
> +
> +        if (hypervAddEprParam(params, "ComputerSystem", priv, &eprQuery,
> +                    Msvm_ComputerSystem_WmiInfo) < 0)
> +            goto cleanup;
> +    } else if (priv->wmiVersion == HYPERV_WMI_VERSION_V2) {
> +        params = hypervCreateInvokeParamsList(priv, "ModifyResourceSettings",
> +                MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_SELECTOR,
> +                Msvm_VirtualSystemManagementService_WmiInfo);
> +
> +        if (!params) {
> +            virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create params"));
> +            goto cleanup;
> +        }
> +    }
> +
> +    memResource = hypervCreateEmbeddedParam(priv, Msvm_MemorySettingData_WmiInfo);
> +    if (!memResource)
> +        goto cleanup;
> +
> +    if (hypervSetEmbeddedProperty(memResource, "VirtualQuantity", memory_str) < 0)
> +        goto cleanup;
> +
> +    if (hypervSetEmbeddedProperty(memResource, "InstanceID",
> +                memsd->data.common->InstanceID) < 0)
> +        goto cleanup;
> +
> +    if (priv->wmiVersion == HYPERV_WMI_VERSION_V1) {
> +        if (hypervAddEmbeddedParam(params, priv, "ResourceSettingData",
> +                    memResource, Msvm_MemorySettingData_WmiInfo) < 0)
> +            goto cleanup;
> +
> +    } else if (priv->wmiVersion == HYPERV_WMI_VERSION_V2) {
> +        if (hypervAddEmbeddedParam(params, priv, "ResourceSettings",
> +                    memResource, Msvm_MemorySettingData_WmiInfo) < 0)
> +            goto cleanup;
> +    }
> +

memResource has to be set to NULL here, as I explained in my previous
mail. hypervInvokeMethod will always free memResource. Therefore,
hypervInvokeMethod will free memResource even if it fails and the code
below go to cleanup, with memResource != NULL. Then memResource will
be freed again, resulting in a double-free. That's why memResource
needs to be set to NULL before calling hypervInvokeMethod, not
afterwards.

> +    if (hypervInvokeMethod(priv, params, NULL) < 0) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not set memory"));
> +        goto cleanup;
> +    }
> +
> +    /* set embedded param to NULL on success to avoid double-free in cleanup */
> +    memResource = NULL;

Setting memResource to NULL here is too late.

> +
> +    result = 0;
> + cleanup:
> +    VIR_FREE(memory_str);
> +    hypervFreeEmbeddedParam(memResource);
> +    hypervFreeObject(priv, (hypervObject *) vssd);
> +    hypervFreeObject(priv, (hypervObject *) memsd);
> +    return result;
> +}


-- 
Matthias Bolte
http://photron.blogspot.com


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]