]> xenbits.xensource.com Git - libvirt.git/commitdiff
nodedev: add an active config to mdev
authorBoris Fiuczynski <fiuczy@linux.ibm.com>
Thu, 22 Feb 2024 13:02:01 +0000 (14:02 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Mon, 26 Feb 2024 09:59:47 +0000 (10:59 +0100)
The configuration of a defined mdev can be modified after the mdev is
started. The defined configuration and the active configuration can
therefore run out of sync. Handle this by storing the modifiable data
which is the mdev type and attributes in two separate active and
defined configurations. mdevctl supports with callout scripts to do an
attribute retrieval of started mdevs which is already implemented in
libvirt.

Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Jonathon Jongsma <jjongsma@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
18 files changed:
include/libvirt/libvirt-nodedev.h
src/conf/node_device_conf.c
src/conf/node_device_conf.h
src/libvirt-nodedev.c
src/node_device/node_device_driver.c
src/node_device/node_device_driver.h
src/node_device/node_device_udev.c
src/test/test_driver.c
tests/nodedevmdevctltest.c
tests/nodedevschemadata/mdev_c60cc60c_c60c_c60c_c60c_c60cc60cc60c.xml [new file with mode: 0644]
tests/nodedevxml2xmlout/mdev_3627463d_b7f0_4fea_b468_f1da537d301b_inactive.xml [new symlink]
tests/nodedevxml2xmlout/mdev_c60cc60c_c60c_c60c_c60c_c60cc60cc60c.xml [new file with mode: 0644]
tests/nodedevxml2xmlout/mdev_c60cc60c_c60c_c60c_c60c_c60cc60cc60c_inactive.xml [new file with mode: 0644]
tests/nodedevxml2xmlout/mdev_d069d019_36ea_4111_8f0a_8c9a70e21366_inactive.xml [new symlink]
tests/nodedevxml2xmlout/mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9_inactive.xml [new symlink]
tests/nodedevxml2xmlout/mdev_ee0b88c4_f554_4dc1_809d_b2a01e8e48ad_inactive.xml [new file with mode: 0644]
tests/nodedevxml2xmlout/mdev_fedc4916_1ca8_49ac_b176_871d16c13076_inactive.xml [new symlink]
tests/nodedevxml2xmltest.c

index 428b0d722fdb6b91119de6173cf880d96776e94f..53ffce6c6926c4bad6aff507ec32578d2950b619 100644 (file)
@@ -117,6 +117,17 @@ int                     virNodeDeviceListCaps    (virNodeDevicePtr dev,
                                                   char **const names,
                                                   int maxnames);
 
+/**
+ * virNodeDeviceXMLFlags:
+ *
+ * Flags used to provide the state of the returned node device configuration.
+ *
+ * Since: 10.1.0
+ */
+typedef enum {
+    VIR_NODE_DEVICE_XML_INACTIVE            = 1 << 0, /* dump inactive device configuration (Since: 10.1.0) */
+} virNodeDeviceXMLFlags;
+
 char *                  virNodeDeviceGetXMLDesc (virNodeDevicePtr dev,
                                                  unsigned int flags);
 
index febc58afd1e8ae2641b36f1a5bb978cc7ccc1e31..48140b17baa57e94e8064ea14f33c8c2abf651ee 100644 (file)
@@ -602,16 +602,22 @@ virNodeDeviceCapMdevAttrFormat(virBuffer *buf,
 
 static void
 virNodeDeviceCapMdevDefFormat(virBuffer *buf,
-                              const virNodeDevCapData *data)
+                              const virNodeDevCapData *data,
+                              bool defined)
 {
-    virBufferEscapeString(buf, "<type id='%s'/>\n", data->mdev.dev_config.type);
+    if (defined)
+        virBufferEscapeString(buf, "<type id='%s'/>\n", data->mdev.defined_config.type);
+    else
+        virBufferEscapeString(buf, "<type id='%s'/>\n", data->mdev.active_config.type);
     virBufferEscapeString(buf, "<uuid>%s</uuid>\n", data->mdev.uuid);
     virBufferEscapeString(buf, "<parent_addr>%s</parent_addr>\n",
                           data->mdev.parent_addr);
     virBufferAsprintf(buf, "<iommuGroup number='%u'/>\n",
                       data->mdev.iommuGroupNumber);
-
-    virNodeDeviceCapMdevAttrFormat(buf, &data->mdev.dev_config);
+    if (defined)
+        virNodeDeviceCapMdevAttrFormat(buf, &data->mdev.defined_config);
+    else
+        virNodeDeviceCapMdevAttrFormat(buf, &data->mdev.active_config);
 }
 
 static void
@@ -662,25 +668,29 @@ virNodeDeviceCapCSSDefFormat(virBuffer *buf,
 
 
 char *
-virNodeDeviceDefFormat(const virNodeDeviceDef *def)
+virNodeDeviceDefFormat(const virNodeDeviceDef *def, unsigned int flags)
 {
     g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
     virNodeDevCapsDef *caps;
     size_t i = 0;
+    bool inactive_state = flags & VIR_NODE_DEVICE_XML_INACTIVE;
 
     virBufferAddLit(&buf, "<device>\n");
     virBufferAdjustIndent(&buf, 2);
     virBufferEscapeString(&buf, "<name>%s</name>\n", def->name);
-    virBufferEscapeString(&buf, "<path>%s</path>\n", def->sysfs_path);
-    virBufferEscapeString(&buf, "<devnode type='dev'>%s</devnode>\n",
-                          def->devnode);
-    if (def->devlinks) {
-        for (i = 0; def->devlinks[i]; i++)
-            virBufferEscapeString(&buf, "<devnode type='link'>%s</devnode>\n",
-                                  def->devlinks[i]);
+    if (!inactive_state) {
+        virBufferEscapeString(&buf, "<path>%s</path>\n", def->sysfs_path);
+        virBufferEscapeString(&buf, "<devnode type='dev'>%s</devnode>\n",
+                              def->devnode);
+        if (def->devlinks) {
+            for (i = 0; def->devlinks[i]; i++) {
+                virBufferEscapeString(&buf, "<devnode type='link'>%s</devnode>\n",
+                                      def->devlinks[i]);
+            }
+        }
     }
     virBufferEscapeString(&buf, "<parent>%s</parent>\n", def->parent);
-    if (def->driver) {
+    if (def->driver && !inactive_state) {
         virBufferAddLit(&buf, "<driver>\n");
         virBufferAdjustIndent(&buf, 2);
         virBufferEscapeString(&buf, "<name>%s</name>\n", def->driver);
@@ -741,7 +751,7 @@ virNodeDeviceDefFormat(const virNodeDeviceDef *def)
             virBufferEscapeString(&buf, "<type>%s</type>\n", virNodeDevDRMTypeToString(data->drm.type));
             break;
         case VIR_NODE_DEV_CAP_MDEV:
-            virNodeDeviceCapMdevDefFormat(&buf, data);
+            virNodeDeviceCapMdevDefFormat(&buf, data, inactive_state);
             break;
         case VIR_NODE_DEV_CAP_CCW_DEV:
             virNodeDeviceCapCCWDefFormat(&buf, data);
@@ -2207,7 +2217,7 @@ virNodeDevCapMdevParseXML(xmlXPathContextPtr ctxt,
 
     ctxt->node = node;
 
-    if (!(mdev->dev_config.type = virXPathString("string(./type[1]/@id)", ctxt))) {
+    if (!(mdev->defined_config.type = virXPathString("string(./type[1]/@id)", ctxt))) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("missing type id attribute for '%1$s'"), def->name);
         return -1;
@@ -2239,7 +2249,7 @@ virNodeDevCapMdevParseXML(xmlXPathContextPtr ctxt,
         return -1;
 
     for (i = 0; i < nattrs; i++)
-        virNodeDevCapMdevAttributeParseXML(ctxt, attrs[i], &mdev->dev_config);
+        virNodeDevCapMdevAttributeParseXML(ctxt, attrs[i], &mdev->defined_config);
 
     return 0;
 }
@@ -2582,11 +2592,15 @@ virNodeDevCapsDefFree(virNodeDevCapsDef *caps)
         g_free(data->sg.path);
         break;
     case VIR_NODE_DEV_CAP_MDEV:
-        g_free(data->mdev.dev_config.type);
+        g_free(data->mdev.defined_config.type);
+        g_free(data->mdev.active_config.type);
         g_free(data->mdev.uuid);
-        for (i = 0; i < data->mdev.dev_config.nattributes; i++)
-            virMediatedDeviceAttrFree(data->mdev.dev_config.attributes[i]);
-        g_free(data->mdev.dev_config.attributes);
+        for (i = 0; i < data->mdev.defined_config.nattributes; i++)
+            virMediatedDeviceAttrFree(data->mdev.defined_config.attributes[i]);
+        g_free(data->mdev.defined_config.attributes);
+        for (i = 0; i < data->mdev.active_config.nattributes; i++)
+            virMediatedDeviceAttrFree(data->mdev.active_config.attributes[i]);
+        g_free(data->mdev.active_config.attributes);
         g_free(data->mdev.parent_addr);
         break;
     case VIR_NODE_DEV_CAP_CSS_DEV:
index f100496272cf81e884a23900d750e4b64864476c..f59440dbb9c7dffd146c45ff14fb715f0cbf20e4 100644 (file)
@@ -153,7 +153,8 @@ typedef struct _virNodeDevCapMdev virNodeDevCapMdev;
 struct _virNodeDevCapMdev {
     unsigned int iommuGroupNumber;
     char *uuid;
-    virMediatedDeviceConfig dev_config;
+    virMediatedDeviceConfig defined_config;
+    virMediatedDeviceConfig active_config;
     char *parent_addr;
     bool autostart;
 };
@@ -360,7 +361,7 @@ struct _virNodeDeviceDef {
 };
 
 char *
-virNodeDeviceDefFormat(const virNodeDeviceDef *def);
+virNodeDeviceDefFormat(const virNodeDeviceDef *def, unsigned int flags);
 
 
 typedef int (*virNodeDeviceDefPostParseCallback)(virNodeDeviceDef *dev,
index f0f99bc020bc109dc7f5898856d2e9db9502f86c..c683b2eef945a65fda5302e72c0fb243feee7f29 100644 (file)
@@ -264,7 +264,7 @@ virNodeDeviceLookupSCSIHostByWWN(virConnectPtr conn,
 /**
  * virNodeDeviceGetXMLDesc:
  * @dev: pointer to the node device
- * @flags: extra flags; not used yet, so callers should always pass 0
+ * @flags: bitwise-OR of virNodeDeviceXMLFlags
  *
  * Fetch an XML document describing all aspects of
  * the device.
index 57b87d02ac6cc9522b7f3a96e0745b9103052b31..37465da3a609533d8576548cb145d8ae0ffd001f 100644 (file)
@@ -338,7 +338,7 @@ nodeDeviceGetXMLDesc(virNodeDevicePtr device,
     virNodeDeviceDef *def;
     char *ret = NULL;
 
-    virCheckFlags(0, NULL);
+    virCheckFlags(VIR_NODE_DEVICE_XML_INACTIVE, NULL);
 
     if (nodeDeviceInitWait() < 0)
         return NULL;
@@ -356,7 +356,19 @@ nodeDeviceGetXMLDesc(virNodeDevicePtr device,
     if (virNodeDeviceUpdateCaps(def) < 0)
         goto cleanup;
 
-    ret = virNodeDeviceDefFormat(def);
+    if (flags & VIR_NODE_DEVICE_XML_INACTIVE) {
+        if (!virNodeDeviceObjIsPersistent(obj)) {
+            virReportError(VIR_ERR_OPERATION_INVALID,
+                           _("node device '%1$s' is not persistent"),
+                           def->name);
+            goto cleanup;
+        }
+    } else {
+        if (!virNodeDeviceObjIsActive(obj))
+            flags |= VIR_NODE_DEVICE_XML_INACTIVE;
+    }
+
+    ret = virNodeDeviceDefFormat(def, flags);
 
  cleanup:
     virNodeDeviceObjEndAPI(&obj);
@@ -629,19 +641,20 @@ nodeDeviceAttributesToJSON(virJSONValue *json,
 /* format a json string that provides configuration information about this mdev
  * to the mdevctl utility */
 static int
-nodeDeviceDefToMdevctlConfig(virNodeDeviceDef *def, char **buf)
+nodeDeviceDefToMdevctlConfig(virNodeDeviceDef *def, char **buf, bool defined)
 {
     virNodeDevCapMdev *mdev = &def->caps->data.mdev;
+    virMediatedDeviceConfig *mdev_config = defined ? &mdev->defined_config : &mdev->active_config;
     g_autoptr(virJSONValue) json = virJSONValueNewObject();
     const char *startval = mdev->autostart ? "auto" : "manual";
 
-    if (virJSONValueObjectAppendString(json, "mdev_type", mdev->dev_config.type) < 0)
+    if (virJSONValueObjectAppendString(json, "mdev_type", mdev_config->type) < 0)
         return -1;
 
     if (virJSONValueObjectAppendString(json, "start", startval) < 0)
         return -1;
 
-    if (nodeDeviceAttributesToJSON(json, &mdev->dev_config) < 0)
+    if (nodeDeviceAttributesToJSON(json, mdev_config) < 0)
         return -1;
 
     *buf = virJSONValueToString(json, false);
@@ -760,7 +773,7 @@ nodeDeviceGetMdevctlCommand(virNodeDeviceDef *def,
             return NULL;
         }
 
-        if (nodeDeviceDefToMdevctlConfig(def, &inbuf) < 0) {
+        if (nodeDeviceDefToMdevctlConfig(def, &inbuf, true) < 0) {
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                            _("couldn't convert node device def to mdevctl JSON"));
             return NULL;
@@ -1139,9 +1152,11 @@ nodeDeviceParseMdevctlAttributes(virMediatedDeviceConfig *config,
 
 static virNodeDeviceDef*
 nodeDeviceParseMdevctlChildDevice(const char *parent,
-                                  virJSONValue *json)
+                                  virJSONValue *json,
+                                  bool defined)
 {
     virNodeDevCapMdev *mdev;
+    virMediatedDeviceConfig *mdev_config;
     const char *uuid;
     virJSONValue *props;
     g_autoptr(virNodeDeviceDef) child = g_new0(virNodeDeviceDef, 1);
@@ -1171,14 +1186,15 @@ nodeDeviceParseMdevctlChildDevice(const char *parent,
     child->caps->data.type = VIR_NODE_DEV_CAP_MDEV;
 
     mdev = &child->caps->data.mdev;
+    mdev_config = defined ? &mdev->defined_config : &mdev->active_config;
     mdev->uuid = g_strdup(uuid);
     mdev->parent_addr = g_strdup(parent);
-    mdev->dev_config.type =
+    mdev_config->type =
         g_strdup(virJSONValueObjectGetString(props, "mdev_type"));
     start = virJSONValueObjectGetString(props, "start");
     mdev->autostart = STREQ_NULLABLE(start, "auto");
 
-    if (nodeDeviceParseMdevctlAttributes(&mdev->dev_config,
+    if (nodeDeviceParseMdevctlAttributes(mdev_config,
                                          virJSONValueObjectGet(props, "attrs")) < 0)
         return NULL;
 
@@ -1190,7 +1206,8 @@ nodeDeviceParseMdevctlChildDevice(const char *parent,
 
 int
 nodeDeviceParseMdevctlJSON(const char *jsonstring,
-                           virNodeDeviceDef ***devs)
+                           virNodeDeviceDef ***devs,
+                           bool defined)
 {
     int n;
     g_autoptr(virJSONValue) json_devicelist = NULL;
@@ -1260,7 +1277,7 @@ nodeDeviceParseMdevctlJSON(const char *jsonstring,
             g_autoptr(virNodeDeviceDef) child = NULL;
             virJSONValue *child_obj = virJSONValueArrayGet(child_array, j);
 
-            if (!(child = nodeDeviceParseMdevctlChildDevice(parent, child_obj))) {
+            if (!(child = nodeDeviceParseMdevctlChildDevice(parent, child_obj, defined))) {
                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                _("Unable to parse child device"));
                 goto error;
@@ -1403,7 +1420,7 @@ nodeDeviceUpdateMediatedDevice(virNodeDeviceDef *def,
         /* Active devices contain some additional information (e.g. sysfs
          * path) that is not provided by mdevctl, so re-use the existing
          * definition and copy over new mdev data */
-        changed = nodeDeviceDefCopyFromMdevctl(olddef, owned);
+        changed = nodeDeviceDefCopyFromMdevctl(olddef, owned, defined);
 
         if (was_defined && !changed) {
             /* if this device was already defined and the definition
@@ -1673,7 +1690,7 @@ virMdevctlList(bool defined,
         return -1;
     }
 
-    return nodeDeviceParseMdevctlJSON(output, devs);
+    return nodeDeviceParseMdevctlJSON(output, devs, defined);
 }
 
 
@@ -1830,16 +1847,24 @@ virMediatedDeviceAttrsCopy(virMediatedDeviceConfig *dst_config,
  * Returns true if anything was copied, else returns false */
 bool
 nodeDeviceDefCopyFromMdevctl(virNodeDeviceDef *dst,
-                             virNodeDeviceDef *src)
+                             virNodeDeviceDef *src,
+                             bool defined)
 {
     bool ret = false;
     virNodeDevCapMdev *srcmdev = &src->caps->data.mdev;
     virNodeDevCapMdev *dstmdev = &dst->caps->data.mdev;
+    virMediatedDeviceConfig *srcmdevconfig = &src->caps->data.mdev.active_config;
+    virMediatedDeviceConfig *dstmdevconfig = &dst->caps->data.mdev.active_config;
+
+    if (defined) {
+        srcmdevconfig = &src->caps->data.mdev.defined_config;
+        dstmdevconfig = &dst->caps->data.mdev.defined_config;
+    }
 
-    if (STRNEQ_NULLABLE(dstmdev->dev_config.type, srcmdev->dev_config.type)) {
+    if (STRNEQ_NULLABLE(dstmdevconfig->type, srcmdevconfig->type)) {
         ret = true;
-        g_free(dstmdev->dev_config.type);
-        dstmdev->dev_config.type = g_strdup(srcmdev->dev_config.type);
+        g_free(dstmdevconfig->type);
+        dstmdevconfig->type = g_strdup(srcmdevconfig->type);
     }
 
     if (STRNEQ_NULLABLE(dstmdev->uuid, srcmdev->uuid)) {
@@ -1848,7 +1873,7 @@ nodeDeviceDefCopyFromMdevctl(virNodeDeviceDef *dst,
         dstmdev->uuid = g_strdup(srcmdev->uuid);
     }
 
-    if (virMediatedDeviceAttrsCopy(&dstmdev->dev_config, &srcmdev->dev_config))
+    if (virMediatedDeviceAttrsCopy(dstmdevconfig, srcmdevconfig))
         ret = true;
 
     if (dstmdev->autostart != srcmdev->autostart) {
index c7d5e22daf6af8e60f3c404560ec679d468fa624..4dce7e6f17495784421be935d26b13e3b63bc9ee 100644 (file)
@@ -142,7 +142,8 @@ nodeDeviceGetMdevctlListCommand(bool defined,
 
 int
 nodeDeviceParseMdevctlJSON(const char *jsonstring,
-                           virNodeDeviceDef ***devs);
+                           virNodeDeviceDef ***devs,
+                           bool defined);
 
 int
 nodeDeviceUpdateMediatedDevices(void);
@@ -154,7 +155,8 @@ nodeDeviceGenerateName(virNodeDeviceDef *def,
                        const char *s);
 
 bool nodeDeviceDefCopyFromMdevctl(virNodeDeviceDef *dst,
-                                  virNodeDeviceDef *src);
+                                  virNodeDeviceDef *src,
+                                  bool defined);
 
 int
 nodeDeviceCreate(virNodeDevice *dev,
index 254e802c50994b09b6975e5b589d2a996ab6985b..57368a96c3054b31549531ed0b9495eabb39d428 100644 (file)
@@ -1069,7 +1069,7 @@ udevProcessMediatedDevice(struct udev_device *dev,
         return -1;
     }
 
-    data->dev_config.type = g_path_get_basename(canonicalpath);
+    data->active_config.type = g_path_get_basename(canonicalpath);
 
     data->uuid = g_strdup(udev_device_get_sysname(dev));
     if ((iommugrp = virMediatedDeviceGetIOMMUGroupNum(data->uuid)) < 0)
@@ -1572,7 +1572,7 @@ udevAddOneDevice(struct udev_device *device)
         objdef = virNodeDeviceObjGetDef(obj);
 
         if (is_mdev)
-            nodeDeviceDefCopyFromMdevctl(def, objdef);
+            nodeDeviceDefCopyFromMdevctl(def, objdef, false);
 
         persistent = virNodeDeviceObjIsPersistent(obj);
         autostart = virNodeDeviceObjIsAutostart(obj);
index ed545848afcd21e68c54724f62dea761e97dc7ce..ed0cdc0dabe8bc1a54f94aec1c90e5788d922f2f 100644 (file)
@@ -7514,12 +7514,12 @@ testNodeDeviceGetXMLDesc(virNodeDevicePtr dev,
     virNodeDeviceObj *obj;
     char *ret = NULL;
 
-    virCheckFlags(0, NULL);
+    virCheckFlags(VIR_NODE_DEVICE_XML_INACTIVE, NULL);
 
     if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
         return NULL;
 
-    ret = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(obj));
+    ret = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(obj), flags);
 
     virNodeDeviceObjEndAPI(&obj);
     return ret;
@@ -7619,7 +7619,7 @@ testNodeDeviceMockCreateVport(testDriver *driver,
                                                    "scsi_host11")))
         goto cleanup;
 
-    xml = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(objcopy));
+    xml = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(objcopy), 0);
     virNodeDeviceObjEndAPI(&objcopy);
     if (!xml)
         goto cleanup;
index e403328e5aedc4eb78ac1dddc91a87f057496ba2..f49d66846128dcf9cd5125ce631b4089d3a6803f 100644 (file)
@@ -229,13 +229,13 @@ testMdevctlParse(const void *data)
         return -1;
     }
 
-    if ((nmdevs = nodeDeviceParseMdevctlJSON(buf, &mdevs)) < 0) {
+    if ((nmdevs = nodeDeviceParseMdevctlJSON(buf, &mdevs, true)) < 0) {
         VIR_TEST_DEBUG("Unable to parse json for %s", filename);
         return -1;
     }
 
     for (i = 0; i < nmdevs; i++) {
-        g_autofree char *devxml = virNodeDeviceDefFormat(mdevs[i]);
+        g_autofree char *devxml = virNodeDeviceDefFormat(mdevs[i], VIR_NODE_DEVICE_XML_INACTIVE);
         if (!devxml)
             goto cleanup;
         virBufferAddStr(&xmloutbuf, devxml);
diff --git a/tests/nodedevschemadata/mdev_c60cc60c_c60c_c60c_c60c_c60cc60cc60c.xml b/tests/nodedevschemadata/mdev_c60cc60c_c60c_c60c_c60c_c60cc60cc60c.xml
new file mode 100644 (file)
index 0000000..6926559
--- /dev/null
@@ -0,0 +1,14 @@
+<device>
+  <name>mdev_c60cc60c_c60c_c60c_c60c_c60cc60cc60c_0_0_0052</name>
+  <path>/sys/devices/css0/0.0.0052/c60cc60c-c60c-c60c-c60c-c60cc60cc60c</path>
+  <parent>css_0_0_0052</parent>
+  <driver>
+    <name>vfio_ccw_mdev</name>
+  </driver>
+  <capability type='mdev'>
+    <type id='vfio_ccw-io'/>
+    <uuid>c60cc60c-c60c-c60c-c60c-c60cc60cc60c</uuid>
+    <parent_addr>0.0.0052</parent_addr>
+    <iommuGroup number='4'/>
+  </capability>
+</device>
diff --git a/tests/nodedevxml2xmlout/mdev_3627463d_b7f0_4fea_b468_f1da537d301b_inactive.xml b/tests/nodedevxml2xmlout/mdev_3627463d_b7f0_4fea_b468_f1da537d301b_inactive.xml
new file mode 120000 (symlink)
index 0000000..f8ec7d8
--- /dev/null
@@ -0,0 +1 @@
+mdev_3627463d_b7f0_4fea_b468_f1da537d301b.xml
\ No newline at end of file
diff --git a/tests/nodedevxml2xmlout/mdev_c60cc60c_c60c_c60c_c60c_c60cc60cc60c.xml b/tests/nodedevxml2xmlout/mdev_c60cc60c_c60c_c60c_c60c_c60cc60cc60c.xml
new file mode 100644 (file)
index 0000000..82c60cc
--- /dev/null
@@ -0,0 +1,10 @@
+<device>
+  <name>mdev_c60cc60c_c60c_c60c_c60c_c60cc60cc60c_0_0_0052</name>
+  <path>/sys/devices/css0/0.0.0052/c60cc60c-c60c-c60c-c60c-c60cc60cc60c</path>
+  <parent>css_0_0_0052</parent>
+  <capability type='mdev'>
+    <type id='vfio_ccw-io'/>
+    <uuid>c60cc60c-c60c-c60c-c60c-c60cc60cc60c</uuid>
+    <iommuGroup number='4'/>
+  </capability>
+</device>
diff --git a/tests/nodedevxml2xmlout/mdev_c60cc60c_c60c_c60c_c60c_c60cc60cc60c_inactive.xml b/tests/nodedevxml2xmlout/mdev_c60cc60c_c60c_c60c_c60c_c60cc60cc60c_inactive.xml
new file mode 100644 (file)
index 0000000..87c5ed1
--- /dev/null
@@ -0,0 +1,9 @@
+<device>
+  <name>mdev_c60cc60c_c60c_c60c_c60c_c60cc60cc60c_0_0_0052</name>
+  <parent>css_0_0_0052</parent>
+  <capability type='mdev'>
+    <type id='vfio_ccw-io'/>
+    <uuid>c60cc60c-c60c-c60c-c60c-c60cc60cc60c</uuid>
+    <iommuGroup number='4'/>
+  </capability>
+</device>
diff --git a/tests/nodedevxml2xmlout/mdev_d069d019_36ea_4111_8f0a_8c9a70e21366_inactive.xml b/tests/nodedevxml2xmlout/mdev_d069d019_36ea_4111_8f0a_8c9a70e21366_inactive.xml
new file mode 120000 (symlink)
index 0000000..f6d5789
--- /dev/null
@@ -0,0 +1 @@
+mdev_d069d019_36ea_4111_8f0a_8c9a70e21366.xml
\ No newline at end of file
diff --git a/tests/nodedevxml2xmlout/mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9_inactive.xml b/tests/nodedevxml2xmlout/mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9_inactive.xml
new file mode 120000 (symlink)
index 0000000..233a750
--- /dev/null
@@ -0,0 +1 @@
+mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9.xml
\ No newline at end of file
diff --git a/tests/nodedevxml2xmlout/mdev_ee0b88c4_f554_4dc1_809d_b2a01e8e48ad_inactive.xml b/tests/nodedevxml2xmlout/mdev_ee0b88c4_f554_4dc1_809d_b2a01e8e48ad_inactive.xml
new file mode 100644 (file)
index 0000000..8c4983f
--- /dev/null
@@ -0,0 +1,8 @@
+<device>
+  <name>mdev_ee0b88c4-f554-4dc1-809d-b2a01e8e48ad</name>
+  <parent>ap_matrix</parent>
+  <capability type='mdev'>
+    <type id='vfio_ap-passthrough'/>
+    <iommuGroup number='0'/>
+  </capability>
+</device>
diff --git a/tests/nodedevxml2xmlout/mdev_fedc4916_1ca8_49ac_b176_871d16c13076_inactive.xml b/tests/nodedevxml2xmlout/mdev_fedc4916_1ca8_49ac_b176_871d16c13076_inactive.xml
new file mode 120000 (symlink)
index 0000000..e053844
--- /dev/null
@@ -0,0 +1 @@
+mdev_fedc4916_1ca8_49ac_b176_871d16c13076.xml
\ No newline at end of file
index 068ec6876909200d056f52b3e66723fdffc5752d..e9189226729642910be45153ea6acf125221f69f 100644 (file)
 
 #define VIR_FROM_THIS VIR_FROM_NONE
 
+struct TestData {
+    const char *filename;
+    unsigned int flags;
+};
+
 static int
-testCompareXMLToXMLFiles(const char *xml, const char *outfile)
+testCompareXMLToXMLFiles(const char *xml, const char *outfile, unsigned int flags)
 {
     g_autofree char *xmlData = NULL;
     g_autofree char *actual = NULL;
     int ret = -1;
     virNodeDeviceDef *dev = NULL;
     virNodeDevCapsDef *caps;
+    size_t i;
 
     if (virTestLoadFile(xml, &xmlData) < 0)
         goto fail;
@@ -46,9 +52,23 @@ testCompareXMLToXMLFiles(const char *xml, const char *outfile)
                                            data->storage.logical_block_size;
             }
         }
+
+        if (caps->data.type == VIR_NODE_DEV_CAP_MDEV &&
+            !(flags & VIR_NODE_DEVICE_XML_INACTIVE)) {
+            data->mdev.active_config.type = g_strdup(data->mdev.defined_config.type);
+            for (i = 0; i < data->mdev.defined_config.nattributes; i++) {
+                g_autoptr(virMediatedDeviceAttr) attr = g_new0(virMediatedDeviceAttr, 1);
+
+                attr->name = g_strdup(data->mdev.defined_config.attributes[i]->name);
+                attr->value = g_strdup(data->mdev.defined_config.attributes[i]->value);
+                VIR_APPEND_ELEMENT(data->mdev.active_config.attributes,
+                                   data->mdev.active_config.nattributes,
+                                   attr);
+            }
+        }
     }
 
-    if (!(actual = virNodeDeviceDefFormat(dev)))
+    if (!(actual = virNodeDeviceDefFormat(dev, flags)))
         goto fail;
 
     if (virTestCompareToFile(actual, outfile) < 0)
@@ -65,16 +85,21 @@ static int
 testCompareXMLToXMLHelper(const void *data)
 {
     int result = -1;
+    const struct TestData *tdata = data;
     g_autofree char *xml = NULL;
     g_autofree char *outfile = NULL;
 
     xml = g_strdup_printf("%s/nodedevschemadata/%s.xml", abs_srcdir,
-                          (const char *)data);
+                          tdata->filename);
 
-    outfile = g_strdup_printf("%s/nodedevxml2xmlout/%s.xml", abs_srcdir,
-                              (const char *)data);
+    if (tdata->flags & VIR_NODE_DEVICE_XML_INACTIVE)
+        outfile = g_strdup_printf("%s/nodedevxml2xmlout/%s_inactive.xml", abs_srcdir,
+                                  tdata->filename);
+    else
+        outfile = g_strdup_printf("%s/nodedevxml2xmlout/%s.xml", abs_srcdir,
+                                  tdata->filename);
 
-    result = testCompareXMLToXMLFiles(xml, outfile);
+    result = testCompareXMLToXMLFiles(xml, outfile, tdata->flags);
 
     return result;
 }
@@ -85,10 +110,20 @@ mymain(void)
 {
     int ret = 0;
 
+#define DO_TEST_FLAGS(desc, filename, flags) \
+    do { \
+        struct TestData data = { filename, flags }; \
+        if (virTestRun(desc, testCompareXMLToXMLHelper, &data) < 0) \
+            ret = -1; \
+       } \
+    while (0)
+
 #define DO_TEST(name) \
-    if (virTestRun("Node device XML-2-XML " name, \
-                   testCompareXMLToXMLHelper, (name)) < 0) \
-        ret = -1
+    DO_TEST_FLAGS("Node device XML-2-XML " name, name, 0)
+
+#define DO_TEST_INACTIVE(name) \
+    DO_TEST_FLAGS("Node device XML-2-XML INACTIVE " name, \
+                  name, VIR_NODE_DEVICE_XML_INACTIVE)
 
     DO_TEST("computer");
     DO_TEST("DVD_GCC_4247N");
@@ -121,6 +156,7 @@ mymain(void)
     DO_TEST("pci_0000_02_10_7_mdev_types");
     DO_TEST("pci_0000_42_00_0_vpd");
     DO_TEST("mdev_3627463d_b7f0_4fea_b468_f1da537d301b");
+    DO_TEST_INACTIVE("mdev_3627463d_b7f0_4fea_b468_f1da537d301b");
     DO_TEST("ccw_0_0_ffff");
     DO_TEST("css_0_0_ffff");
     DO_TEST("css_0_0_ffff_channel_dev_addr");
@@ -134,7 +170,13 @@ mymain(void)
     DO_TEST("mdev_d069d019_36ea_4111_8f0a_8c9a70e21366");
     DO_TEST("mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9");
     DO_TEST("mdev_fedc4916_1ca8_49ac_b176_871d16c13076");
+    DO_TEST_INACTIVE("mdev_ee0b88c4_f554_4dc1_809d_b2a01e8e48ad");
+    DO_TEST_INACTIVE("mdev_d069d019_36ea_4111_8f0a_8c9a70e21366");
+    DO_TEST_INACTIVE("mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9");
+    DO_TEST_INACTIVE("mdev_fedc4916_1ca8_49ac_b176_871d16c13076");
     DO_TEST("hba_vport_ops");
+    DO_TEST("mdev_c60cc60c_c60c_c60c_c60c_c60cc60cc60c");
+    DO_TEST_INACTIVE("mdev_c60cc60c_c60c_c60c_c60c_c60cc60cc60c");
 
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }