[libvirt] [RFC PATCH 05/12] conf: Add interface to parse and format memory device information

John Ferlan jferlan at redhat.com
Wed Feb 4 22:09:20 UTC 2015



On 01/30/2015 08:21 AM, Peter Krempa wrote:
> WIP: TODO: docs
> 
> Also forbid the new device in post parse callback in all driver that
> implement the callback to warn users right away that the device is not
> supported with their hypervisor.
> ---
>  docs/schemas/domaincommon.rng                      |  50 ++++
>  src/bhyve/bhyve_domain.c                           |   5 +-
>  src/conf/domain_conf.c                             | 317 ++++++++++++++++++++-
>  src/conf/domain_conf.h                             |  33 +++
>  src/libvirt_private.syms                           |   2 +
>  src/libxl/libxl_domain.c                           |   3 +
>  src/lxc/lxc_domain.c                               |   4 +
>  src/openvz/openvz_driver.c                         |   3 +
>  src/qemu/qemu_domain.c                             |   3 +
>  src/qemu/qemu_driver.c                             |  13 +
>  src/qemu/qemu_hotplug.c                            |   3 +
>  src/uml/uml_driver.c                               |   3 +
>  src/xen/xen_driver.c                               |   3 +
>  src/xenapi/xenapi_driver.c                         |   3 +
>  .../qemuxml2argv-memory-hotplug-dimm.xml           |  47 +++
>  15 files changed, 490 insertions(+), 2 deletions(-)
>  create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-memory-hotplug-dimm.xml
> 

<...snip...>

> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 0b9fb06..298b574 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -236,7 +236,8 @@ VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST,
>                "rng",
>                "shmem",
>                "tpm",
> -              "panic")
> +              "panic",
> +              "memory")
> 
>  VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
>                "none",
> @@ -779,6 +780,12 @@ VIR_ENUM_DECL(virDomainBlockJob)
>  VIR_ENUM_IMPL(virDomainBlockJob, VIR_DOMAIN_BLOCK_JOB_TYPE_LAST,
>                "", "", "copy", "", "active-commit")
> 
> +VIR_ENUM_IMPL(virDomainMemoryModel, VIR_DOMAIN_MEMORY_MODEL_LAST,
> +              "", "acpi-dimm")
> +
> +#define VIR_DOMAIN_XML_WRITE_FLAGS  VIR_DOMAIN_XML_SECURE
> +#define VIR_DOMAIN_XML_READ_FLAGS   VIR_DOMAIN_XML_INACTIVE
> +
>  static virClassPtr virDomainObjClass;
>  static virClassPtr virDomainObjListClass;
>  static virClassPtr virDomainXMLOptionClass;
> @@ -1003,6 +1010,27 @@ virDomainDefCheckUnsupportedMemoryHotplug(virDomainDefPtr def)
>  }
> 
> 
> +/**
> + * virDomainDeviceDefCheckUnsupportedMemoryDevice:
> + * @dev: device definition
> + *
> + * Returns -1 if the device definition describes a memory device and reports an
> + * error. Otherwise returns 0.
> + */
> +int
> +virDomainDeviceDefCheckUnsupportedMemoryDevice(virDomainDeviceDefPtr dev)
> +{
> +    /* This driver doesn't yet know how to handle memory devices */
> +    if (dev->type == VIR_DOMAIN_DEVICE_MEMORY) {
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                       _("memory devices are not supported by this driver"));
> +        return -1;
> +    }
> +
> +    return 0;
> +}
> +
> +
>  static void
>  virDomainObjListDataFree(void *payload, const void *name ATTRIBUTE_UNUSED)
>  {
> @@ -1934,6 +1962,15 @@ void virDomainRedirFilterDefFree(virDomainRedirFilterDefPtr def)
>      VIR_FREE(def);
>  }
> 
> +void virDomainMemoryDefFree(virDomainMemoryDefPtr def)
> +{
> +    if (!def)
> +        return;
> +
> +    virDomainDeviceInfoClear(&def->info);
> +    VIR_FREE(def);
> +}
> +
>  void virDomainDeviceDefFree(virDomainDeviceDefPtr def)
>  {
>      if (!def)
> @@ -2003,6 +2040,9 @@ void virDomainDeviceDefFree(virDomainDeviceDefPtr def)
>      case VIR_DOMAIN_DEVICE_PANIC:
>          virDomainPanicDefFree(def->data.panic);
>          break;
> +    case VIR_DOMAIN_DEVICE_MEMORY:
> +        virDomainMemoryDefFree(def->data.memory);
> +        break;
>      case VIR_DOMAIN_DEVICE_LAST:
>      case VIR_DOMAIN_DEVICE_NONE:
>          break;
> @@ -2200,6 +2240,10 @@ void virDomainDefFree(virDomainDefPtr def)
>          virDomainRNGDefFree(def->rngs[i]);
>      VIR_FREE(def->rngs);
> 
> +    for (i = 0; i < def->nmems; i++)
> +        virDomainMemoryDefFree(def->mems[i]);
> +    VIR_FREE(def->mems);
> +
>      virDomainTPMDefFree(def->tpm);
> 
>      virDomainPanicDefFree(def->panic);
> @@ -2709,6 +2753,8 @@ virDomainDeviceGetInfo(virDomainDeviceDefPtr device)
>          return &device->data.tpm->info;
>      case VIR_DOMAIN_DEVICE_PANIC:
>          return &device->data.panic->info;
> +    case VIR_DOMAIN_DEVICE_MEMORY:
> +        return &device->data.memory->info;
> 
>      /* The following devices do not contain virDomainDeviceInfo */
>      case VIR_DOMAIN_DEVICE_LEASE:
> @@ -2940,6 +2986,13 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def,
>              return -1;
>      }
> 
> +    device.type = VIR_DOMAIN_DEVICE_MEMORY;
> +    for (i = 0; i < def->nmems; i++) {
> +        device.data.memory = def->mems[i];
> +        if (cb(def, &device, &def->mems[i]->info, opaque) < 0)
> +            return -1;
> +    }
> +
>      /* Coverity is not very happy with this - all dead_error_condition */
>  #if !STATIC_ANALYSIS
>      /* This switch statement is here to trigger compiler warning when adding
> @@ -2972,6 +3025,7 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def,
>      case VIR_DOMAIN_DEVICE_PANIC:
>      case VIR_DOMAIN_DEVICE_LAST:
>      case VIR_DOMAIN_DEVICE_RNG:
> +    case VIR_DOMAIN_DEVICE_MEMORY:
>          break;
>      }
>  #endif
> @@ -11109,6 +11163,119 @@ virDomainPMStateParseXML(xmlXPathContextPtr ctxt,
>      return ret;
>  }
> 
> +
> +static int
> +virDomainMemorySourceDefParseXML(xmlNodePtr node,
> +                                 xmlXPathContextPtr ctxt,
> +                                 virDomainMemoryDefPtr def)
> +{
> +    int ret = -1;
> +    char *nodemask = NULL;
> +    xmlNodePtr save = ctxt->node;
> +    ctxt->node = node;
> +
> +    if (virDomainParseMemory("./pagesize", "./pagesize/@unit", ctxt,
> +                             &def->pagesize, false, false) < 0)
> +        goto cleanup;
> +
> +    if ((nodemask = virXPathString("string(./nodemask)", ctxt))) {
> +        if (virBitmapParse(nodemask, 0, &def->sourceNodes,
> +                           VIR_DOMAIN_CPUMASK_LEN) < 0)
> +            goto cleanup;
> +    }
> +
> +    ret = 0;
> +
> + cleanup:
> +    VIR_FREE(nodemask);
> +    ctxt->node = save;
> +    return ret;
> +}
> +
> +
> +static int
> +virDomainMemoryTargetDefParseXML(xmlNodePtr node,
> +                                 xmlXPathContextPtr ctxt,
> +                                 virDomainMemoryDefPtr def)
> +{
> +    int ret = -1;
> +    xmlNodePtr save = ctxt->node;
> +    ctxt->node = node;
> +
> +    if (virXPathInt("string(./node)", ctxt, &def->targetNode) < 0) {
> +        virReportError(VIR_ERR_XML_ERROR, "%s",
> +                       _("invalid or missing value of memory device node"));
> +        goto cleanup;
> +    }
> +
> +    if (virDomainParseMemory("./size", "./size/@unit", ctxt,
> +                             &def->size, true, false) < 0)
> +        goto cleanup;
> +
> +    ret = 0;
> +
> + cleanup:
> +    ctxt->node = save;
> +    return ret;
> +}
> +
> +
> +static virDomainMemoryDefPtr
> +virDomainMemoryDefParseXML(xmlNodePtr memdevNode,
> +                           xmlXPathContextPtr ctxt,
> +                           unsigned int flags)
> +{
> +    char *tmp = NULL;
> +    xmlNodePtr save = ctxt->node;
> +    xmlNodePtr node;
> +    virDomainMemoryDefPtr def;
> +
> +    ctxt->node = memdevNode;
> +
> +    if (VIR_ALLOC(def) < 0)
> +        return NULL;
> +
> +    if (!(tmp = virXMLPropString(memdevNode, "model"))) {
> +        virReportError(VIR_ERR_XML_ERROR, "%s",
> +                       _("missing memory model"));
> +        goto error;
> +    }
> +
> +    if ((def->model = virDomainMemoryModelTypeFromString(tmp)) < 0) {
> +        virReportError(VIR_ERR_XML_ERROR,
> +                       _("invalid memory model '%s'"), tmp);
> +        goto error;
> +    }
> +    VIR_FREE(tmp);
> +
> +    /* source */
> +    if ((node = virXPathNode("./source", ctxt)) &&
> +        virDomainMemorySourceDefParseXML(node, ctxt, def) < 0)
> +        goto error;
> +
> +    /* target */
> +    if (!(node = virXPathNode("./target", ctxt))) {
> +        virReportError(VIR_ERR_XML_ERROR, "%s",
> +                       _("missing <target> element for <memory> device"));
> +        goto error;
> +    }
> +
> +    if (virDomainMemoryTargetDefParseXML(node, ctxt, def) < 0)
> +        goto error;
> +
> +    if (virDomainDeviceInfoParseXML(memdevNode, NULL, &def->info, flags) < 0)
> +        goto error;
> +
> +    return def;
> +
> + error:
> +    VIR_FREE(tmp);
> +    virDomainMemoryDefFree(def);
> +    ctxt->node = save;
> +    return NULL;
> +}
> +
> +
>  virDomainDeviceDefPtr
>  virDomainDeviceDefParse(const char *xmlStr,
>                          const virDomainDef *def,
> @@ -11243,6 +11410,10 @@ virDomainDeviceDefParse(const char *xmlStr,
>          if (!(dev->data.panic = virDomainPanicDefParseXML(node)))
>              goto error;
>          break;
> +    case VIR_DOMAIN_DEVICE_MEMORY:
> +        if (!(dev->data.memory = virDomainMemoryDefParseXML(node, ctxt, flags)))
> +            goto error;
> +        break;
>      case VIR_DOMAIN_DEVICE_NONE:
>      case VIR_DOMAIN_DEVICE_LAST:
>          break;
> @@ -14438,6 +14609,23 @@ virDomainDefParseXML(xmlDocPtr xml,
>      ctxt->node = node;
>      VIR_FREE(nodes);
> 
> +    /* analysis of memory devices */
> +    if ((n = virXPathNodeSet("./devices/memory", ctxt, &nodes)) < 0)
> +        goto error;
> +    if (n && VIR_ALLOC_N(def->mems, n) < 0)
> +        goto error;
> +
> +    for (i = 0; i < n; i++) {
> +        virDomainMemoryDefPtr mem = virDomainMemoryDefParseXML(nodes[i],
> +                                                               ctxt,
> +                                                               flags);
> +        if (!mem)
> +            goto error;
> +
> +        def->mems[def->nmems++] = mem;
> +    }
> +    VIR_FREE(nodes);
> +
>      /* analysis of the user namespace mapping */
>      if ((n = virXPathNodeSet("./idmap/uid", ctxt, &nodes)) < 0)
>          goto error;
> @@ -15677,6 +15865,39 @@ virDomainPanicDefCheckABIStability(virDomainPanicDefPtr src,
>      return virDomainDeviceInfoCheckABIStability(&src->info, &dst->info);
>  }
> 
> +static bool
> +virDomainMemoryDefCheckABIStability(virDomainMemoryDefPtr src,
> +                                    virDomainMemoryDefPtr dst)
> +{
> +    if (src->model != dst->model) {
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                       _("Target memory device model '%s' "
> +                         "doesn't match source model '%s'"),
> +                       virDomainMemoryModelTypeToString(dst->model),
> +                       virDomainMemoryModelTypeToString(src->model));
> +        return false;
> +    }
> +
> +    if (src->targetNode != dst->targetNode) {
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                       _("Target memory device targetNode '%d' "
> +                         "doesn't match source targetNode '%d'"),
> +                       dst->targetNode, src->targetNode);
> +        return false;
> +    }
> +
> +    if (src->size != dst->size) {
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                       _("Target memory device size '%llu' doesn't match "
> +                         "source memory device size '%llu'"),
> +                       dst->size, src->size);
> +        return false;
> +    }
> +
> +    return virDomainDeviceInfoCheckABIStability(&src->info, &dst->info);
> +}
> +
> +
>  /* This compares two configurations and looks for any differences
>   * which will affect the guest ABI. This is primarily to allow
>   * validation of custom XML config passed in during migration
> @@ -16114,6 +16335,18 @@ virDomainDefCheckABIStability(virDomainDefPtr src,
>          goto error;
>      }
> 
> +    if (src->nmems != dst->nmems) {
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                       _("Target domain memory device count %zu "
> +                         "does not match source %zu"), dst->nmems, src->nmems);
> +        goto error;
> +    }
> +
> +    for (i = 0; i < src->nmems; i++) {
> +        if (!virDomainMemoryDefCheckABIStability(src->mems[i], dst->mems[i]))
> +            goto error;
> +    }
> +
>      /* Coverity is not very happy with this - all dead_error_condition */
>  #if !STATIC_ANALYSIS
>      /* This switch statement is here to trigger compiler warning when adding
> @@ -16145,6 +16378,7 @@ virDomainDefCheckABIStability(virDomainDefPtr src,
>      case VIR_DOMAIN_DEVICE_TPM:
>      case VIR_DOMAIN_DEVICE_PANIC:
>      case VIR_DOMAIN_DEVICE_SHMEM:
> +    case VIR_DOMAIN_DEVICE_MEMORY:
>          break;
>      }
>  #endif
> @@ -18616,6 +18850,81 @@ virDomainRNGDefFree(virDomainRNGDefPtr def)
>      VIR_FREE(def);
>  }
> 
> +
> +static int
> +virDomainMemorySourceDefFormat(virBufferPtr buf,
> +                               virDomainMemoryDefPtr def)
> +{
> +    char *bitmap = NULL;
> +    int ret = -1;
> +
> +    if (!def->pagesize && !def->sourceNodes)
> +        return 0;
> +
> +    virBufferAddLit(buf, "<source>\n");
> +    virBufferAdjustIndent(buf, 2);
> +
> +    if (def->sourceNodes) {
> +        if (!(bitmap = virBitmapFormat(def->sourceNodes)))
> +            goto cleanup;
> +
> +        virBufferAsprintf(buf, "<nodemask>%s</nodemask>\n", bitmap);
> +    }
> +
> +    if (def->pagesize)
> +        virBufferAsprintf(buf, "<pagesize unit='KiB'>%llu</pagesize>\n",
> +                          def->pagesize);
> +
> +    virBufferAdjustIndent(buf, -2);
> +    virBufferAddLit(buf, "</source>\n");
> +
> +    ret = 0;
> +
> + cleanup:
> +    VIR_FREE(bitmap);
> +    return ret;
> +}
> +
> +
> +static void
> +virDomainMemoryTargetDefFormat(virBufferPtr buf,
> +                               virDomainMemoryDefPtr def)
> +{
> +    virBufferAddLit(buf, "<target>\n");
> +    virBufferAdjustIndent(buf, 2);
> +
> +    virBufferAsprintf(buf, "<size unit='KiB'>%llu</size>\n", def->size);
> +    virBufferAsprintf(buf, "<node>%d</node>\n", def->targetNode);
> +
> +    virBufferAdjustIndent(buf, -2);
> +    virBufferAddLit(buf, "</target>\n");
> +}
> +
> +static int
> +virDomainMemoryDefFormat(virBufferPtr buf,
> +                         virDomainMemoryDefPtr def,
> +                         unsigned int flags)
> +{
> +    const char *model = virDomainMemoryModelTypeToString(def->model);
> +
> +    virBufferAsprintf(buf, "<memory model='%s'>\n", model);
> +    virBufferAdjustIndent(buf, 2);
> +
> +    if (virDomainMemorySourceDefFormat(buf, def) < 0)
> +        return -1;
> +
> +    virDomainMemoryTargetDefFormat(buf, def);
> +
> +    if (virDomainDeviceInfoNeedsFormat(&def->info, flags)) {
> +        if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0)
> +            return -1;
> +    }
> +
> +    virBufferAdjustIndent(buf, -2);
> +    virBufferAddLit(buf, "</memory>\n");
> +    return 0;
> +}
> +
>  static void
>  virDomainVideoAccelDefFormat(virBufferPtr buf,
>                               virDomainVideoAccelDefPtr def)
> @@ -20168,6 +20477,10 @@ virDomainDefFormatInternal(virDomainDefPtr def,
>          if (virDomainShmemDefFormat(buf, def->shmems[n], flags) < 0)
>              goto error;
> 
> +    for (n = 0; n < def->nmems; n++)
> +        if (virDomainMemoryDefFormat(buf, def->mems[n], flags) < 0)
> +            goto error;
> +
>      virBufferAdjustIndent(buf, -2);
>      virBufferAddLit(buf, "</devices>\n");
> 
> @@ -21570,6 +21883,8 @@ virDomainDeviceDefCopy(virDomainDeviceDefPtr src,
>          break;
>      case VIR_DOMAIN_DEVICE_PANIC:
>          rc = virDomainPanicDefFormat(&buf, src->data.panic);

Coverity found a missing break here


John

> +    case VIR_DOMAIN_DEVICE_MEMORY:
> +        rc = virDomainMemoryDefFormat(&buf, src->data.memory, flags);
>          break;
>      case VIR_DOMAIN_DEVICE_NONE:
>      case VIR_DOMAIN_DEVICE_SMARTCARD:




More information about the libvir-list mailing list