nodedev: add an active config to mdev

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>
This commit is contained in:
Boris Fiuczynski 2024-02-22 14:02:01 +01:00 committed by Michal Privoznik
parent c65c078655
commit e67bca23e4
18 changed files with 199 additions and 59 deletions

View 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);

View 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:

View 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,

View 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.

View 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 (STRNEQ_NULLABLE(dstmdev->dev_config.type, srcmdev->dev_config.type)) {
if (defined) {
srcmdevconfig = &src->caps->data.mdev.defined_config;
dstmdevconfig = &dst->caps->data.mdev.defined_config;
}
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) {

View 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,

View 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);

View 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;

View 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);

View File

@ -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>

View File

@ -0,0 +1 @@
mdev_3627463d_b7f0_4fea_b468_f1da537d301b.xml

View File

@ -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>

View File

@ -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>

View File

@ -0,0 +1 @@
mdev_d069d019_36ea_4111_8f0a_8c9a70e21366.xml

View File

@ -0,0 +1 @@
mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9.xml

View File

@ -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>

View File

@ -0,0 +1 @@
mdev_fedc4916_1ca8_49ac_b176_871d16c13076.xml

View File

@ -11,14 +11,20 @@
#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;
}